From f6466a5c8f1112dd6054bb458a3527d1fbe4a3b3 Mon Sep 17 00:00:00 2001 From: Nicolas Constant Date: Sun, 14 Jun 2020 20:39:51 -0400 Subject: [PATCH] added followers retrieval --- .../user-follows/user-follows.component.html | 11 +++- .../user-follows/user-follows.component.scss | 10 ++++ .../user-follows/user-follows.component.ts | 60 ++++++++++++++++--- src/app/services/mastodon-wrapper.service.ts | 16 ++++- src/app/services/mastodon.service.ts | 23 ++++++- src/app/services/models/api.settings.ts | 2 + 6 files changed, 108 insertions(+), 14 deletions(-) diff --git a/src/app/components/stream/user-follows/user-follows.component.html b/src/app/components/stream/user-follows/user-follows.component.html index 57a86440..f91e10dd 100644 --- a/src/app/components/stream/user-follows/user-follows.component.html +++ b/src/app/components/stream/user-follows/user-follows.component.html @@ -1,3 +1,8 @@ -

- user-follows works! -

+
+ +
+ +
+
\ No newline at end of file diff --git a/src/app/components/stream/user-follows/user-follows.component.scss b/src/app/components/stream/user-follows/user-follows.component.scss index e69de29b..0a3e1427 100644 --- a/src/app/components/stream/user-follows/user-follows.component.scss +++ b/src/app/components/stream/user-follows/user-follows.component.scss @@ -0,0 +1,10 @@ +@import "variables"; +@import "commons"; + +.follow { + height: calc(100%); + width: calc(100%); + + overflow: auto; + position: relative; +} \ No newline at end of file diff --git a/src/app/components/stream/user-follows/user-follows.component.ts b/src/app/components/stream/user-follows/user-follows.component.ts index 83daf842..c5f3291a 100644 --- a/src/app/components/stream/user-follows/user-follows.component.ts +++ b/src/app/components/stream/user-follows/user-follows.component.ts @@ -1,5 +1,13 @@ import { Component, OnInit, Input, EventEmitter, Output, OnDestroy, ViewChild, ElementRef } from '@angular/core'; -import { Subscription } from 'rxjs'; +import { Subscription, Observable } from 'rxjs'; +import { Store } from '@ngxs/store'; + +import { AccountInfo } from '../../../states/accounts.state'; +import { MastodonWrapperService } from '../../../services/mastodon-wrapper.service'; +import { ToolsService } from '../../../services/tools.service'; +import { Account } from "../../../services/models/mastodon.interfaces"; + + @Component({ selector: 'app-user-follows', @@ -8,15 +16,18 @@ import { Subscription } from 'rxjs'; }) export class UserFollowsComponent implements OnInit, OnDestroy { - private _type: string; + private _type: 'follows' | 'followers'; private _currentAccount: string; + isLoading: boolean = true; + accounts: Account[] = []; + @Input('type') - set setType(type: string) { + set setType(type: 'follows' | 'followers') { this._type = type; this.load(this._type, this._currentAccount); } - get setType(): string { + get setType(): 'follows' | 'followers' { return this._type; } @@ -34,12 +45,19 @@ export class UserFollowsComponent implements OnInit, OnDestroy { @Output() browseAccountEvent = new EventEmitter(); - @ViewChild('statusstream') public statustream: ElementRef; + @ViewChild('accountslist') public accountslist: ElementRef; private refreshSubscription: Subscription; - private goToTopSubscription: Subscription; + private goToTopSubscription: Subscription; + // private accountSub: Subscription; + // private accounts$: Observable; - constructor() { } + constructor( + private readonly store: Store, + private readonly toolsService: ToolsService, + private readonly mastodonService: MastodonWrapperService) { + // this.accounts$ = this.store.select(state => state.registeredaccounts.accounts); + } ngOnInit() { if (this.refreshEventEmitter) { @@ -58,19 +76,43 @@ export class UserFollowsComponent implements OnInit, OnDestroy { ngOnDestroy(): void { if (this.refreshSubscription) this.refreshSubscription.unsubscribe(); if (this.goToTopSubscription) this.goToTopSubscription.unsubscribe(); + // if (this.accountSub) this.accountSub.unsubscribe(); } - private load(type: string, accountName: string) { + private load(type: 'follows' | 'followers', accountName: string) { if (type && accountName) { console.warn(`type: ${type} account ${accountName}`); + this.isLoading = true; + + let currentAccount = this.toolsService.getSelectedAccounts()[0]; + this.toolsService.findAccount(currentAccount, accountName) + .then((acc: Account) => { + if(type === 'followers'){ + return this.mastodonService.getFollowers(currentAccount, acc.id, null, null); + } else if(type === 'follows') { + return this.mastodonService.getFollowing(currentAccount, acc.id, null, null); + } else { + throw Error('not implemented'); + } + }) + .then((accounts: Account[]) => { + this.accounts = accounts; + }) + .catch(err => { + + }) + .then(() => { + this.isLoading = false; + }); } } refresh(): any { + this.load(this._type, this._currentAccount); } goToTop(): any { - const stream = this.statustream.nativeElement as HTMLElement; + const stream = this.accountslist.nativeElement as HTMLElement; setTimeout(() => { stream.scrollTo({ top: 0, diff --git a/src/app/services/mastodon-wrapper.service.ts b/src/app/services/mastodon-wrapper.service.ts index db2cad4e..5ace2257 100644 --- a/src/app/services/mastodon-wrapper.service.ts +++ b/src/app/services/mastodon-wrapper.service.ts @@ -11,7 +11,7 @@ import { AppInfo, RegisteredAppsStateModel } from '../states/registered-apps.sta @Injectable({ providedIn: 'root' }) -export class MastodonWrapperService { +export class MastodonWrapperService { private refreshingToken: { [id: string]: Promise } = {}; constructor( @@ -391,4 +391,18 @@ export class MastodonWrapperService { return this.mastodonService.deleteScheduledStatus(refreshedAccount, statusId); }); } + + getFollowing(account: AccountInfo, accountId: number, maxId: string, sinceId: string, limit: number = 40): Promise { + return this.refreshAccountIfNeeded(account) + .then((refreshedAccount: AccountInfo) => { + return this.mastodonService.getFollowing(refreshedAccount, accountId, maxId, sinceId, limit); + }); + } + + getFollowers(account: AccountInfo, accountId: number, maxId: string, sinceId: string, limit: number = 40): Promise { + return this.refreshAccountIfNeeded(account) + .then((refreshedAccount: AccountInfo) => { + return this.mastodonService.getFollowers(refreshedAccount, accountId, maxId, sinceId, limit); + }); + } } diff --git a/src/app/services/mastodon.service.ts b/src/app/services/mastodon.service.ts index 3f976fea..eea3530f 100644 --- a/src/app/services/mastodon.service.ts +++ b/src/app/services/mastodon.service.ts @@ -7,7 +7,7 @@ import { AccountInfo } from '../states/accounts.state'; import { StreamTypeEnum, StreamElement } from '../states/streams.state'; @Injectable() -export class MastodonService { +export class MastodonService { private apiRoutes = new ApiRoutes(); constructor(private readonly httpClient: HttpClient) { } @@ -468,6 +468,27 @@ export class MastodonService { const headers = new HttpHeaders({ 'Authorization': `Bearer ${account.token.access_token}` }); return this.httpClient.delete(route, { headers: headers }).toPromise(); } + + getFollowers(account: AccountInfo, targetAccountId: number, maxId: string = null, sinceId: string = null, limit: number = 40): Promise { + const route = `https://${account.instance}${this.apiRoutes.getFollowers}`.replace('{0}', targetAccountId.toString()); + + let params = `?limit=${limit}`; + if(maxId) params += `$max_id=${maxId}`; + if(sinceId) params += `$since_id=${sinceId}`; + + const headers = new HttpHeaders({ 'Authorization': `Bearer ${account.token.access_token}` }); + return this.httpClient.get(route + params, { headers: headers }).toPromise(); + } + getFollowing(account: AccountInfo, targetAccountId: number, maxId: string, sinceId: string, limit: number = 40): Promise { + const route = `https://${account.instance}${this.apiRoutes.getFollowing}`.replace('{0}', targetAccountId.toString()); + + let params = `?limit=${limit}`; + if(maxId) params += `$max_id=${maxId}`; + if(sinceId) params += `$since_id=${sinceId}`; + + const headers = new HttpHeaders({ 'Authorization': `Bearer ${account.token.access_token}` }); + return this.httpClient.get(route + params, { headers: headers }).toPromise(); + } } export enum VisibilityEnum { diff --git a/src/app/services/models/api.settings.ts b/src/app/services/models/api.settings.ts index c2e9dfc0..f6c28816 100644 --- a/src/app/services/models/api.settings.ts +++ b/src/app/services/models/api.settings.ts @@ -73,4 +73,6 @@ export class ApiRoutes { bookmarkingStatus = '/api/v1/statuses/{0}/bookmark'; unbookmarkingStatus = '/api/v1/statuses/{0}/unbookmark'; getBookmarks = '/api/v1/bookmarks'; + getFollowers = '/api/v1/accounts/{0}/followers'; + getFollowing = '/api/v1/accounts/{0}/following'; }