-
diff --git a/src/app/components/stream/stream-statuses/stream-statuses.component.ts b/src/app/components/stream/stream-statuses/stream-statuses.component.ts
index 64d01f45..129dc1ce 100644
--- a/src/app/components/stream/stream-statuses/stream-statuses.component.ts
+++ b/src/app/components/stream/stream-statuses/stream-statuses.component.ts
@@ -101,6 +101,8 @@ export class StreamStatusesComponent extends TimelineBase {
});
}
});
+
+ this.numNewItems = 0;
}
ngOnDestroy() {
@@ -133,6 +135,7 @@ export class StreamStatusesComponent extends TimelineBase {
private resetStream() {
this.statuses.length = 0;
this.bufferStream.length = 0;
+ this.numNewItems = 0;
if (this.websocketStreaming) this.websocketStreaming.dispose();
}
@@ -154,6 +157,7 @@ export class StreamStatusesComponent extends TimelineBase {
this.statuses.unshift(wrapper);
} else {
this.bufferStream.push(update.status);
+ this.numNewItems++;
}
}
} else if (update.type === EventEnum.delete) {
@@ -201,6 +205,7 @@ export class StreamStatusesComponent extends TimelineBase {
}
this.bufferStream.length = 0;
+ this.numNewItems = 0;
return false;
}
@@ -212,7 +217,7 @@ export class StreamStatusesComponent extends TimelineBase {
return status.filter(x => !this.isFiltered(x));
});
}
-
+
private isFiltered(status: Status): boolean {
if (this.streamElement.hideBoosts) {
if (status.reblog) {
diff --git a/src/app/components/stream/thread/thread.component.ts b/src/app/components/stream/thread/thread.component.ts
index 5bb89e22..076416fb 100644
--- a/src/app/components/stream/thread/thread.component.ts
+++ b/src/app/components/stream/thread/thread.component.ts
@@ -28,6 +28,7 @@ export class ThreadComponent extends BrowseBase {
hasContentWarnings = false;
private remoteStatusFetchingDisabled = false;
+ numNewItems: number; //html compatibility only
bufferStream: Status[] = []; //html compatibility only
streamPositionnedAtTop: boolean = true; //html compatibility only
timelineLoadingMode: TimeLineModeEnum = TimeLineModeEnum.OnTop; //html compatibility only
diff --git a/src/app/services/mastodon-wrapper.service.ts b/src/app/services/mastodon-wrapper.service.ts
index f4675380..b9a172c8 100644
--- a/src/app/services/mastodon-wrapper.service.ts
+++ b/src/app/services/mastodon-wrapper.service.ts
@@ -1,7 +1,7 @@
import { Injectable } from '@angular/core';
import { Store } from '@ngxs/store';
-import { Account, Status, Results, Context, Relationship, Instance, Attachment, Notification, List, Poll, Emoji, Conversation, ScheduledStatus, TokenData } from "./models/mastodon.interfaces";
+import { Account, Status, Results, Context, Relationship, Instance, Attachment, Notification, List, Poll, Emoji, Conversation, ScheduledStatus, TokenData, Tag } from "./models/mastodon.interfaces";
import { AccountInfo, UpdateAccount } from '../states/accounts.state';
import { StreamTypeEnum, StreamElement } from '../states/streams.state';
import { FavoriteResult, VisibilityEnum, PollParameters, MastodonService, BookmarkResult, FollowingResult } from './mastodon.service';
@@ -274,6 +274,27 @@ export class MastodonWrapperService {
});
}
+ followHashtag(currentlyUsedAccount: AccountInfo, hashtag: string): Promise
{
+ return this.refreshAccountIfNeeded(currentlyUsedAccount)
+ .then((refreshedAccount: AccountInfo) => {
+ return this.mastodonService.followHashtag(refreshedAccount, hashtag);
+ });
+ }
+
+ unfollowHashtag(currentlyUsedAccount: AccountInfo, hashtag: string): Promise {
+ return this.refreshAccountIfNeeded(currentlyUsedAccount)
+ .then((refreshedAccount: AccountInfo) => {
+ return this.mastodonService.unfollowHashtag(refreshedAccount, hashtag);
+ });
+ }
+
+ getHashtag(currentlyUsedAccount: AccountInfo, hashtag: string): Promise {
+ return this.refreshAccountIfNeeded(currentlyUsedAccount)
+ .then((refreshedAccount: AccountInfo) => {
+ return this.mastodonService.getHashtag(refreshedAccount, hashtag);
+ });
+ }
+
uploadMediaAttachment(account: AccountInfo, file: File, description: string): Promise {
return this.refreshAccountIfNeeded(account)
.then((refreshedAccount: AccountInfo) => {
diff --git a/src/app/services/mastodon.service.ts b/src/app/services/mastodon.service.ts
index 46609a83..e5e7c79d 100644
--- a/src/app/services/mastodon.service.ts
+++ b/src/app/services/mastodon.service.ts
@@ -2,7 +2,7 @@ import { Injectable } from '@angular/core';
import { HttpHeaders, HttpClient, HttpResponse } from '@angular/common/http';
import { ApiRoutes } from './models/api.settings';
-import { Account, Status, Results, Context, Relationship, Instance, Attachment, Notification, List, Poll, Emoji, Conversation, ScheduledStatus } from "./models/mastodon.interfaces";
+import { Account, Status, Results, Context, Relationship, Instance, Attachment, Notification, List, Poll, Emoji, Conversation, ScheduledStatus, Tag } from "./models/mastodon.interfaces";
import { AccountInfo } from '../states/accounts.state';
import { StreamTypeEnum, StreamElement } from '../states/streams.state';
@@ -333,6 +333,24 @@ export class MastodonService {
}
+ followHashtag(currentlyUsedAccount: AccountInfo, hashtag: string): Promise {
+ const route = `https://${currentlyUsedAccount.instance}${this.apiRoutes.followHashtag}`.replace('{0}', hashtag);
+ const headers = new HttpHeaders({ 'Authorization': `Bearer ${currentlyUsedAccount.token.access_token}` });
+ return this.httpClient.post(route, null, { headers: headers }).toPromise();
+ }
+
+ unfollowHashtag(currentlyUsedAccount: AccountInfo, hashtag: string): Promise {
+ const route = `https://${currentlyUsedAccount.instance}${this.apiRoutes.unfollowHashtag}`.replace('{0}', hashtag);
+ const headers = new HttpHeaders({ 'Authorization': `Bearer ${currentlyUsedAccount.token.access_token}` });
+ return this.httpClient.post(route, null, { headers: headers }).toPromise();
+ }
+
+ getHashtag(currentlyUsedAccount: AccountInfo, hashtag: string): Promise {
+ const route = `https://${currentlyUsedAccount.instance}${this.apiRoutes.getHashtag}`.replace('{0}', hashtag);
+ const headers = new HttpHeaders({ 'Authorization': `Bearer ${currentlyUsedAccount.token.access_token}` });
+ return this.httpClient.get(route, { headers: headers }).toPromise();
+ }
+
uploadMediaAttachment(account: AccountInfo, file: File, description: string): Promise {
let input = new FormData();
input.append('file', file);
diff --git a/src/app/services/models/api.settings.ts b/src/app/services/models/api.settings.ts
index 8fc41e7a..f0bb1c10 100644
--- a/src/app/services/models/api.settings.ts
+++ b/src/app/services/models/api.settings.ts
@@ -76,4 +76,7 @@ export class ApiRoutes {
getBookmarks = '/api/v1/bookmarks';
getFollowers = '/api/v1/accounts/{0}/followers';
getFollowing = '/api/v1/accounts/{0}/following';
+ followHashtag = '/api/v1/tags/{0}/follow';
+ unfollowHashtag = '/api/v1/tags/{0}/unfollow';
+ getHashtag = '/api/v1/tags/{0}';
}
diff --git a/src/app/services/models/mastodon.interfaces.ts b/src/app/services/models/mastodon.interfaces.ts
index 8debd55a..7b33d791 100644
--- a/src/app/services/models/mastodon.interfaces.ts
+++ b/src/app/services/models/mastodon.interfaces.ts
@@ -141,7 +141,7 @@ export interface Relationship {
id: number;
following: boolean;
followed_by: boolean;
- blocked_by: boolean;
+ blocked_by: boolean;
blocking: boolean;
domain_blocking: boolean;
muting: boolean;
@@ -190,7 +190,7 @@ export interface Status {
muted: boolean;
bookmarked: boolean;
card: Card;
- poll: Poll;
+ poll: Poll;
pleroma: PleromaStatusInfo;
}
@@ -207,11 +207,6 @@ export interface PleromaStatusInfo {
local: boolean;
}
-export interface Tag {
- name: string;
- url: string;
-}
-
export interface List {
id: string;
title: string;
@@ -249,4 +244,17 @@ export interface StatusParams {
visibility: 'public' | 'unlisted' | 'private' | 'direct';
scheduled_at: string;
application_id: string;
+}
+
+export interface TagHistory {
+ day: string;
+ uses: number;
+ accounts: number;
+}
+
+export interface Tag {
+ name: string;
+ url: string;
+ history: TagHistory[];
+ following: boolean;
}
\ No newline at end of file