diff --git a/src/app/components/floating-column/manage-account/notifications/notification/notification.component.scss b/src/app/components/floating-column/manage-account/notifications/notification/notification.component.scss
index 0b156f04..c928bf96 100644
--- a/src/app/components/floating-column/manage-account/notifications/notification/notification.component.scss
+++ b/src/app/components/floating-column/manage-account/notifications/notification/notification.component.scss
@@ -46,6 +46,7 @@
color: $boost-color;
}
+$acccount-info-left: 70px;
.follow-account {
padding: 5px;
height: 60px;
@@ -62,8 +63,7 @@
height: 45px;
border-radius: 2px;
}
-
- $acccount-info-left: 70px;
+
&__display-name {
position: absolute;
top: 7px;
@@ -81,5 +81,44 @@
left: $acccount-info-left;
font-size: 13px;
color: $status-links-color;
+
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+
+ width: calc(100% - #{$acccount-info-left});
+ }
+}
+
+.follow_request {
+ width: calc(100% - #{$acccount-info-left});
+ margin-left: $acccount-info-left;
+
+ &__link {
+ display: inline-block;
+ width: calc(50%);
+ padding: 2px;
+
+ text-align: center;
+ color: rgb(182, 182, 182);
+ transition: all .2s;
+
+ // outline: 1px dotted greenyellow;
+
+ &--check {
+ &:hover {
+ color: greenyellow;
+ }
+ }
+
+ &--cross {
+ &:hover {
+ color: orangered;
+ }
+ }
+ }
+
+ &__icon {
+ text-align: center;
}
}
\ No newline at end of file
diff --git a/src/app/components/floating-column/manage-account/notifications/notification/notification.component.ts b/src/app/components/floating-column/manage-account/notifications/notification/notification.component.ts
index 48505220..547a58fb 100644
--- a/src/app/components/floating-column/manage-account/notifications/notification/notification.component.ts
+++ b/src/app/components/floating-column/manage-account/notifications/notification/notification.component.ts
@@ -1,22 +1,30 @@
import { Component, Input } from '@angular/core';
-import { faUserPlus } from "@fortawesome/free-solid-svg-icons";
+import { faUserPlus, faUserClock, faCheck, faTimes } from "@fortawesome/free-solid-svg-icons";
import { NotificationWrapper } from '../notifications.component';
import { ToolsService } from '../../../../../services/tools.service';
import { Account } from '../../../../../services/models/mastodon.interfaces';
import { BrowseBase } from '../../../../../components/common/browse-base';
+import { MastodonWrapperService } from '../../../../../services/mastodon-wrapper.service';
+import { NotificationService } from '../../../../../services/notification.service';
@Component({
selector: 'app-notification',
templateUrl: './notification.component.html',
styleUrls: ['./notification.component.scss']
})
-export class NotificationComponent extends BrowseBase {
+export class NotificationComponent extends BrowseBase {
faUserPlus = faUserPlus;
+ faUserClock = faUserClock;
+ faCheck = faCheck;
+ faTimes = faTimes;
@Input() notification: NotificationWrapper;
- constructor(private readonly toolsService: ToolsService) {
+ constructor(
+ private readonly notificationsService: NotificationService,
+ private readonly mastodonService: MastodonWrapperService,
+ private readonly toolsService: ToolsService) {
super();
}
@@ -31,9 +39,47 @@ export class NotificationComponent extends BrowseBase {
this.browseAccountEvent.next(accountName);
return false;
}
-
+
openUrl(url: string): boolean {
window.open(url, '_blank');
return false;
}
+
+ followRequestWorking: boolean;
+ followRequestProcessed: boolean;
+ acceptFollowRequest(): boolean {
+ if(this.followRequestWorking) return false;
+ this.followRequestWorking = true;
+
+ this.mastodonService.authorizeFollowRequest(this.notification.provider, this.notification.notification.account.id)
+ .then(res => {
+ this.followRequestProcessed = true;
+ })
+ .catch(err => {
+ this.notificationsService.notifyHttpError(err, this.notification.provider);
+ })
+ .then(res => {
+ this.followRequestWorking = false;
+ });
+
+ return false;
+ }
+
+ refuseFollowRequest(): boolean {
+ if(this.followRequestWorking) return false;
+ this.followRequestWorking = true;
+
+ this.mastodonService.rejectFollowRequest(this.notification.provider, this.notification.notification.account.id)
+ .then(res => {
+ this.followRequestProcessed = true;
+ })
+ .catch(err => {
+ this.notificationsService.notifyHttpError(err, this.notification.provider);
+ })
+ .then(res => {
+ this.followRequestWorking = false;
+ });
+
+ return false;
+ }
}
diff --git a/src/app/components/floating-column/manage-account/notifications/notifications.component.ts b/src/app/components/floating-column/manage-account/notifications/notifications.component.ts
index c9ab4157..c8a9db9c 100644
--- a/src/app/components/floating-column/manage-account/notifications/notifications.component.ts
+++ b/src/app/components/floating-column/manage-account/notifications/notifications.component.ts
@@ -158,11 +158,13 @@ export class NotificationWrapper {
this.account = notification.account;
this.wrapperId = `${this.type}-${notification.id}`;
this.notification = notification;
+ this.provider = provider;
}
+ provider: AccountInfo;
notification: Notification;
wrapperId: string;
account: Account;
status: StatusWrapper;
- type: 'mention' | 'reblog' | 'favourite' | 'follow' | 'poll';
+ type: 'mention' | 'reblog' | 'favourite' | 'follow' | 'poll' | 'follow_request';
}
\ No newline at end of file
diff --git a/src/app/components/stream/stream-notifications/stream-notifications.component.ts b/src/app/components/stream/stream-notifications/stream-notifications.component.ts
index d31e9306..339b83cb 100644
--- a/src/app/components/stream/stream-notifications/stream-notifications.component.ts
+++ b/src/app/components/stream/stream-notifications/stream-notifications.component.ts
@@ -128,6 +128,8 @@ export class StreamNotificationsComponent extends BrowseBase {
this.mastodonService.getNotifications(this.account, null, null, null, 10)
.then((notifications: Notification[]) => {
+ console.warn(notifications);
+
this.isNotificationsLoading = false;
this.notifications = notifications.map(x => {
@@ -235,7 +237,7 @@ export class StreamNotificationsComponent extends BrowseBase {
this.isMentionsLoading = true;
- this.mastodonService.getNotifications(this.account, ['follow', 'favourite', 'reblog', 'poll'], this.lastMentionId)
+ this.mastodonService.getNotifications(this.account, ['follow', 'favourite', 'reblog', 'poll', 'follow_request'], this.lastMentionId)
.then((result: Notification[]) => {
if (result.length === 0) {
this.mentionsMaxReached = true;
diff --git a/src/app/components/stream/user-profile/user-profile.component.html b/src/app/components/stream/user-profile/user-profile.component.html
index 5e3341a0..cc154f6c 100644
--- a/src/app/components/stream/user-profile/user-profile.component.html
+++ b/src/app/components/stream/user-profile/user-profile.component.html
@@ -13,7 +13,7 @@
@{{displayedAccount.acct}}
+ target="_blank" title="{{displayedAccount.acct}}">@{{displayedAccount.acct}}
diff --git a/src/app/components/stream/user-profile/user-profile.component.scss b/src/app/components/stream/user-profile/user-profile.component.scss
index 0eed5661..cab3bebb 100644
--- a/src/app/components/stream/user-profile/user-profile.component.scss
+++ b/src/app/components/stream/user-profile/user-profile.component.scss
@@ -402,6 +402,12 @@ $floating-header-height: 60px;
}
}
+.fa-lock {
+ margin-left: 5px;
+ color: gray;
+ font-size: 14px;
+}
+
//Mastodon styling
:host ::ng-deep .profile-fields__field--value {
// font-size: 14px;
diff --git a/src/app/components/stream/user-profile/user-profile.component.ts b/src/app/components/stream/user-profile/user-profile.component.ts
index 8b613382..3677530b 100644
--- a/src/app/components/stream/user-profile/user-profile.component.ts
+++ b/src/app/components/stream/user-profile/user-profile.component.ts
@@ -1,6 +1,6 @@
import { Component, OnInit, Input, Output, EventEmitter, ViewChild, ElementRef } from '@angular/core';
import { HttpErrorResponse } from '@angular/common/http';
-import { faUser, faHourglassHalf, faUserCheck, faExclamationTriangle, faLink } from "@fortawesome/free-solid-svg-icons";
+import { faUser, faHourglassHalf, faUserCheck, faExclamationTriangle, faLink, faLock } from "@fortawesome/free-solid-svg-icons";
import { faUser as faUserRegular } from "@fortawesome/free-regular-svg-icons";
import { Observable, Subscription } from 'rxjs';
import { Store } from '@ngxs/store';
@@ -29,6 +29,7 @@ export class UserProfileComponent extends BrowseBase {
faUserCheck = faUserCheck;
faExclamationTriangle = faExclamationTriangle;
faLink = faLink;
+ faLock = faLock;
displayedAccount: Account;
hasNote: boolean;
diff --git a/src/app/services/mastodon-wrapper.service.ts b/src/app/services/mastodon-wrapper.service.ts
index 28b3afc6..4dde19f8 100644
--- a/src/app/services/mastodon-wrapper.service.ts
+++ b/src/app/services/mastodon-wrapper.service.ts
@@ -252,7 +252,7 @@ export class MastodonWrapperService {
});
}
- getNotifications(account: AccountInfo, excludeTypes: ('follow' | 'favourite' | 'reblog' | 'mention' | 'poll')[] = null, maxId: string = null, sinceId: string = null, limit: number = 15): Promise
{
+ getNotifications(account: AccountInfo, excludeTypes: ('follow' | 'favourite' | 'reblog' | 'mention' | 'poll' | 'follow_request')[] = null, maxId: string = null, sinceId: string = null, limit: number = 15): Promise {
return this.refreshAccountIfNeeded(account)
.then((refreshedAccount: AccountInfo) => {
return this.mastodonService.getNotifications(refreshedAccount, excludeTypes, maxId, sinceId, limit);
@@ -405,4 +405,18 @@ export class MastodonWrapperService {
return this.mastodonService.getFollowers(refreshedAccount, accountId, maxId, sinceId, limit);
});
}
+
+ authorizeFollowRequest(account: AccountInfo, id: number): Promise {
+ return this.refreshAccountIfNeeded(account)
+ .then((refreshedAccount: AccountInfo) => {
+ return this.mastodonService.authorizeFollowRequest(refreshedAccount, id);
+ });
+ }
+
+ rejectFollowRequest(account: AccountInfo, id: number): Promise {
+ return this.refreshAccountIfNeeded(account)
+ .then((refreshedAccount: AccountInfo) => {
+ return this.mastodonService.rejectFollowRequest(refreshedAccount, id);
+ });
+ }
}
diff --git a/src/app/services/mastodon.service.ts b/src/app/services/mastodon.service.ts
index 003ef106..09302276 100644
--- a/src/app/services/mastodon.service.ts
+++ b/src/app/services/mastodon.service.ts
@@ -311,7 +311,7 @@ export class MastodonService {
return this.httpClient.put(route, input, { headers: headers }).toPromise();
}
- getNotifications(account: AccountInfo, excludeTypes: ('follow' | 'favourite' | 'reblog' | 'mention' | 'poll')[] = null, maxId: string = null, sinceId: string = null, limit: number = 15): Promise {
+ getNotifications(account: AccountInfo, excludeTypes: ('follow' | 'favourite' | 'reblog' | 'mention' | 'poll' | 'follow_request')[] = null, maxId: string = null, sinceId: string = null, limit: number = 15): Promise {
let route = `https://${account.instance}${this.apiRoutes.getNotifications}?limit=${limit}`;
if (maxId) {
@@ -490,6 +490,7 @@ export class MastodonService {
return new FollowingResult(lastId, res.body)
});
}
+
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());
@@ -511,6 +512,20 @@ export class MastodonService {
return new FollowingResult(lastId, res.body)
});
}
+
+ authorizeFollowRequest(account: AccountInfo, id: number): Promise {
+ const route = `https://${account.instance}${this.apiRoutes.authorizeFollowRequest}`.replace('{0}', id.toString());
+
+ const headers = new HttpHeaders({ 'Authorization': `Bearer ${account.token.access_token}` });
+ return this.httpClient.post(route, null, { headers: headers }).toPromise();
+ }
+
+ rejectFollowRequest(account: AccountInfo, id: number): Promise {
+ const route = `https://${account.instance}${this.apiRoutes.rejectFollowRequest}`.replace('{0}', id.toString());
+
+ const headers = new HttpHeaders({ 'Authorization': `Bearer ${account.token.access_token}` });
+ return this.httpClient.post(route, null, { 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 f6c28816..08573c16 100644
--- a/src/app/services/models/api.settings.ts
+++ b/src/app/services/models/api.settings.ts
@@ -21,8 +21,8 @@ export class ApiRoutes {
getBlocks = '/api/v1/blocks';
getFavourites = '/api/v1/favourites';
getFollowRequests = '/api/v1/follow_requests';
- authorizeFollowRequest = '/api/v1/follow_requests/authorize';
- rejectFollowRequest = '/api/v1/follow_requests/reject';
+ authorizeFollowRequest = '/api/v1/follow_requests/{0}/authorize';
+ rejectFollowRequest = '/api/v1/follow_requests/{0}/reject';
followRemote = '/api/v1/follows';
getInstance = '/api/v1/instance';
uploadMediaAttachment = '/api/v1/media';
diff --git a/src/app/services/models/mastodon.interfaces.ts b/src/app/services/models/mastodon.interfaces.ts
index 844585e6..6aa2956a 100644
--- a/src/app/services/models/mastodon.interfaces.ts
+++ b/src/app/services/models/mastodon.interfaces.ts
@@ -26,7 +26,7 @@ export interface Account {
username: string;
acct: string;
display_name: string;
- locked: string;
+ locked: boolean;
created_at: string;
followers_count: number;
following_count: number;
@@ -130,7 +130,7 @@ export interface Mention {
export interface Notification {
id: string;
- type: 'mention' | 'reblog' | 'favourite' | 'follow' | 'poll';
+ type: 'mention' | 'reblog' | 'favourite' | 'follow' | 'poll' | 'follow_request';
created_at: string;
account: Account;
status?: Status;
diff --git a/src/app/services/user-notification.service.ts b/src/app/services/user-notification.service.ts
index f2545b53..f8cc94cb 100644
--- a/src/app/services/user-notification.service.ts
+++ b/src/app/services/user-notification.service.ts
@@ -58,7 +58,7 @@ export class UserNotificationService {
}
private startFetchingNotifications(account: AccountInfo) {
- let getMentionsPromise = this.mastodonService.getNotifications(account, ['favourite', 'follow', 'reblog', 'poll'], null, null, 10)
+ let getMentionsPromise = this.mastodonService.getNotifications(account, ['favourite', 'follow', 'reblog', 'poll', 'follow_request'], null, null, 10)
.then((notifications: Notification[]) => {
this.processMentionsAndNotifications(account, notifications, NotificationTypeEnum.UserMention);
})