diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2d9da504..41195c8e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -20,5 +20,5 @@ For example: ## Pull Requests -Pull Requests are maybe a bit early right now, since the project and code can change a lot, so it's not really adviced to open PR today. -I will notify explicitly when I'll be more open to external contributions. + +Please open first an [issue](https://github.com/NicolasConstant/sengi/issues/new) before working on a new functionality you would like to submit to this repository. diff --git a/README.md b/README.md index c0f4f6fb..45c06e1b 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ It is released as a **browser webapp** and also packaged as an **cross-platform ## State of development -Sengi already supports all the basics functionalities, but many minors enhancements are still needed before a 1.0.0 release. +The first major stable release has been published (1.0.0), the project is open to external contributions. ## Screens diff --git a/package.json b/package.json index 5558d5cb..755b085a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "sengi", - "version": "0.33.0", + "version": "1.0.0", "license": "AGPL-3.0-or-later", "main": "main-electron.js", "description": "A multi-account desktop client for Mastodon and Pleroma", diff --git a/src/app/components/common/account/account.component.html b/src/app/components/common/account/account.component.html index af57ef6a..4efcf35f 100644 --- a/src/app/components/common/account/account.component.html +++ b/src/app/components/common/account/account.component.html @@ -1,4 +1,4 @@ - +
@{{ account.acct }}
diff --git a/src/app/components/common/account/account.component.ts b/src/app/components/common/account/account.component.ts index f7955b80..7d20d216 100644 --- a/src/app/components/common/account/account.component.ts +++ b/src/app/components/common/account/account.component.ts @@ -21,4 +21,9 @@ export class AccountComponent implements OnInit { this.accountSelected.next(this.account); return false; } + + openAccount(): boolean { + window.open(this.account.url, '_blank'); + return false; + } } diff --git a/src/app/components/create-status/create-status.component.ts b/src/app/components/create-status/create-status.component.ts index 6f305863..2561159a 100644 --- a/src/app/components/create-status/create-status.component.ts +++ b/src/app/components/create-status/create-status.component.ts @@ -883,7 +883,6 @@ export class CreateStatusComponent implements OnInit, OnDestroy { this.overlayRef = this.overlay.create(config); // this.overlayRef.backdropClick().subscribe(() => { - // console.warn('wut?'); // this.overlayRef.dispose(); // }); diff --git a/src/app/components/floating-column/manage-account/mentions/mentions.component.ts b/src/app/components/floating-column/manage-account/mentions/mentions.component.ts index eb416065..e1ca1c8d 100644 --- a/src/app/components/floating-column/manage-account/mentions/mentions.component.ts +++ b/src/app/components/floating-column/manage-account/mentions/mentions.component.ts @@ -70,7 +70,7 @@ export class MentionsComponent extends TimelineBase { if (userNotification && userNotification.mentions) { let orderedMentions = [...userNotification.mentions.map(x => x.status)].reverse(); for (let m of orderedMentions) { - if (!this.statuses.find(x => x.status.id === m.id)) { + if (m && !this.statuses.find(x => x.status.id === m.id)) { let cwPolicy = this.toolsService.checkContentWarning(m); const statusWrapper = new StatusWrapper(cwPolicy.status, this.account, cwPolicy.applyCw, cwPolicy.hide); this.statuses.unshift(statusWrapper); @@ -82,8 +82,7 @@ export class MentionsComponent extends TimelineBase { } protected getNextStatuses(): Promise { - console.warn('MENTIONS get next status'); - return this.mastodonService.getNotifications(this.account, ['follow', 'favourite', 'reblog', 'poll'], this.lastId) + return this.mastodonService.getNotifications(this.account, ['follow', 'favourite', 'reblog', 'poll', 'move'], this.lastId) .then((result: Notification[]) => { const statuses = result.map(x => x.status); diff --git a/src/app/components/floating-column/manage-account/notifications/notification/notification.component.html b/src/app/components/floating-column/manage-account/notifications/notification/notification.component.html index a91f1481..93d2f28d 100644 --- a/src/app/components/floating-column/manage-account/notifications/notification/notification.component.html +++ b/src/app/components/floating-column/manage-account/notifications/notification/notification.component.html @@ -50,6 +50,25 @@
+
+
+ +
+
+ + migrated to +
+ + + + + + +
+ { - console.warn('CLOSE'); this.close(); return false; }); diff --git a/src/app/components/notification-hub/notification-hub.component.ts b/src/app/components/notification-hub/notification-hub.component.ts index 65f9b297..bc1d15c5 100644 --- a/src/app/components/notification-hub/notification-hub.component.ts +++ b/src/app/components/notification-hub/notification-hub.component.ts @@ -1,5 +1,5 @@ import { Component, OnInit } from '@angular/core'; -import { NotificationService, NotificatioData } from '../../services/notification.service'; +import { NotificationService, NotificationData } from '../../services/notification.service'; @Component({ selector: 'app-notification-hub', @@ -12,7 +12,7 @@ export class NotificationHubComponent implements OnInit { constructor(private notificationService: NotificationService) { } ngOnInit() { - this.notificationService.notifactionStream.subscribe((notification: NotificatioData) => { + this.notificationService.notifactionStream.subscribe((notification: NotificationData) => { let alreadyExistingNotification = this.notifications.find(x => x.avatar === notification.avatar && x.message === notification.message); if(alreadyExistingNotification){ @@ -40,13 +40,13 @@ export class NotificationHubComponent implements OnInit { // }, 1500); // } - onClick(notification: NotificatioData): void{ + onClick(notification: NotificationData): void{ this.notifications = this.notifications.filter(x => x.id !== notification.id); } } -class NotificationWrapper extends NotificatioData { - constructor(data: NotificatioData) { +class NotificationWrapper extends NotificationData { + constructor(data: NotificationData) { super(data.avatar, data.errorCode, data.message, data.isError); } diff --git a/src/app/components/stream/hashtag/hashtag.component.html b/src/app/components/stream/hashtag/hashtag.component.html index dbf3f1c6..f6df8687 100644 --- a/src/app/components/stream/hashtag/hashtag.component.html +++ b/src/app/components/stream/hashtag/hashtag.component.html @@ -3,7 +3,7 @@

#{{hashtagElement.tag}}

- +
{ - console.warn(notifications); - this.isNotificationsLoading = false; this.notifications = notifications.map(x => { @@ -237,7 +235,7 @@ export class StreamNotificationsComponent extends BrowseBase { this.isMentionsLoading = true; - this.mastodonService.getNotifications(this.account, ['follow', 'favourite', 'reblog', 'poll', 'follow_request'], this.lastMentionId) + this.mastodonService.getNotifications(this.account, ['follow', 'favourite', 'reblog', 'poll', 'follow_request', 'move'], this.lastMentionId) .then((result: Notification[]) => { if (result.length === 0) { this.mentionsMaxReached = true; 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 f39e9ff3..546a0e8f 100644 --- a/src/app/components/stream/user-follows/user-follows.component.ts +++ b/src/app/components/stream/user-follows/user-follows.component.ts @@ -96,7 +96,6 @@ export class UserFollowsComponent implements OnInit, OnDestroy { } }) .then((result: FollowingResult) => { - console.warn(result); this.maxId = result.maxId; this.accounts = result.follows; }) diff --git a/src/app/services/mastodon-wrapper.service.ts b/src/app/services/mastodon-wrapper.service.ts index 4dde19f8..9452ced7 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' | 'follow_request')[] = null, maxId: string = null, sinceId: string = null, limit: number = 15): Promise { + getNotifications(account: AccountInfo, excludeTypes: ('follow' | 'favourite' | 'reblog' | 'mention' | 'poll' | 'follow_request' | 'move')[] = 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); diff --git a/src/app/services/mastodon.service.ts b/src/app/services/mastodon.service.ts index 09302276..78a89f18 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' | 'follow_request')[] = null, maxId: string = null, sinceId: string = null, limit: number = 15): Promise { + getNotifications(account: AccountInfo, excludeTypes: ('follow' | 'favourite' | 'reblog' | 'mention' | 'poll' | 'follow_request' | 'move')[] = null, maxId: string = null, sinceId: string = null, limit: number = 15): Promise { let route = `https://${account.instance}${this.apiRoutes.getNotifications}?limit=${limit}`; if (maxId) { @@ -393,8 +393,11 @@ export class MastodonService { let route = `https://${account.instance}${this.apiRoutes.voteOnPoll}`.replace('{0}', pollId); route += `?${this.formatArray(pollSelection.map(x => x.toString()), 'choices')}`; + let data = new PollData(); + data.choices = pollSelection; + const headers = new HttpHeaders({ 'Authorization': `Bearer ${account.token.access_token}` }); - return this.httpClient.post(route, null, { headers: headers }).toPromise(); + return this.httpClient.post(route, data, { headers: headers }).toPromise(); } getPoll(account: AccountInfo, pollId: string): Promise { @@ -536,6 +539,10 @@ export enum VisibilityEnum { Direct = 4 } +class PollData { + choices: number[]; +} + class StatusData { status: string; in_reply_to_id: string; diff --git a/src/app/services/models/mastodon.interfaces.ts b/src/app/services/models/mastodon.interfaces.ts index 6aa2956a..c1668a7a 100644 --- a/src/app/services/models/mastodon.interfaces.ts +++ b/src/app/services/models/mastodon.interfaces.ts @@ -130,10 +130,11 @@ export interface Mention { export interface Notification { id: string; - type: 'mention' | 'reblog' | 'favourite' | 'follow' | 'poll' | 'follow_request'; + type: 'mention' | 'reblog' | 'favourite' | 'follow' | 'poll' | 'follow_request' | 'move'; created_at: string; account: Account; status?: Status; + target?: Account; //for move Pleroma's notification } export interface Relationship { diff --git a/src/app/services/notification.service.ts b/src/app/services/notification.service.ts index b39468d3..7ed28448 100644 --- a/src/app/services/notification.service.ts +++ b/src/app/services/notification.service.ts @@ -10,7 +10,7 @@ import { ToolsService } from './tools.service'; @Injectable() export class NotificationService { public restartNotificationStream = new Subject(); - public notifactionStream = new Subject(); + public notifactionStream = new Subject(); public newRespondPostedStream = new Subject(); public hideAccountUrlStream = new Subject(); public deletedStatusStream = new Subject(); @@ -19,7 +19,7 @@ export class NotificationService { } public notify(avatar: string, errorCode: number, message: string, isError: boolean) { - let newNotification = new NotificatioData(avatar, errorCode, message, isError); + let newNotification = new NotificationData(avatar, errorCode, message, isError); this.notifactionStream.next(newNotification); } @@ -70,7 +70,7 @@ export class NotificationService { } } -export class NotificatioData { +export class NotificationData { public id: string; constructor( diff --git a/src/app/services/streaming.service.ts b/src/app/services/streaming.service.ts index a5040157..7076bb1c 100644 --- a/src/app/services/streaming.service.ts +++ b/src/app/services/streaming.service.ts @@ -16,8 +16,6 @@ export class StreamingService { private readonly mastodonService: MastodonWrapperService) { } getStreaming(accountInfo: AccountInfo, stream: StreamElement, since_id: string = null): StreamingWrapper { - - //console.warn('EventSourceStreaminWrapper'); //new EventSourceStreaminWrapper(accountInfo, stream); return new StreamingWrapper(this.mastodonService, accountInfo, stream, this.nbStatusPerIteration); diff --git a/src/app/services/user-notification.service.ts b/src/app/services/user-notification.service.ts index f8cc94cb..7110bafd 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', 'follow_request'], null, null, 10) + let getMentionsPromise = this.mastodonService.getNotifications(account, ['favourite', 'follow', 'reblog', 'poll', 'follow_request', 'move'], null, null, 10) .then((notifications: Notification[]) => { this.processMentionsAndNotifications(account, notifications, NotificationTypeEnum.UserMention); })