From bd44586d960930c1332fc9d8595db041c576c853 Mon Sep 17 00:00:00 2001 From: Nicolas Constant Date: Wed, 29 Apr 2020 19:26:15 -0400 Subject: [PATCH 01/17] typo fix --- src/app/components/create-status/create-status.component.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/components/create-status/create-status.component.html b/src/app/components/create-status/create-status.component.html index df0480d4..d7f3538e 100644 --- a/src/app/components/create-status/create-status.component.html +++ b/src/app/components/create-status/create-status.component.html @@ -8,7 +8,7 @@ From 560147743d81bdd3a244513dc85a13de492d4247 Mon Sep 17 00:00:00 2001 From: Nicolas Constant Date: Wed, 29 Apr 2020 22:04:39 -0400 Subject: [PATCH 02/17] better token renewal, fix #269 --- src/app/services/mastodon-wrapper.service.ts | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/app/services/mastodon-wrapper.service.ts b/src/app/services/mastodon-wrapper.service.ts index 694a73b6..db2cad4e 100644 --- a/src/app/services/mastodon-wrapper.service.ts +++ b/src/app/services/mastodon-wrapper.service.ts @@ -12,6 +12,7 @@ import { AppInfo, RegisteredAppsStateModel } from '../states/registered-apps.sta providedIn: 'root' }) export class MastodonWrapperService { + private refreshingToken: { [id: string]: Promise } = {}; constructor( private readonly store: Store, @@ -19,6 +20,10 @@ export class MastodonWrapperService { private readonly mastodonService: MastodonService) { } refreshAccountIfNeeded(accountInfo: AccountInfo): Promise { + if(this.refreshingToken[accountInfo.id]){ + return this.refreshingToken[accountInfo.id]; + } + let isExpired = false; let storedAccountInfo = this.getStoreAccountInfo(accountInfo.id); @@ -47,11 +52,8 @@ export class MastodonWrapperService { } if (storedAccountInfo.token.refresh_token && isExpired) { - console.log('>>> MARTY!! ------------'); - console.log('>>> RENEW TOKEN FFS ----'); - const app = this.getAllSavedApps().find(x => x.instance === storedAccountInfo.instance); - return this.authService.refreshToken(storedAccountInfo.instance, app.app.client_id, app.app.client_secret, storedAccountInfo.token.refresh_token) + let p = this.authService.refreshToken(storedAccountInfo.instance, app.app.client_id, app.app.client_secret, storedAccountInfo.token.refresh_token) .then((tokenData: TokenData) => { if (tokenData.refresh_token && !tokenData.created_at) { const nowEpoch = Date.now() / 1000 | 0; @@ -66,6 +68,13 @@ export class MastodonWrapperService { .catch(err => { return Promise.resolve(storedAccountInfo); }); + + p.then(() => { + this.refreshingToken[accountInfo.id] = null; + }); + + this.refreshingToken[accountInfo.id] = p; + return p; } else { return Promise.resolve(storedAccountInfo); } From 6f96de22ceee2127a1318a4ba6a7cc6d368f1974 Mon Sep 17 00:00:00 2001 From: Nicolas Constant Date: Thu, 30 Apr 2020 02:11:02 -0400 Subject: [PATCH 03/17] fix emoji pipeline --- src/app/pipes/account-emoji.pipe.ts | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/app/pipes/account-emoji.pipe.ts b/src/app/pipes/account-emoji.pipe.ts index 31480535..50cb6a96 100644 --- a/src/app/pipes/account-emoji.pipe.ts +++ b/src/app/pipes/account-emoji.pipe.ts @@ -4,19 +4,22 @@ import { EmojiConverter, EmojiTypeEnum } from '../tools/emoji.tools'; import { Account } from '../services/models/mastodon.interfaces'; @Pipe({ - name: "accountEmoji" + name: "accountEmoji" }) export class AccountEmojiPipe implements PipeTransform { - private emojiConverter = new EmojiConverter(); + private emojiConverter = new EmojiConverter(); - transform(value: Account, text?: string): any { + transform(value: Account, text?: string): any { + try { + let textToTransform = text; + if (!text) { + if (value.display_name) textToTransform = value.display_name; + else textToTransform = value.acct.split('@')[0]; + } - let textToTransform = text; - if(!text){ - if(value.display_name) textToTransform = value.display_name; - else textToTransform = value.acct.split('@')[0]; - } - - return this.emojiConverter.applyEmojis(value.emojis, textToTransform, EmojiTypeEnum.small) - } + return this.emojiConverter.applyEmojis(value.emojis, textToTransform, EmojiTypeEnum.small); + } catch (err){ + return ''; + } + } } From 54bce7762e5eb20462456d4b9c398792e140137a Mon Sep 17 00:00:00 2001 From: Nicolas Constant Date: Thu, 30 Apr 2020 02:12:01 -0400 Subject: [PATCH 04/17] added gototop on profile, fix #259 --- .../bookmarks/bookmarks.component.ts | 11 ++++++ .../direct-messages.component.ts | 11 ++++++ .../favorites/favorites.component.ts | 11 ++++++ .../manage-account.component.html | 10 ++--- .../manage-account.component.ts | 37 ++++++++++++++++++- .../mentions/mentions.component.ts | 11 ++++++ .../notifications/notifications.component.ts | 11 ++++++ 7 files changed, 95 insertions(+), 7 deletions(-) diff --git a/src/app/components/floating-column/manage-account/bookmarks/bookmarks.component.ts b/src/app/components/floating-column/manage-account/bookmarks/bookmarks.component.ts index 42e3010d..0b148cb7 100644 --- a/src/app/components/floating-column/manage-account/bookmarks/bookmarks.component.ts +++ b/src/app/components/floating-column/manage-account/bookmarks/bookmarks.component.ts @@ -127,4 +127,15 @@ export class BookmarksComponent implements OnInit { browseThread(openThreadEvent: OpenThreadEvent): void { this.browseThreadEvent.next(openThreadEvent); } + + applyGoToTop(): boolean { + const stream = this.statustream.nativeElement as HTMLElement; + setTimeout(() => { + stream.scrollTo({ + top: 0, + behavior: 'smooth' + }); + }, 0); + return false; + } } diff --git a/src/app/components/floating-column/manage-account/direct-messages/direct-messages.component.ts b/src/app/components/floating-column/manage-account/direct-messages/direct-messages.component.ts index da6d00f2..c03de70f 100644 --- a/src/app/components/floating-column/manage-account/direct-messages/direct-messages.component.ts +++ b/src/app/components/floating-column/manage-account/direct-messages/direct-messages.component.ts @@ -121,6 +121,17 @@ export class DirectMessagesComponent implements OnInit { browseThread(openThreadEvent: OpenThreadEvent): void { this.browseThreadEvent.next(openThreadEvent); } + + applyGoToTop(): boolean { + const stream = this.statustream.nativeElement as HTMLElement; + setTimeout(() => { + stream.scrollTo({ + top: 0, + behavior: 'smooth' + }); + }, 0); + return false; + } } class ConversationWrapper { diff --git a/src/app/components/floating-column/manage-account/favorites/favorites.component.ts b/src/app/components/floating-column/manage-account/favorites/favorites.component.ts index 6f5dfd83..89e8e4af 100644 --- a/src/app/components/floating-column/manage-account/favorites/favorites.component.ts +++ b/src/app/components/floating-column/manage-account/favorites/favorites.component.ts @@ -128,4 +128,15 @@ export class FavoritesComponent implements OnInit { browseThread(openThreadEvent: OpenThreadEvent): void { this.browseThreadEvent.next(openThreadEvent); } + + applyGoToTop(): boolean { + const stream = this.statustream.nativeElement as HTMLElement; + setTimeout(() => { + stream.scrollTo({ + top: 0, + behavior: 'smooth' + }); + }, 0); + return false; + } } diff --git a/src/app/components/floating-column/manage-account/manage-account.component.html b/src/app/components/floating-column/manage-account/manage-account.component.html index 4ad23889..f1916c76 100644 --- a/src/app/components/floating-column/manage-account/manage-account.component.html +++ b/src/app/components/floating-column/manage-account/manage-account.component.html @@ -35,20 +35,20 @@ - - - - - \ No newline at end of file diff --git a/src/app/components/floating-column/manage-account/manage-account.component.ts b/src/app/components/floating-column/manage-account/manage-account.component.ts index c6fdfe69..b417fcae 100644 --- a/src/app/components/floating-column/manage-account/manage-account.component.ts +++ b/src/app/components/floating-column/manage-account/manage-account.component.ts @@ -1,4 +1,4 @@ -import { Component, OnInit, OnDestroy, Input, Output, EventEmitter } from '@angular/core'; +import { Component, OnInit, OnDestroy, Input, Output, EventEmitter, ViewChild } from '@angular/core'; import { faAt, faUserPlus } from "@fortawesome/free-solid-svg-icons"; import { faBell, faEnvelope, faUser, faStar, faBookmark } from "@fortawesome/free-regular-svg-icons"; import { Subscription } from 'rxjs'; @@ -10,6 +10,11 @@ import { MastodonWrapperService } from '../../../services/mastodon-wrapper.servi import { Account } from "../../../services/models/mastodon.interfaces"; import { NotificationService } from '../../../services/notification.service'; import { AccountInfo } from '../../../states/accounts.state'; +import { BookmarksComponent } from './bookmarks/bookmarks.component'; +import { NotificationsComponent } from './notifications/notifications.component'; +import { MentionsComponent } from './mentions/mentions.component'; +import { DirectMessagesComponent } from './direct-messages/direct-messages.component'; +import { FavoritesComponent } from './favorites/favorites.component'; @Component({ @@ -122,8 +127,36 @@ export class ManageAccountComponent implements OnInit, OnDestroy { } } - loadSubPanel(subpanel: 'account' | 'notifications' | 'mentions' | 'dm' | 'favorites'): boolean { + @ViewChild('bookmarks') bookmarksComp:BookmarksComponent; + @ViewChild('notifications') notificationsComp:NotificationsComponent; + @ViewChild('mentions') mentionsComp:MentionsComponent; + @ViewChild('dm') dmComp:DirectMessagesComponent; + @ViewChild('favorites') favoritesComp:FavoritesComponent; + + loadSubPanel(subpanel: 'account' | 'notifications' | 'mentions' | 'dm' | 'favorites' | 'bookmarks'): boolean { + if(this.subPanel === subpanel){ + switch(subpanel){ + case 'bookmarks': + this.bookmarksComp.applyGoToTop(); + break; + case 'notifications': + this.notificationsComp.applyGoToTop(); + break; + case 'mentions': + this.mentionsComp.applyGoToTop(); + break; + case 'dm': + this.dmComp.applyGoToTop(); + break; + case 'favorites': + this.favoritesComp.applyGoToTop(); + break; + } + console.log('gototop'); + } + this.subPanel = subpanel; + return false; } 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 b90a56a2..cee550d4 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 @@ -146,4 +146,15 @@ export class MentionsComponent implements OnInit, OnDestroy { browseThread(openThreadEvent: OpenThreadEvent): void { this.browseThreadEvent.next(openThreadEvent); } + + applyGoToTop(): boolean { + const stream = this.statustream.nativeElement as HTMLElement; + setTimeout(() => { + stream.scrollTo({ + top: 0, + behavior: 'smooth' + }); + }, 0); + 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 35f4fe12..0753858b 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 @@ -135,6 +135,17 @@ export class NotificationsComponent implements OnInit, OnDestroy { browseThread(openThreadEvent: OpenThreadEvent): void { this.browseThreadEvent.next(openThreadEvent); } + + applyGoToTop(): boolean { + const stream = this.statustream.nativeElement as HTMLElement; + setTimeout(() => { + stream.scrollTo({ + top: 0, + behavior: 'smooth' + }); + }, 0); + return false; + } } export class NotificationWrapper { From 42217b42b8dfe0065b68327a6fee1d761c279698 Mon Sep 17 00:00:00 2001 From: Nicolas Constant Date: Thu, 30 Apr 2020 02:40:17 -0400 Subject: [PATCH 05/17] clean up --- .../floating-column/manage-account/manage-account.component.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/app/components/floating-column/manage-account/manage-account.component.ts b/src/app/components/floating-column/manage-account/manage-account.component.ts index b417fcae..1f314a68 100644 --- a/src/app/components/floating-column/manage-account/manage-account.component.ts +++ b/src/app/components/floating-column/manage-account/manage-account.component.ts @@ -152,7 +152,6 @@ export class ManageAccountComponent implements OnInit, OnDestroy { this.favoritesComp.applyGoToTop(); break; } - console.log('gototop'); } this.subPanel = subpanel; From 25d468ad21f5f79c410a7aad562a3e51682352c2 Mon Sep 17 00:00:00 2001 From: Nicolas Constant Date: Thu, 30 Apr 2020 18:31:27 -0400 Subject: [PATCH 06/17] fix frefox scroll not working, fix #230 --- src/app/components/create-status/create-status.component.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/app/components/create-status/create-status.component.ts b/src/app/components/create-status/create-status.component.ts index a926199b..ec26f747 100644 --- a/src/app/components/create-status/create-status.component.ts +++ b/src/app/components/create-status/create-status.component.ts @@ -735,7 +735,11 @@ export class CreateStatusComponent implements OnInit, OnDestroy { if (isVisible) { setTimeout(() => { - this.footerElement.nativeElement.scrollIntoViewIfNeeded({ behavior: 'instant', block: 'end', inline: 'start' }); + try{ + this.footerElement.nativeElement.scrollIntoViewIfNeeded({ behavior: 'instant', block: 'end', inline: 'start' }); + }catch(err) { + this.footerElement.nativeElement.scrollIntoView({ behavior: 'instant', block: 'end', inline: 'start' }); + } }, 0); } } From 7008dbbbba59fae65fb92224fd153a8fdec456c4 Mon Sep 17 00:00:00 2001 From: Nicolas Constant Date: Thu, 30 Apr 2020 18:46:15 -0400 Subject: [PATCH 07/17] fetching notifications on new accounts, fix #260 --- src/app/services/user-notification.service.ts | 116 ++++++++++-------- 1 file changed, 64 insertions(+), 52 deletions(-) diff --git a/src/app/services/user-notification.service.ts b/src/app/services/user-notification.service.ts index 7c0413c5..f2545b53 100644 --- a/src/app/services/user-notification.service.ts +++ b/src/app/services/user-notification.service.ts @@ -25,82 +25,94 @@ export class UserNotificationService { private soundJustPlayed = false; private soundFileId: string; + private accountSub: Subscription; + private loadedAccounts: AccountInfo[] = []; + constructor( private readonly streamingService: StreamingService, private readonly toolsService: ToolsService, private readonly notificationService: NotificationService, private readonly mastodonService: MastodonWrapperService, private readonly store: Store) { - + this.fetchNotifications(); - } + } private fetchNotifications() { let accounts = this.store.snapshot().registeredaccounts.accounts; - // let promises: Promise[] = []; accounts.forEach((account: AccountInfo) => { - // let sinceId = null; - // if (this.sinceIds[account.id]) { - // sinceId = this.sinceIds[account.id]; - // } - - let getMentionsPromise = this.mastodonService.getNotifications(account, ['favourite', 'follow', 'reblog', 'poll'], null, null, 10) - .then((notifications: Notification[]) => { - this.processMentionsAndNotifications(account, notifications, NotificationTypeEnum.UserMention); - }) - .catch(err => { - this.notificationService.notifyHttpError(err, account); - }); - - let getNotificationPromise = this.mastodonService.getNotifications(account, ['mention'], null, null, 10) - .then((notifications: Notification[]) => { - this.processMentionsAndNotifications(account, notifications, NotificationTypeEnum.UserNotification); - }) - .catch(err => { - this.notificationService.notifyHttpError(err, account); - }); - - Promise.all([getMentionsPromise, getNotificationPromise]) - .then(() => { - let streamElement = new StreamElement(StreamTypeEnum.personnal, 'activity', account.id, null, null, null, account.instance); - - let streaming = this.streamingService.getStreaming(account, streamElement); - streaming.statusUpdateSubjet.subscribe((notification: StatusUpdate) => { - if (notification && notification.type === EventEnum.notification) { - this.processNewUpdate(account, notification); - } - }); - }) - .catch(err => { }); + this.loadedAccounts.push(account); + this.startFetchingNotifications(account); }); + + this.accountSub = this.store.select(state => state.registeredaccounts.accounts) + .subscribe((accounts: AccountInfo[]) => { + accounts.forEach(a => { + if(!this.loadedAccounts.find(x => x.id === a.id)){ + this.loadedAccounts.push(a); + this.startFetchingNotifications(a); + } + }); + }); + } + + private startFetchingNotifications(account: AccountInfo) { + let getMentionsPromise = this.mastodonService.getNotifications(account, ['favourite', 'follow', 'reblog', 'poll'], null, null, 10) + .then((notifications: Notification[]) => { + this.processMentionsAndNotifications(account, notifications, NotificationTypeEnum.UserMention); + }) + .catch(err => { + this.notificationService.notifyHttpError(err, account); + }); + + let getNotificationPromise = this.mastodonService.getNotifications(account, ['mention'], null, null, 10) + .then((notifications: Notification[]) => { + this.processMentionsAndNotifications(account, notifications, NotificationTypeEnum.UserNotification); + }) + .catch(err => { + this.notificationService.notifyHttpError(err, account); + }); + + Promise.all([getMentionsPromise, getNotificationPromise]) + .then(() => { + let streamElement = new StreamElement(StreamTypeEnum.personnal, 'activity', account.id, null, null, null, account.instance); + + let streaming = this.streamingService.getStreaming(account, streamElement); + streaming.statusUpdateSubjet.subscribe((notification: StatusUpdate) => { + if (notification && notification.type === EventEnum.notification) { + this.processNewUpdate(account, notification); + } + }); + }) + .catch(err => { }); } private playSoundNotification() { const settings = this.toolsService.getSettings(); - if(settings.disableSounds) return; - if(this.soundJustPlayed) return; + if (settings.disableSounds) return; + if (this.soundJustPlayed) return; this.soundJustPlayed = true; - + this.setNotificationSound(); this.sound.play(); - setTimeout(() => { + setTimeout(() => { this.soundJustPlayed = false; }, 2000); } private setNotificationSound() { let settings = this.toolsService.getSettings(); - let soundId = settings.notificationSoundFileId; - - if(!soundId){ + let soundId = settings.notificationSoundFileId; + + if (!soundId) { soundId = '0'; settings.notificationSoundFileId = '0'; this.toolsService.saveSettings(settings); } - if(this.soundFileId === soundId) return; + if (this.soundFileId === soundId) return; var sound = this.getAllNotificationSounds().find(x => x.id === soundId); this.sound = new Howl({ @@ -110,9 +122,9 @@ export class UserNotificationService { } private processNewUpdate(account: AccountInfo, notification: StatusUpdate) { - if(!notification && !notification.notification) return; + if (!notification && !notification.notification) return; - if(!notification.muteSound){ + if (!notification.muteSound) { this.playSoundNotification(); } @@ -129,15 +141,15 @@ export class UserNotificationService { } let currentNotifications = this.userNotifications.value; - let currentAccountNotifications = currentNotifications.find(x => x.account.id === account.id); + let currentAccountNotifications = currentNotifications.find(x => x.account.id === account.id); if (currentAccountNotifications) { currentAccountNotifications = this.analyseNotifications(account, currentAccountNotifications, notifications, type); //if (currentAccountNotifications.hasNewMentions || currentAccountNotifications.hasNewNotifications) { - currentNotifications = currentNotifications.filter(x => x.account.id !== account.id); - currentNotifications.push(currentAccountNotifications); - this.userNotifications.next(currentNotifications); + currentNotifications = currentNotifications.filter(x => x.account.id !== account.id); + currentNotifications.push(currentAccountNotifications); + this.userNotifications.next(currentNotifications); //} } else { let newNotifications = new UserNotification(); @@ -230,7 +242,7 @@ export class UserNotificationService { new NotificationSoundDefinition('0', 'assets/audio/all-eyes-on-me.mp3', 'All eyes on me'), new NotificationSoundDefinition('1', 'assets/audio/exquisite.mp3', 'Exquisite'), new NotificationSoundDefinition('2', 'assets/audio/appointed.mp3', 'Appointed'), - new NotificationSoundDefinition('3', 'assets/audio/boop.mp3', 'Mastodon boop'), + new NotificationSoundDefinition('3', 'assets/audio/boop.mp3', 'Mastodon boop'), ]; return defs; } @@ -261,5 +273,5 @@ export class NotificationSoundDefinition { constructor( public readonly id: string, public readonly path: string, - public readonly name: string) {} + public readonly name: string) { } } \ No newline at end of file From b71743b8f6a01ddb38045cc9c8fb8deef9898b1d Mon Sep 17 00:00:00 2001 From: Nicolas Constant Date: Thu, 30 Apr 2020 22:11:00 -0400 Subject: [PATCH 08/17] fix autoupdater UI --- src/app/app.component.html | 2 +- src/app/app.component.scss | 9 +++++--- src/app/app.component.ts | 43 ++++++++++++++++++++++++++------------ 3 files changed, 37 insertions(+), 17 deletions(-) diff --git a/src/app/app.component.html b/src/app/app.component.html index 9a1e319a..ec1a6820 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -10,7 +10,7 @@ -
+
A new version is available!
reload
diff --git a/src/app/app.component.scss b/src/app/app.component.scss index c13b810d..aef18c8b 100644 --- a/src/app/app.component.scss +++ b/src/app/app.component.scss @@ -104,17 +104,20 @@ app-streams-selection-footer { transition-timing-function: ease-in; position: absolute; - height: 70px; + height: 50px; left: 0; right: 0; - bottom: -80px; + bottom: 0; + //bottom: -80px; + opacity: 0; z-index: 999999999; &__activated { // opacity: 1; transition: all .25s; transition-timing-function: ease-out; - bottom: 0px; + opacity: 1; + height: 70px; } &__display { diff --git a/src/app/app.component.ts b/src/app/app.component.ts index e0a03b45..c3b7eaa9 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -32,7 +32,9 @@ export class AppComponent implements OnInit, OnDestroy { floatingColumnActive: boolean; tutorialActive: boolean; openedMediaEvent: OpenMediaEvent + updateAvailable: boolean; + showUpdate: boolean; private authStorageKey: string = 'tempAuth'; @@ -42,7 +44,7 @@ export class AppComponent implements OnInit, OnDestroy { private dragoverSub: Subscription; private updateAvailableSub: Subscription; private paramsSub: Subscription; - + @Select(state => state.streamsstatemodel.streams) streamElements$: Observable; constructor( @@ -59,7 +61,7 @@ export class AppComponent implements OnInit, OnDestroy { } ngOnInit(): void { - this.paramsSub = this.activatedRoute.queryParams.subscribe(params => { + this.paramsSub = this.activatedRoute.queryParams.subscribe(params => { const code = params['code']; if (!code) { return; @@ -76,10 +78,10 @@ export class AppComponent implements OnInit, OnDestroy { let usedTokenData: TokenData; this.authService.getToken(appDataWrapper.instance, appInfo.app.client_id, appInfo.app.client_secret, code, appInfo.app.redirect_uri) .then((tokenData: TokenData) => { - - if(tokenData.refresh_token && !tokenData.created_at){ + + if (tokenData.refresh_token && !tokenData.created_at) { const nowEpoch = Date.now() / 1000 | 0; - tokenData.created_at = nowEpoch; + tokenData.created_at = nowEpoch; } usedTokenData = tokenData; @@ -87,17 +89,17 @@ export class AppComponent implements OnInit, OnDestroy { return this.mastodonService.retrieveAccountDetails({ 'instance': appDataWrapper.instance, 'id': '', 'username': '', 'order': 0, 'isSelected': true, 'token': tokenData }); }) .then((account: Account) => { - var username = account.username.toLowerCase(); + var username = account.username.toLowerCase(); var instance = appDataWrapper.instance.toLowerCase(); - if(this.isAccountAlreadyPresent(username, instance)){ + if (this.isAccountAlreadyPresent(username, instance)) { this.notificationService.notify(null, null, `Account @${username}@${instance} is already registered`, true); this.router.navigate(['/']); return; } const accountInfo = new AccountInfo(); - accountInfo.username = username; + accountInfo.username = username; accountInfo.instance = instance; accountInfo.token = usedTokenData; @@ -114,7 +116,9 @@ export class AppComponent implements OnInit, OnDestroy { }); this.updateAvailableSub = this.serviceWorkerService.newAppVersionIsAvailable.subscribe((updateAvailable) => { - this.updateAvailable = updateAvailable; + if(updateAvailable){ + this.showAutoUpdate(); + } }); this.streamSub = this.streamElements$.subscribe((streams: StreamElement[]) => { @@ -199,15 +203,28 @@ export class AppComponent implements OnInit, OnDestroy { return false; } - closeAutoUpdate(): boolean { - this.updateAvailable = false; + showAutoUpdate(): boolean { + this.showUpdate = true; + setTimeout(() => { + this.updateAvailable = true; + }, 200); + return false; } - private isAccountAlreadyPresent(username: string, instance: string): boolean{ + closeAutoUpdate(): boolean { + this.updateAvailable = false; + setTimeout(() => { + this.showUpdate = false; + }, 250); + + return false; + } + + private isAccountAlreadyPresent(username: string, instance: string): boolean { const accounts = this.store.snapshot().registeredaccounts.accounts; for (let acc of accounts) { - if(acc.instance === instance && acc.username == username){ + if (acc.instance === instance && acc.username == username) { return true; } } From e064297187b4c59abcdd4ea22eec290d36ea6a86 Mon Sep 17 00:00:00 2001 From: Nicolas Constant Date: Thu, 30 Apr 2020 22:38:16 -0400 Subject: [PATCH 09/17] use restart notification for settings changes --- src/app/app.component.html | 4 +- src/app/app.component.ts | 45 ++++++++++--------- .../settings/settings.component.html | 12 ----- .../settings/settings.component.ts | 33 +++++++------- src/app/services/notification.service.ts | 5 +++ src/app/services/service-worker.service.ts | 14 +++--- 6 files changed, 56 insertions(+), 57 deletions(-) diff --git a/src/app/app.component.html b/src/app/app.component.html index ec1a6820..fd202f74 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -10,9 +10,9 @@
-
+
-
A new version is available!
reload +
{{restartNotificationLabel}}
reload
diff --git a/src/app/app.component.ts b/src/app/app.component.ts index c3b7eaa9..4b70a8b9 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -33,8 +33,9 @@ export class AppComponent implements OnInit, OnDestroy { tutorialActive: boolean; openedMediaEvent: OpenMediaEvent - updateAvailable: boolean; - showUpdate: boolean; + restartNotificationLabel: string; + restartNotificationAvailable: boolean; + showRestartNotification: boolean; private authStorageKey: string = 'tempAuth'; @@ -42,8 +43,8 @@ export class AppComponent implements OnInit, OnDestroy { private openMediaSub: Subscription; private streamSub: Subscription; private dragoverSub: Subscription; - private updateAvailableSub: Subscription; private paramsSub: Subscription; + private restartNotificationSub: Subscription; @Select(state => state.streamsstatemodel.streams) streamElements$: Observable; @@ -54,7 +55,7 @@ export class AppComponent implements OnInit, OnDestroy { private readonly mastodonService: MastodonWrapperService, private readonly authService: AuthService, private readonly activatedRoute: ActivatedRoute, - private readonly serviceWorkerService: ServiceWorkerService, + private readonly serviceWorkerService: ServiceWorkerService, // Ensure update checks private readonly toolsService: ToolsService, private readonly mediaService: MediaService, private readonly navigationService: NavigationService) { @@ -115,12 +116,6 @@ export class AppComponent implements OnInit, OnDestroy { }); }); - this.updateAvailableSub = this.serviceWorkerService.newAppVersionIsAvailable.subscribe((updateAvailable) => { - if(updateAvailable){ - this.showAutoUpdate(); - } - }); - this.streamSub = this.streamElements$.subscribe((streams: StreamElement[]) => { if (streams && streams.length === 0) { this.tutorialActive = true; @@ -151,7 +146,13 @@ export class AppComponent implements OnInit, OnDestroy { ) .subscribe(() => { this.drag = false; - }) + }); + + this.restartNotificationSub = this.notificationService.restartNotificationStream.subscribe((label: string) => { + if (label) { + this.displayRestartNotification(label); + } + }); } ngOnDestroy(): void { @@ -159,8 +160,8 @@ export class AppComponent implements OnInit, OnDestroy { this.columnEditorSub.unsubscribe(); this.openMediaSub.unsubscribe(); this.dragoverSub.unsubscribe(); - this.updateAvailableSub.unsubscribe(); this.paramsSub.unsubscribe(); + this.restartNotificationSub.unsubscribe(); } closeMedia() { @@ -199,25 +200,27 @@ export class AppComponent implements OnInit, OnDestroy { } loadNewVersion(): boolean { - this.serviceWorkerService.loadNewAppVersion(); + document.location.reload(); + // this.serviceWorkerService.loadNewAppVersion(); return false; } - showAutoUpdate(): boolean { - this.showUpdate = true; + displayRestartNotification(label: string): boolean { + this.restartNotificationLabel = label; + this.showRestartNotification = true; setTimeout(() => { - this.updateAvailable = true; + this.restartNotificationAvailable = true; }, 200); return false; } - closeAutoUpdate(): boolean { - this.updateAvailable = false; + closeRestartNotification(): boolean { + this.restartNotificationAvailable = false; setTimeout(() => { - this.showUpdate = false; - }, 250); - + this.showRestartNotification = false; + }, 250); + return false; } diff --git a/src/app/components/floating-column/settings/settings.component.html b/src/app/components/floating-column/settings/settings.component.html index 039ab411..8977c6a0 100644 --- a/src/app/components/floating-column/settings/settings.component.html +++ b/src/app/components/floating-column/settings/settings.component.html @@ -48,9 +48,6 @@ type="radio" name="colmun-win" value="colmun-win" id="colmun-win">
- - this settings needs a reload to be effective.

Content-Warning Policies

@@ -90,9 +87,6 @@ - -
this settings needs a reload to be effective.

Timelines

@@ -123,9 +117,6 @@
- this settings needs a reload to be effective. - loading behavior:

- - this settings needs a reload to be effective.

Other

diff --git a/src/app/components/floating-column/settings/settings.component.ts b/src/app/components/floating-column/settings/settings.component.ts index b8aacd77..b3a1b072 100644 --- a/src/app/components/floating-column/settings/settings.component.ts +++ b/src/app/components/floating-column/settings/settings.component.ts @@ -7,6 +7,7 @@ import { ToolsService } from '../../../services/tools.service'; import { UserNotificationService, NotificationSoundDefinition } from '../../../services/user-notification.service'; import { ServiceWorkerService } from '../../../services/service-worker.service'; import { ContentWarningPolicy, ContentWarningPolicyEnum, TimeLineModeEnum, TimeLineHeaderEnum } from '../../../states/settings.state'; +import { NotificationService } from '../../../services/notification.service'; @Component({ selector: 'app-settings', @@ -27,16 +28,9 @@ export class SettingsComponent implements OnInit { version: string; columnShortcutEnabled: ColumnShortcut = ColumnShortcut.Ctrl; - columnShortcutChanged = false; - timeLineHeader: TimeLineHeaderEnum = TimeLineHeaderEnum.Title_DomainName; - timeLineHeaderChanged = false; - timeLineMode: TimeLineModeEnum = TimeLineModeEnum.OnTop; - timeLineModeChanged = false; - contentWarningPolicy: ContentWarningPolicyEnum = ContentWarningPolicyEnum.None; - contentWarningPolicyChanged = false; private addCwOnContent: string; set setAddCwOnContent(value: string) { @@ -69,6 +63,7 @@ export class SettingsComponent implements OnInit { private formBuilder: FormBuilder, private serviceWorkersService: ServiceWorkerService, private readonly toolsService: ToolsService, + private readonly notificationService: NotificationService, private readonly userNotificationsService: UserNotificationService) { } ngOnInit() { @@ -104,7 +99,7 @@ export class SettingsComponent implements OnInit { onShortcutChange(id: ColumnShortcut) { this.columnShortcutEnabled = id; - this.columnShortcutChanged = true; + this.notifyRestartNeeded(); let settings = this.toolsService.getSettings(); settings.columnSwitchingWinAlt = id === ColumnShortcut.Win; @@ -113,7 +108,7 @@ export class SettingsComponent implements OnInit { onTimeLineHeaderChange(id: TimeLineHeaderEnum){ this.timeLineHeader = id; - this.timeLineHeaderChanged = true; + this.notifyRestartNeeded(); let settings = this.toolsService.getSettings(); settings.timelineHeader = id; @@ -122,7 +117,7 @@ export class SettingsComponent implements OnInit { onTimeLineModeChange(id: TimeLineModeEnum){ this.timeLineMode = id; - this.timeLineModeChanged = true; + this.notifyRestartNeeded(); let settings = this.toolsService.getSettings(); settings.timelineMode = id; @@ -131,13 +126,13 @@ export class SettingsComponent implements OnInit { onCwPolicyChange(id: ContentWarningPolicyEnum) { this.contentWarningPolicy = id; - this.contentWarningPolicyChanged = true; + this.notifyRestartNeeded(); this.setCwPolicy(id); } private setCwPolicy(id: ContentWarningPolicyEnum = null, addCw: string = null, removeCw: string = null, hide: string = null){ - this.contentWarningPolicyChanged = true; + this.notifyRestartNeeded(); let settings = this.toolsService.getSettings(); let cwPolicySettings = new ContentWarningPolicy(); @@ -172,10 +167,10 @@ export class SettingsComponent implements OnInit { return data.split(';').map(x => x.trim().toLowerCase()).filter((value, index, self) => self.indexOf(value) === index).filter(y => y !== ''); } - reload(): boolean { - window.location.reload(); - return false; - } + // reload(): boolean { + // window.location.reload(); + // return false; + // } onChange(soundId: string) { this.notificationSoundId = soundId; @@ -196,6 +191,7 @@ export class SettingsComponent implements OnInit { } onDisableAutofocusChanged() { + this.notifyRestartNeeded(); let settings = this.toolsService.getSettings(); settings.disableAutofocus = this.disableAutofocusEnabled; this.toolsService.saveSettings(settings); @@ -208,6 +204,7 @@ export class SettingsComponent implements OnInit { } onDisableAvatarNotificationsChanged() { + this.notifyRestartNeeded(); let settings = this.toolsService.getSettings(); settings.disableAvatarNotifications = this.disableAvatarNotificationsEnabled; this.toolsService.saveSettings(settings); @@ -248,6 +245,10 @@ export class SettingsComponent implements OnInit { }); return false; } + + notifyRestartNeeded(){ + this.notificationService.notifyRestartNotification('Reload to apply changes'); + } } enum ColumnShortcut { diff --git a/src/app/services/notification.service.ts b/src/app/services/notification.service.ts index a8406bce..80696dad 100644 --- a/src/app/services/notification.service.ts +++ b/src/app/services/notification.service.ts @@ -9,6 +9,7 @@ import { ToolsService } from './tools.service'; @Injectable() export class NotificationService { + public restartNotificationStream = new Subject(); public notifactionStream = new Subject(); public newRespondPostedStream = new Subject(); public hideAccountUrlStream = new Subject(); @@ -60,6 +61,10 @@ export class NotificationService { public deleteStatus(status: StatusWrapper) { this.deletedStatusStream.next(status); } + + public notifyRestartNotification(label: string){ + this.restartNotificationStream.next(label); + } } export class NotificatioData { diff --git a/src/app/services/service-worker.service.ts b/src/app/services/service-worker.service.ts index f5dfc761..6b477517 100644 --- a/src/app/services/service-worker.service.ts +++ b/src/app/services/service-worker.service.ts @@ -1,17 +1,19 @@ import { Injectable, ApplicationRef } from '@angular/core'; import { SwUpdate } from '@angular/service-worker'; -import { first } from 'rxjs/operators'; import { interval, concat, BehaviorSubject } from 'rxjs'; +import { NotificationService } from './notification.service'; + @Injectable({ providedIn: 'root' }) export class ServiceWorkerService { - newAppVersionIsAvailable = new BehaviorSubject(false); - private isListening = false; - constructor(appRef: ApplicationRef, private updates: SwUpdate) { + constructor( + appRef: ApplicationRef, + private updates: SwUpdate, + private notificationService: NotificationService) { //https://angular.io/guide/service-worker-communications @@ -19,7 +21,7 @@ export class ServiceWorkerService { console.log('current version is', event.current); console.log('available version is', event.available); - this.newAppVersionIsAvailable.next(true); + this.notificationService.notifyRestartNotification('A new version is available!'); }); // Allow the app to stabilize first, before starting polling for updates with `interval()`. @@ -47,6 +49,6 @@ export class ServiceWorkerService { } checkForUpdates(): Promise { - return this.updates.checkForUpdate(); + return this.updates.checkForUpdate(); } } \ No newline at end of file From 586aef214c8b3f2c41e743446ca034b4e88f16a0 Mon Sep 17 00:00:00 2001 From: Nicolas Constant Date: Thu, 30 Apr 2020 22:40:52 -0400 Subject: [PATCH 10/17] remote fetching needs restart --- .../components/floating-column/settings/settings.component.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/app/components/floating-column/settings/settings.component.ts b/src/app/components/floating-column/settings/settings.component.ts index b3a1b072..190a0c56 100644 --- a/src/app/components/floating-column/settings/settings.component.ts +++ b/src/app/components/floating-column/settings/settings.component.ts @@ -198,6 +198,7 @@ export class SettingsComponent implements OnInit { } onDisableRemoteStatusFetchingChanged() { + this.notifyRestartNeeded(); let settings = this.toolsService.getSettings(); settings.disableRemoteStatusFetching = this.disableRemoteStatusFetchingEnabled; this.toolsService.saveSettings(settings); From 8d9895b0c9a2c461f416d5df191a8387b6c7a309 Mon Sep 17 00:00:00 2001 From: Nicolas Constant Date: Fri, 1 May 2020 01:32:25 -0400 Subject: [PATCH 11/17] fix list flicking in account panel --- .../my-account/my-account.component.ts | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/app/components/floating-column/manage-account/my-account/my-account.component.ts b/src/app/components/floating-column/manage-account/my-account/my-account.component.ts index 43a54251..be469978 100644 --- a/src/app/components/floating-column/manage-account/my-account/my-account.component.ts +++ b/src/app/components/floating-column/manage-account/my-account/my-account.component.ts @@ -104,18 +104,22 @@ export class MyAccountComponent implements OnInit, OnDestroy { } }); - this.availableLists.length = 0; + // this.availableLists.length = 0; this.mastodonService.getLists(account.info) .then((streams: StreamElement[]) => { - this.availableLists.length = 0; + // this.availableLists.length = 0; for (let stream of streams) { - let wrappedStream = new StreamWrapper(stream); + let wrappedStream = this.availableLists.find(x => x.id === stream.id); + if(!wrappedStream){ + wrappedStream = new StreamWrapper(stream); + this.availableLists.push(wrappedStream); + } + if(loadedStreams.find(x => x.id == stream.id)){ wrappedStream.isAdded = true; } else { wrappedStream.isAdded = false; - } - this.availableLists.push(wrappedStream); + } } }) .catch(err => { From 51ef48150fb7128e1a43b23c908467917d5ec685 Mon Sep 17 00:00:00 2001 From: Nicolas Constant Date: Fri, 1 May 2020 02:45:10 -0400 Subject: [PATCH 12/17] added remove button UI --- .../my-account/my-account.component.html | 30 ++++++++++------- .../my-account/my-account.component.scss | 33 ++++++++++++++++++- 2 files changed, 51 insertions(+), 12 deletions(-) diff --git a/src/app/components/floating-column/manage-account/my-account/my-account.component.html b/src/app/components/floating-column/manage-account/my-account/my-account.component.html index b18a8fea..fcc99981 100644 --- a/src/app/components/floating-column/manage-account/my-account/my-account.component.html +++ b/src/app/components/floating-column/manage-account/my-account/my-account.component.html @@ -1,11 +1,16 @@