diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 24f67ffe..3eccb04b 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -34,6 +34,7 @@ import { FloatingColumnComponent } from './components/floating-column/floating-c import { StreamsState } from "./states/streams.state"; import { StatusComponent } from "./components/stream/status/status.component"; import { MastodonService } from "./services/mastodon.service"; +import { MastodonWrapperService } from "./services/mastodon-wrapper.service"; import { AttachementsComponent } from './components/stream/status/attachements/attachements.component'; import { SettingsComponent } from './components/floating-column/settings/settings.component'; import { AddNewAccountComponent } from './components/floating-column/add-new-account/add-new-account.component'; @@ -163,7 +164,7 @@ const routes: Routes = [ ContextMenuModule.forRoot(), HotkeyModule.forRoot() ], - providers: [AuthService, NavigationService, NotificationService, MastodonService, StreamingService], + providers: [AuthService, NavigationService, NotificationService, MastodonWrapperService, MastodonService, StreamingService], bootstrap: [AppComponent], schemas: [CUSTOM_ELEMENTS_SCHEMA] }) diff --git a/src/app/components/create-status/autosuggest/autosuggest.component.ts b/src/app/components/create-status/autosuggest/autosuggest.component.ts index 4dd404d3..42dfb08f 100644 --- a/src/app/components/create-status/autosuggest/autosuggest.component.ts +++ b/src/app/components/create-status/autosuggest/autosuggest.component.ts @@ -1,7 +1,7 @@ import { Component, OnInit, Input, Output, EventEmitter, OnDestroy } from '@angular/core'; import { ToolsService } from '../../../services/tools.service'; -import { MastodonService } from '../../../services/mastodon.service'; +import { MastodonWrapperService } from '../../../services/mastodon-wrapper.service'; import { NotificationService } from '../../../services/notification.service'; import { Results, Account } from '../../../services/models/mastodon.interfaces'; import { Actions } from '@ngxs/store'; @@ -44,7 +44,7 @@ export class AutosuggestComponent implements OnInit, OnDestroy { constructor( private readonly notificationService: NotificationService, private readonly toolsService: ToolsService, - private readonly mastodonService: MastodonService) { } + private readonly mastodonService: MastodonWrapperService) { } ngOnInit() { if (this.autoSuggestUserActionsStream) { diff --git a/src/app/components/create-status/create-status.component.html b/src/app/components/create-status/create-status.component.html index a9d729f7..21b858f4 100644 --- a/src/app/components/create-status/create-status.component.html +++ b/src/app/components/create-status/create-status.component.html @@ -21,9 +21,9 @@ (suggestionSelectedEvent)="suggestionSelected($event)" (hasSuggestionsEvent)="suggestionsChanged($event)"> - + - + diff --git a/src/app/components/create-status/create-status.component.ts b/src/app/components/create-status/create-status.component.ts index b379f0fc..6a996ca1 100644 --- a/src/app/components/create-status/create-status.component.ts +++ b/src/app/components/create-status/create-status.component.ts @@ -7,9 +7,10 @@ import { faPaperclip, faGlobe, faGlobeAmericas, faLock, faLockOpen, faEnvelope, import { faClock, faWindowClose as faWindowCloseRegular } from "@fortawesome/free-regular-svg-icons"; import { ContextMenuService, ContextMenuComponent } from 'ngx-contextmenu'; -import { MastodonService, VisibilityEnum, PollParameters } from '../../services/mastodon.service'; +import { VisibilityEnum, PollParameters } from '../../services/mastodon.service'; +import { MastodonWrapperService } from '../../services/mastodon-wrapper.service'; import { Status, Attachment } from '../../services/models/mastodon.interfaces'; -import { ToolsService } from '../../services/tools.service'; +import { ToolsService, InstanceInfo, InstanceType } from '../../services/tools.service'; import { NotificationService } from '../../services/notification.service'; import { StatusWrapper } from '../../models/common.model'; import { AccountInfo } from '../../states/accounts.state'; @@ -109,6 +110,8 @@ export class CreateStatusComponent implements OnInit, OnDestroy { isSending: boolean; mentionTooFarAwayError: boolean; autosuggestData: string = null; + instanceSupportsPoll = true; + instanceSupportsScheduling = true; private statusLoaded: boolean; private hasSuggestions: boolean; @@ -160,7 +163,7 @@ export class CreateStatusComponent implements OnInit, OnDestroy { private readonly store: Store, private readonly notificationService: NotificationService, private readonly toolsService: ToolsService, - private readonly mastodonService: MastodonService, + private readonly mastodonService: MastodonWrapperService, private readonly instancesInfoService: InstancesInfoService, private readonly mediaService: MediaService, private readonly overlay: Overlay, @@ -322,6 +325,19 @@ export class CreateStatusComponent implements OnInit, OnDestroy { if (!this.statusReplyingToWrapper && !this.replyingUserHandle) { this.getDefaultPrivacy(); } + + this.toolsService.getInstanceInfo(this.selectedAccount) + .then((instance: InstanceInfo) => { + if(instance.type === InstanceType.Pixelfed){ + this.instanceSupportsPoll = false; + this.instanceSupportsScheduling = false; + this.pollIsActive = false; + this.scheduleIsActive = false; + } else { + this.instanceSupportsPoll = true; + this.instanceSupportsScheduling = true; + } + }); } } 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 ed6aed28..31966c44 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 @@ -5,7 +5,7 @@ import { AccountWrapper } from '../../../../models/account.models'; import { OpenThreadEvent } from '../../../../services/tools.service'; import { StatusWrapper } from '../../../../models/common.model'; import { NotificationService } from '../../../../services/notification.service'; -import { MastodonService } from '../../../../services/mastodon.service'; +import { MastodonWrapperService } from '../../../../services/mastodon-wrapper.service'; import { Conversation } from '../../../../services/models/mastodon.interfaces'; import { AccountInfo } from '../../../../states/accounts.state'; @@ -43,7 +43,7 @@ export class DirectMessagesComponent implements OnInit { constructor( private readonly notificationService: NotificationService, - private readonly mastodonService: MastodonService) { } + private readonly mastodonService: MastodonWrapperService) { } ngOnInit() { } 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 9d9bf4bc..fa869b92 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 @@ -3,7 +3,8 @@ import { Component, OnInit, Output, EventEmitter, Input, ViewChild, ElementRef } import { StatusWrapper } from '../../../../models/common.model'; import { OpenThreadEvent } from '../../../../services/tools.service'; import { AccountWrapper } from '../../../../models/account.models'; -import { MastodonService, FavoriteResult } from '../../../../services/mastodon.service'; +import { FavoriteResult } from '../../../../services/mastodon.service'; +import { MastodonWrapperService } from '../../../../services/mastodon-wrapper.service'; import { Status } from '../../../../services/models/mastodon.interfaces'; import { NotificationService } from '../../../../services/notification.service'; import { resetCompiledComponents } from '@angular/core/src/render3/jit/module'; @@ -41,7 +42,7 @@ export class FavoritesComponent implements OnInit { constructor( private readonly notificationService: NotificationService, - private readonly mastodonService: MastodonService) { } + private readonly mastodonService: MastodonWrapperService) { } ngOnInit() { } 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 3f80c0fd..08bb5525 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 @@ -6,7 +6,7 @@ import { Subscription } from 'rxjs'; import { AccountWrapper } from '../../../models/account.models'; import { UserNotificationService, UserNotification } from '../../../services/user-notification.service'; import { OpenThreadEvent } from '../../../services/tools.service'; -import { MastodonService } from '../../../services/mastodon.service'; +import { MastodonWrapperService } from '../../../services/mastodon-wrapper.service'; import { Account } from "../../../services/models/mastodon.interfaces"; import { NotificationService } from '../../../services/notification.service'; import { AccountInfo } from '../../../states/accounts.state'; @@ -49,7 +49,7 @@ export class ManageAccountComponent implements OnInit, OnDestroy { private _account: AccountWrapper; constructor( - private readonly mastodonService: MastodonService, + private readonly mastodonService: MastodonWrapperService, private readonly notificationService: NotificationService, private readonly userNotificationService: UserNotificationService) { } 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 a7749962..008bc47d 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 @@ -5,7 +5,7 @@ import { AccountWrapper } from '../../../../models/account.models'; import { UserNotificationService, UserNotification } from '../../../../services/user-notification.service'; import { StatusWrapper } from '../../../../models/common.model'; import { Status, Notification } from '../../../../services/models/mastodon.interfaces'; -import { MastodonService } from '../../../../services/mastodon.service'; +import { MastodonWrapperService } from '../../../../services/mastodon-wrapper.service'; import { NotificationService } from '../../../../services/notification.service'; import { OpenThreadEvent } from '../../../../services/tools.service'; @@ -45,7 +45,7 @@ export class MentionsComponent implements OnInit, OnDestroy { constructor( private readonly notificationService: NotificationService, private readonly userNotificationService: UserNotificationService, - private readonly mastodonService: MastodonService) { + private readonly mastodonService: MastodonWrapperService) { } diff --git a/src/app/components/floating-column/manage-account/my-account/list-editor/list-editor.component.ts b/src/app/components/floating-column/manage-account/my-account/list-editor/list-editor.component.ts index 9c6c447b..f6cb4e04 100644 --- a/src/app/components/floating-column/manage-account/my-account/list-editor/list-editor.component.ts +++ b/src/app/components/floating-column/manage-account/my-account/list-editor/list-editor.component.ts @@ -2,7 +2,7 @@ import { Component, OnInit, Input } from '@angular/core'; import { faTimes } from "@fortawesome/free-solid-svg-icons"; import { StreamWrapper } from '../my-account.component'; -import { MastodonService } from '../../../../../services/mastodon.service'; +import { MastodonWrapperService } from '../../../../../services/mastodon-wrapper.service'; import { AccountWrapper } from '../../../../../models/account.models'; import { NotificationService } from '../../../../../services/notification.service'; import { Account, Relationship, Instance } from "../../../../../services/models/mastodon.interfaces"; @@ -26,7 +26,7 @@ export class ListEditorComponent implements OnInit { constructor( private readonly notificationService: NotificationService, - private readonly mastodonService: MastodonService) { } + private readonly mastodonService: MastodonWrapperService) { } ngOnInit() { this.accountsInList.length = 0; 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 b35ed2d5..5b030b32 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 @@ -9,7 +9,7 @@ import { StreamElement, StreamTypeEnum, AddStream, RemoveAllStreams, RemoveStrea import { AccountWrapper } from '../../../../models/account.models'; import { RemoveAccount } from '../../../../states/accounts.state'; import { NavigationService } from '../../../../services/navigation.service'; -import { MastodonService } from '../../../../services/mastodon.service'; +import { MastodonWrapperService } from '../../../../services/mastodon-wrapper.service'; import { ToolsService } from '../../../../services/tools.service'; import { AccountSettings } from '../../../../states/settings.state'; @@ -51,7 +51,7 @@ export class MyAccountComponent implements OnInit, OnDestroy { private readonly store: Store, private readonly toolsService: ToolsService, private readonly navigationService: NavigationService, - private readonly mastodonService: MastodonService, + private readonly mastodonService: MastodonWrapperService, private readonly notificationService: NotificationService) { } ngOnInit() { 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 bdb4f54a..ea303526 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 @@ -7,7 +7,7 @@ import { AccountWrapper } from '../../../../models/account.models'; import { UserNotificationService, UserNotification } from '../../../../services/user-notification.service'; import { StatusWrapper } from '../../../../models/common.model'; import { Notification, Account } from '../../../../services/models/mastodon.interfaces'; -import { MastodonService } from '../../../../services/mastodon.service'; +import { MastodonWrapperService } from '../../../../services/mastodon-wrapper.service'; import { NotificationService } from '../../../../services/notification.service'; import { AccountInfo } from '../../../../states/accounts.state'; import { OpenThreadEvent, ToolsService } from '../../../../services/tools.service'; @@ -49,7 +49,7 @@ export class NotificationsComponent implements OnInit, OnDestroy { private readonly toolsService: ToolsService, private readonly notificationService: NotificationService, private readonly userNotificationService: UserNotificationService, - private readonly mastodonService: MastodonService) { } + private readonly mastodonService: MastodonWrapperService) { } ngOnInit() { } diff --git a/src/app/components/floating-column/scheduled-statuses/scheduled-status/scheduled-status.component.ts b/src/app/components/floating-column/scheduled-statuses/scheduled-status/scheduled-status.component.ts index c93fa1fe..a7be57ae 100644 --- a/src/app/components/floating-column/scheduled-statuses/scheduled-status/scheduled-status.component.ts +++ b/src/app/components/floating-column/scheduled-statuses/scheduled-status/scheduled-status.component.ts @@ -3,7 +3,7 @@ import { Component, OnInit, Input, ViewChild, Output, EventEmitter } from '@angu import { AccountInfo } from '../../../../states/accounts.state'; import { ScheduledStatus } from '../../../../services/models/mastodon.interfaces'; import { ToolsService } from '../../../../services/tools.service'; -import { MastodonService } from '../../../../services/mastodon.service'; +import { MastodonWrapperService } from '../../../../services/mastodon-wrapper.service'; import { NotificationService } from '../../../../services/notification.service'; import { ScheduledStatusService } from '../../../../services/scheduled-status.service'; import { StatusSchedulerComponent } from '../../../../components/create-status/status-scheduler/status-scheduler.component'; @@ -28,7 +28,7 @@ export class ScheduledStatusComponent implements OnInit { constructor( private readonly scheduledStatusService: ScheduledStatusService, private readonly notificationService: NotificationService, - private readonly mastodonService: MastodonService, + private readonly mastodonService: MastodonWrapperService, private readonly toolsService: ToolsService) { } ngOnInit() { diff --git a/src/app/components/floating-column/search/search.component.ts b/src/app/components/floating-column/search/search.component.ts index 137646b9..e54b837f 100644 --- a/src/app/components/floating-column/search/search.component.ts +++ b/src/app/components/floating-column/search/search.component.ts @@ -1,7 +1,7 @@ import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core'; import { HttpErrorResponse } from '@angular/common/http'; -import { MastodonService } from '../../../services/mastodon.service'; +import { MastodonWrapperService } from '../../../services/mastodon-wrapper.service'; import { AccountInfo } from '../../../states/accounts.state'; import { Results, Account } from '../../../services/models/mastodon.interfaces'; import { ToolsService, OpenThreadEvent } from '../../../services/tools.service'; @@ -29,7 +29,7 @@ export class SearchComponent implements OnInit { constructor( private readonly notificationService: NotificationService, private readonly toolsService: ToolsService, - private readonly mastodonService: MastodonService) { } + private readonly mastodonService: MastodonWrapperService) { } ngOnInit() { } diff --git a/src/app/components/stream/status/action-bar/action-bar.component.ts b/src/app/components/stream/status/action-bar/action-bar.component.ts index 0c0f41ff..68bc2fe3 100644 --- a/src/app/components/stream/status/action-bar/action-bar.component.ts +++ b/src/app/components/stream/status/action-bar/action-bar.component.ts @@ -5,7 +5,7 @@ import { Observable, Subscription } from 'rxjs'; import { faWindowClose, faReply, faRetweet, faStar, faEllipsisH, faLock, faEnvelope } from "@fortawesome/free-solid-svg-icons"; import { faWindowClose as faWindowCloseRegular } from "@fortawesome/free-regular-svg-icons"; -import { MastodonService } from '../../../../services/mastodon.service'; +import { MastodonWrapperService } from '../../../../services/mastodon-wrapper.service'; import { AccountInfo } from '../../../../states/accounts.state'; import { Status, Account, Results } from '../../../../services/models/mastodon.interfaces'; import { ToolsService, OpenThreadEvent } from '../../../../services/tools.service'; @@ -59,7 +59,7 @@ export class ActionBarComponent implements OnInit, OnDestroy { constructor( private readonly store: Store, private readonly toolsService: ToolsService, - private readonly mastodonService: MastodonService, + private readonly mastodonService: MastodonWrapperService, private readonly notificationService: NotificationService) { this.accounts$ = this.store.select(state => state.registeredaccounts.accounts); @@ -155,7 +155,11 @@ export class ActionBarComponent implements OnInit, OnDestroy { if (boostedStatus.pleroma) { this.bootedStatePerAccountId[account.id] = boostedStatus.reblog !== null; //FIXME: when Pleroma will return the good status } else { - this.bootedStatePerAccountId[account.id] = boostedStatus.reblogged; + let reblogged = boostedStatus.reblogged; //FIXME: when pixelfed will return the good status + if(reblogged === null){ + reblogged = !this.bootedStatePerAccountId[account.id]; + } + this.bootedStatePerAccountId[account.id] = reblogged; } this.checkIfBoosted(); @@ -187,9 +191,12 @@ export class ActionBarComponent implements OnInit, OnDestroy { } }) .then((favoritedStatus: Status) => { - this.favoriteStatePerAccountId[account.id] = favoritedStatus.favourited; + let favourited = favoritedStatus.favourited; //FIXME: when pixelfed will return the good status + if(favourited === null){ + favourited = !this.favoriteStatePerAccountId[account.id]; + } + this.favoriteStatePerAccountId[account.id] = favourited; this.checkIfFavorited(); - // this.isFavorited = !this.isFavorited; }) .catch((err: HttpErrorResponse) => { this.notificationService.notifyHttpError(err, account); diff --git a/src/app/components/stream/status/action-bar/status-user-context-menu/status-user-context-menu.component.ts b/src/app/components/stream/status/action-bar/status-user-context-menu/status-user-context-menu.component.ts index 28edbbf3..368a0743 100644 --- a/src/app/components/stream/status/action-bar/status-user-context-menu/status-user-context-menu.component.ts +++ b/src/app/components/stream/status/action-bar/status-user-context-menu/status-user-context-menu.component.ts @@ -9,7 +9,7 @@ import { ToolsService, OpenThreadEvent } from '../../../../../services/tools.ser import { StatusWrapper } from '../../../../../models/common.model'; import { NavigationService } from '../../../../../services/navigation.service'; import { AccountInfo } from '../../../../../states/accounts.state'; -import { MastodonService } from '../../../../../services/mastodon.service'; +import { MastodonWrapperService } from '../../../../../services/mastodon-wrapper.service'; import { NotificationService } from '../../../../../services/notification.service'; @@ -39,7 +39,7 @@ export class StatusUserContextMenuComponent implements OnInit, OnDestroy { constructor( private readonly store: Store, - private readonly mastodonService: MastodonService, + private readonly mastodonService: MastodonWrapperService, private readonly notificationService: NotificationService, private readonly navigationService: NavigationService, private readonly toolsService: ToolsService, diff --git a/src/app/components/stream/status/poll/poll.component.ts b/src/app/components/stream/status/poll/poll.component.ts index 5e4e71ee..6894b7b5 100644 --- a/src/app/components/stream/status/poll/poll.component.ts +++ b/src/app/components/stream/status/poll/poll.component.ts @@ -5,7 +5,7 @@ import { faLock } from "@fortawesome/free-solid-svg-icons"; import { Poll, PollOption, Status } from '../../../../services/models/mastodon.interfaces'; import { AccountInfo } from '../../../../states/accounts.state'; -import { MastodonService } from '../../../../services/mastodon.service'; +import { MastodonWrapperService } from '../../../../services/mastodon-wrapper.service'; import { NotificationService } from '../../../../services/notification.service'; import { ToolsService } from '../../../../services/tools.service'; import { StatusWrapper } from '../../../../models/common.model'; @@ -67,7 +67,7 @@ export class PollComponent implements OnInit { private readonly store: Store, private notificationService: NotificationService, private toolsService: ToolsService, - private mastodonService: MastodonService) { + private mastodonService: MastodonWrapperService) { this.accounts$ = this.store.select(state => state.registeredaccounts.accounts); } 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 af32b6d9..bbe771a2 100644 --- a/src/app/components/stream/stream-statuses/stream-statuses.component.ts +++ b/src/app/components/stream/stream-statuses/stream-statuses.component.ts @@ -7,7 +7,7 @@ import { StreamElement } from '../../../states/streams.state'; import { AccountInfo } from '../../../states/accounts.state'; import { StreamingService, EventEnum, StreamingWrapper, StatusUpdate } from '../../../services/streaming.service'; import { Status } from '../../../services/models/mastodon.interfaces'; -import { MastodonService } from '../../../services/mastodon.service'; +import { MastodonWrapperService } from '../../../services/mastodon-wrapper.service'; import { NotificationService } from '../../../services/notification.service'; import { OpenThreadEvent, ToolsService } from '../../../services/tools.service'; import { StatusWrapper } from '../../../models/common.model'; @@ -67,7 +67,7 @@ export class StreamStatusesComponent implements OnInit, OnDestroy { private readonly toolsService: ToolsService, private readonly notificationService: NotificationService, private readonly streamingService: StreamingService, - private readonly mastodonService: MastodonService) { + private readonly mastodonService: MastodonWrapperService) { this.streams$ = this.store.select(state => state.streamsstatemodel.streams); } diff --git a/src/app/components/stream/thread/thread.component.ts b/src/app/components/stream/thread/thread.component.ts index 5dd3e0a4..32693b61 100644 --- a/src/app/components/stream/thread/thread.component.ts +++ b/src/app/components/stream/thread/thread.component.ts @@ -2,7 +2,7 @@ import { Component, OnInit, OnDestroy, Input, Output, EventEmitter, ViewChildren import { HttpErrorResponse } from '@angular/common/http'; import { Subscription } from 'rxjs'; -import { MastodonService } from '../../../services/mastodon.service'; +import { MastodonWrapperService } from '../../../services/mastodon-wrapper.service'; import { ToolsService, OpenThreadEvent } from '../../../services/tools.service'; import { Results, Context, Status } from '../../../services/models/mastodon.interfaces'; import { NotificationService, NewReplyData } from '../../../services/notification.service'; @@ -51,7 +51,7 @@ export class ThreadComponent implements OnInit, OnDestroy { constructor( private readonly notificationService: NotificationService, private readonly toolsService: ToolsService, - private readonly mastodonService: MastodonService) { } + private readonly mastodonService: MastodonWrapperService) { } ngOnInit() { if (this.refreshEventEmitter) { 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 32a9e592..cd5a35b2 100644 --- a/src/app/components/stream/user-profile/user-profile.component.ts +++ b/src/app/components/stream/user-profile/user-profile.component.ts @@ -6,7 +6,7 @@ import { Observable, Subscription } from 'rxjs'; import { Store } from '@ngxs/store'; import { Account, Status, Relationship, Attachment } from "../../../services/models/mastodon.interfaces"; -import { MastodonService } from '../../../services/mastodon.service'; +import { MastodonWrapperService } from '../../../services/mastodon-wrapper.service'; import { ToolsService, OpenThreadEvent } from '../../../services/tools.service'; import { NotificationService } from '../../../services/notification.service'; import { AccountInfo } from '../../../states/accounts.state'; @@ -77,7 +77,7 @@ export class UserProfileComponent implements OnInit { private readonly store: Store, private readonly navigationService: NavigationService, private readonly notificationService: NotificationService, - private readonly mastodonService: MastodonService, + private readonly mastodonService: MastodonWrapperService, private readonly toolsService: ToolsService) { this.accounts$ = this.store.select(state => state.registeredaccounts.accounts); diff --git a/src/app/pages/register-new-account/register-new-account.component.ts b/src/app/pages/register-new-account/register-new-account.component.ts index 4e905f78..4a1579f4 100644 --- a/src/app/pages/register-new-account/register-new-account.component.ts +++ b/src/app/pages/register-new-account/register-new-account.component.ts @@ -8,7 +8,7 @@ import { TokenData, Account } from "../../services/models/mastodon.interfaces"; import { RegisteredAppsStateModel, AppInfo } from "../../states/registered-apps.state"; import { AccountInfo, AddAccount, AccountsStateModel } from "../../states/accounts.state"; import { NotificationService } from "../../services/notification.service"; -import { MastodonService } from '../../services/mastodon.service'; +import { MastodonWrapperService } from '../../services/mastodon-wrapper.service'; @Component({ selector: "app-register-new-account", @@ -24,7 +24,7 @@ export class RegisterNewAccountComponent implements OnInit { private authStorageKey: string = 'tempAuth'; constructor( - private readonly mastodonService: MastodonService, + private readonly mastodonService: MastodonWrapperService, private readonly notificationService: NotificationService, private readonly authService: AuthService, private readonly store: Store, @@ -50,7 +50,14 @@ export class RegisterNewAccountComponent implements OnInit { 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){ + const nowEpoch = Date.now() / 1000 | 0; + tokenData.created_at = nowEpoch; + } + usedTokenData = tokenData; + return this.mastodonService.retrieveAccountDetails({ 'instance': appDataWrapper.instance, 'id': '', 'username': '', 'order': 0, 'isSelected': true, 'token': tokenData }); }) .then((account: Account) => { @@ -103,7 +110,7 @@ export class RegisterNewAccountComponent implements OnInit { this.errorMessage = 'No authentication code returned. Please retry.' break; } - } + } private getAllSavedApps(): AppInfo[] { const snapshot = this.store.snapshot().registeredapps; diff --git a/src/app/services/auth.service.ts b/src/app/services/auth.service.ts index 1815696d..e99e437d 100644 --- a/src/app/services/auth.service.ts +++ b/src/app/services/auth.service.ts @@ -31,6 +31,20 @@ export class AuthService { return this.httpClient.post(url, bodyLoad).toPromise(); } + refreshToken(instance: string, client_id: string, client_secret: string, refresh_token: string): Promise { + const url = `https://${instance}/oauth/token?client_id=${client_id}&client_secret=${client_secret}&grant_type=refresh_token&refresh_token=${refresh_token}&scope=${encodeURIComponent('read write follow')}`; + + const bodyLoad = { + 'client_id': client_id, + 'client_secret': client_secret, + 'grant_type': 'refresh_token', + 'refresh_token': refresh_token, + 'scope': 'read write follow' + }; + + return this.httpClient.post(url, bodyLoad).toPromise(); + } + createNewApplication(instance: string, appName: string, redirectUrl: string, scopes: string, website: string): Promise { const url = 'https://' + instance + this.apiRoutes.createApp; diff --git a/src/app/services/instances-info.service.ts b/src/app/services/instances-info.service.ts index f024438d..d7cf2aac 100644 --- a/src/app/services/instances-info.service.ts +++ b/src/app/services/instances-info.service.ts @@ -1,6 +1,7 @@ import { Injectable } from '@angular/core'; -import { MastodonService, VisibilityEnum } from './mastodon.service'; +import { VisibilityEnum } from './mastodon.service'; +import { MastodonWrapperService } from './mastodon-wrapper.service'; import { Instance, Account } from './models/mastodon.interfaces'; import { AccountInfo } from '../states/accounts.state'; @@ -12,7 +13,7 @@ export class InstancesInfoService { private cachedMaxInstanceChar: { [id: string]: Promise; } = {}; private cachedDefaultPrivacy: { [id: string]: Promise; } = {}; - constructor(private mastodonService: MastodonService) { } + constructor(private mastodonService: MastodonWrapperService) { } getMaxStatusChars(instance: string): Promise { if (!this.cachedMaxInstanceChar[instance]) { diff --git a/src/app/services/mastodon-wrapper.service.spec.ts b/src/app/services/mastodon-wrapper.service.spec.ts new file mode 100644 index 00000000..da363728 --- /dev/null +++ b/src/app/services/mastodon-wrapper.service.spec.ts @@ -0,0 +1,12 @@ +import { TestBed } from '@angular/core/testing'; + +import { MastodonWrapperService } from './mastodon-wrapper.service'; + +xdescribe('MastodonWrapperService', () => { + beforeEach(() => TestBed.configureTestingModule({})); + + it('should be created', () => { + const service: MastodonWrapperService = TestBed.get(MastodonWrapperService); + expect(service).toBeTruthy(); + }); +}); diff --git a/src/app/services/mastodon-wrapper.service.ts b/src/app/services/mastodon-wrapper.service.ts new file mode 100644 index 00000000..10f38d3f --- /dev/null +++ b/src/app/services/mastodon-wrapper.service.ts @@ -0,0 +1,358 @@ +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 { AccountInfo, UpdateAccount } from '../states/accounts.state'; +import { StreamTypeEnum, StreamElement } from '../states/streams.state'; +import { FavoriteResult, VisibilityEnum, PollParameters, MastodonService } from './mastodon.service'; +import { AuthService } from './auth.service'; +import { AppInfo, RegisteredAppsStateModel } from '../states/registered-apps.state'; + +@Injectable({ + providedIn: 'root' +}) +export class MastodonWrapperService { + + constructor( + private readonly store: Store, + private readonly authService: AuthService, + private readonly mastodonService: MastodonService) { } + + refreshAccountIfNeeded(accountInfo: AccountInfo): Promise { + let isExpired = false; + let storedAccountInfo = this.getStoreAccountInfo(accountInfo.id); + + try { + if (storedAccountInfo.token.refresh_token) { + if (!storedAccountInfo.token.created_at || !storedAccountInfo.token.expires_in) { + isExpired = true; + } else { + const nowEpoch = Date.now() / 1000 | 0; + + //Pleroma workaround + let expire_in = storedAccountInfo.token.expires_in; + if(expire_in < 3600) { + expire_in = 3600; + } + + let expire_on = expire_in + storedAccountInfo.token.created_at; + isExpired = expire_on - nowEpoch <= 60 * 2; + + //console.warn(`expiring in ${Math.round((expire_on - nowEpoch)/24/60/60)}days ${Math.round((expire_on - nowEpoch)/60/60)}h ${Math.round((expire_on - nowEpoch)/60)} mins`); + } + } + } catch (err) { + console.error(err); + } + + if (storedAccountInfo.token.refresh_token && isExpired) { + console.warn('--------------------------'); + console.warn('-------->> MARTY!! -------'); + console.warn('-------->> RENEW TOKEN FFS'); + console.warn('--------------------------'); + + 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) + .then((tokenData: TokenData) => { + if (tokenData.refresh_token && !tokenData.created_at) { + const nowEpoch = Date.now() / 1000 | 0; + tokenData.created_at = nowEpoch; + } + + storedAccountInfo.token = tokenData; + this.store.dispatch([new UpdateAccount(storedAccountInfo)]); + + return storedAccountInfo; + }) + .catch(err => { + return Promise.resolve(storedAccountInfo); + }); + } else { + return Promise.resolve(storedAccountInfo); + } + } + + private getAllSavedApps(): AppInfo[] { + const snapshot = this.store.snapshot().registeredapps; + return snapshot.apps; + } + + private getStoreAccountInfo(accountId: string): AccountInfo { + var regAccounts = this.store.snapshot().registeredaccounts.accounts; + return regAccounts.find(x => x.id === accountId); + } + + getInstance(instance: string): Promise { + return this.mastodonService.getInstance(instance); + } + + retrieveAccountDetails(account: AccountInfo): Promise { + return this.mastodonService.retrieveAccountDetails(account); + } + + getTimeline(account: AccountInfo, type: StreamTypeEnum, max_id: string = null, since_id: string = null, limit: number = 20, tag: string = null, listId: string = null): Promise { + return this.refreshAccountIfNeeded(account) + .then((refreshedAccount: AccountInfo) => { + return this.mastodonService.getTimeline(refreshedAccount, type, max_id, since_id, limit, tag, listId); + }); + } + + getConversations(account: AccountInfo, max_id: string = null, since_id: string = null, min_id = null, limit: number = 20): Promise { + return this.refreshAccountIfNeeded(account) + .then((refreshedAccount: AccountInfo) => { + return this.mastodonService.getConversations(refreshedAccount, max_id, since_id, min_id, limit); + }); + } + + postNewStatus(account: AccountInfo, status: string, visibility: VisibilityEnum, spoiler: string = null, in_reply_to_id: string = null, mediaIds: string[], poll: PollParameters = null, scheduled_at: string = null): Promise { + return this.refreshAccountIfNeeded(account) + .then((refreshedAccount: AccountInfo) => { + return this.mastodonService.postNewStatus(refreshedAccount, status, visibility, spoiler, in_reply_to_id, mediaIds, poll, scheduled_at); + }); + } + + getStatus(account: AccountInfo, statusId: string): Promise { + return this.refreshAccountIfNeeded(account) + .then((refreshedAccount: AccountInfo) => { + return this.mastodonService.getStatus(refreshedAccount, statusId); + }); + } + + search(account: AccountInfo, query: string, version: 'v1' | 'v2', resolve: boolean = false): Promise { + return this.refreshAccountIfNeeded(account) + .then((refreshedAccount: AccountInfo) => { + return this.mastodonService.search(refreshedAccount, query, version, resolve); + }); + } + + getAccountStatuses(account: AccountInfo, targetAccountId: number, onlyMedia: boolean, onlyPinned: boolean, excludeReplies: boolean, maxId: string, sinceId: string, limit: number = 20): Promise { + return this.refreshAccountIfNeeded(account) + .then((refreshedAccount: AccountInfo) => { + return this.mastodonService.getAccountStatuses(refreshedAccount, targetAccountId, onlyMedia, onlyPinned, excludeReplies, maxId, sinceId, limit); + }); + } + + getStatusContext(account: AccountInfo, targetStatusId: string): Promise { + return this.refreshAccountIfNeeded(account) + .then((refreshedAccount: AccountInfo) => { + return this.mastodonService.getStatusContext(refreshedAccount, targetStatusId); + }); + } + + getFavorites(account: AccountInfo, maxId: string = null): Promise { //, minId: string = null + return this.refreshAccountIfNeeded(account) + .then((refreshedAccount: AccountInfo) => { + return this.mastodonService.getFavorites(refreshedAccount, maxId); + }); + } + + searchAccount(account: AccountInfo, query: string, limit: number = 40, following: boolean = false, resolve = true): Promise { + return this.refreshAccountIfNeeded(account) + .then((refreshedAccount: AccountInfo) => { + return this.mastodonService.searchAccount(refreshedAccount, query, limit, following, resolve); + }); + } + + reblog(account: AccountInfo, status: Status): Promise { + return this.refreshAccountIfNeeded(account) + .then((refreshedAccount: AccountInfo) => { + return this.mastodonService.reblog(refreshedAccount, status); + }); + } + + unreblog(account: AccountInfo, status: Status): Promise { + return this.refreshAccountIfNeeded(account) + .then((refreshedAccount: AccountInfo) => { + return this.mastodonService.unreblog(refreshedAccount, status); + }); + } + + favorite(account: AccountInfo, status: Status): Promise { + return this.refreshAccountIfNeeded(account) + .then((refreshedAccount: AccountInfo) => { + return this.mastodonService.favorite(refreshedAccount, status); + }); + } + + unfavorite(account: AccountInfo, status: Status): Promise { + return this.refreshAccountIfNeeded(account) + .then((refreshedAccount: AccountInfo) => { + return this.mastodonService.unfavorite(refreshedAccount, status); + }); + } + + getRelationships(account: AccountInfo, accountsToRetrieve: Account[]): Promise { + return this.refreshAccountIfNeeded(account) + .then((refreshedAccount: AccountInfo) => { + return this.mastodonService.getRelationships(refreshedAccount, accountsToRetrieve); + }); + } + + follow(currentlyUsedAccount: AccountInfo, account: Account): Promise { + return this.refreshAccountIfNeeded(currentlyUsedAccount) + .then((refreshedAccount: AccountInfo) => { + return this.mastodonService.follow(refreshedAccount, account); + }); + } + + unfollow(currentlyUsedAccount: AccountInfo, account: Account): Promise { + return this.refreshAccountIfNeeded(currentlyUsedAccount) + .then((refreshedAccount: AccountInfo) => { + return this.mastodonService.unfollow(refreshedAccount, account); + }); + } + + uploadMediaAttachment(account: AccountInfo, file: File, description: string): Promise { + return this.refreshAccountIfNeeded(account) + .then((refreshedAccount: AccountInfo) => { + return this.mastodonService.uploadMediaAttachment(refreshedAccount, file, description); + }); + } + + updateMediaAttachment(account: AccountInfo, mediaId: string, description: string): Promise { + return this.refreshAccountIfNeeded(account) + .then((refreshedAccount: AccountInfo) => { + return this.mastodonService.updateMediaAttachment(refreshedAccount, mediaId, description); + }); + } + + getNotifications(account: AccountInfo, excludeTypes: string[] = 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); + }); + } + + getLists(account: AccountInfo): Promise { + return this.refreshAccountIfNeeded(account) + .then((refreshedAccount: AccountInfo) => { + return this.mastodonService.getLists(refreshedAccount); + }); + } + + createList(account: AccountInfo, title: string): Promise { + return this.refreshAccountIfNeeded(account) + .then((refreshedAccount: AccountInfo) => { + return this.mastodonService.createList(refreshedAccount, title); + }); + } + + deleteList(account: AccountInfo, listId: string): Promise { + return this.refreshAccountIfNeeded(account) + .then((refreshedAccount: AccountInfo) => { + return this.mastodonService.deleteList(refreshedAccount, listId); + }); + } + + getListAccounts(account: AccountInfo, listId: string): Promise { + return this.refreshAccountIfNeeded(account) + .then((refreshedAccount: AccountInfo) => { + return this.mastodonService.getListAccounts(refreshedAccount, listId); + }); + } + + addAccountToList(account: AccountInfo, listId: string, accountId: number): Promise { + return this.refreshAccountIfNeeded(account) + .then((refreshedAccount: AccountInfo) => { + return this.mastodonService.addAccountToList(refreshedAccount, listId, accountId); + }); + } + + removeAccountFromList(account: AccountInfo, listId: string, accountId: number): Promise { + return this.refreshAccountIfNeeded(account) + .then((refreshedAccount: AccountInfo) => { + return this.mastodonService.removeAccountFromList(refreshedAccount, listId, accountId); + }); + } + + voteOnPoll(account: AccountInfo, pollId: string, pollSelection: number[]): Promise { + return this.refreshAccountIfNeeded(account) + .then((refreshedAccount: AccountInfo) => { + return this.mastodonService.voteOnPoll(refreshedAccount, pollId, pollSelection); + }); + } + + getPoll(account: AccountInfo, pollId: string): Promise { + return this.refreshAccountIfNeeded(account) + .then((refreshedAccount: AccountInfo) => { + return this.mastodonService.getPoll(refreshedAccount, pollId); + }); + } + + mute(account: AccountInfo, accounId: number): Promise { + return this.refreshAccountIfNeeded(account) + .then((refreshedAccount: AccountInfo) => { + return this.mastodonService.mute(refreshedAccount, accounId); + }); + } + + block(account: AccountInfo, accounId: number): Promise { + return this.refreshAccountIfNeeded(account) + .then((refreshedAccount: AccountInfo) => { + return this.mastodonService.block(refreshedAccount, accounId); + }); + } + + pinOnProfile(account: AccountInfo, statusId: string): Promise { + return this.refreshAccountIfNeeded(account) + .then((refreshedAccount: AccountInfo) => { + return this.mastodonService.pinOnProfile(refreshedAccount, statusId); + }); + } + + unpinFromProfile(account: AccountInfo, statusId: string): Promise { + return this.refreshAccountIfNeeded(account) + .then((refreshedAccount: AccountInfo) => { + return this.mastodonService.unpinFromProfile(refreshedAccount, statusId); + }); + } + + muteConversation(account: AccountInfo, statusId: string): Promise { + return this.refreshAccountIfNeeded(account) + .then((refreshedAccount: AccountInfo) => { + return this.mastodonService.muteConversation(refreshedAccount, statusId); + }); + } + + unmuteConversation(account: AccountInfo, statusId: string): Promise { + return this.refreshAccountIfNeeded(account) + .then((refreshedAccount: AccountInfo) => { + return this.mastodonService.unmuteConversation(refreshedAccount, statusId); + }); + } + + deleteStatus(account: AccountInfo, statusId: string): Promise { + return this.refreshAccountIfNeeded(account) + .then((refreshedAccount: AccountInfo) => { + return this.mastodonService.deleteStatus(refreshedAccount, statusId); + }); + } + + getCustomEmojis(account: AccountInfo): Promise { + return this.refreshAccountIfNeeded(account) + .then((refreshedAccount: AccountInfo) => { + return this.mastodonService.getCustomEmojis(refreshedAccount); + }); + } + + getScheduledStatuses(account: AccountInfo): Promise { + return this.refreshAccountIfNeeded(account) + .then((refreshedAccount: AccountInfo) => { + return this.mastodonService.getScheduledStatuses(refreshedAccount); + }); + } + + changeScheduledStatus(account: AccountInfo, statusId: string, scheduled_at: string): Promise { + return this.refreshAccountIfNeeded(account) + .then((refreshedAccount: AccountInfo) => { + return this.mastodonService.changeScheduledStatus(refreshedAccount, statusId, scheduled_at); + }); + } + + deleteScheduledStatus(account: AccountInfo, statusId: string): Promise { + return this.refreshAccountIfNeeded(account) + .then((refreshedAccount: AccountInfo) => { + return this.mastodonService.deleteScheduledStatus(refreshedAccount, statusId); + }); + } +} diff --git a/src/app/services/mastodon.service.ts b/src/app/services/mastodon.service.ts index fb2e52c2..41ada2b6 100644 --- a/src/app/services/mastodon.service.ts +++ b/src/app/services/mastodon.service.ts @@ -28,7 +28,7 @@ export class MastodonService { return this.httpClient.get(route, { headers: headers }).toPromise(); } - getConversations(account: AccountInfo, max_id: string = null, since_id: string = null, min_id = null, limit: number = 20,): Promise { + getConversations(account: AccountInfo, max_id: string = null, since_id: string = null, min_id = null, limit: number = 20): Promise { let params = `?limit=${limit}`; if (max_id) params += `&max_id=${max_id}`; if (since_id) params += `&since_id=${since_id}`; diff --git a/src/app/services/media.service.ts b/src/app/services/media.service.ts index 266e29af..06015580 100644 --- a/src/app/services/media.service.ts +++ b/src/app/services/media.service.ts @@ -3,7 +3,7 @@ import { BehaviorSubject } from 'rxjs'; import { AccountInfo } from '../states/accounts.state'; import { Attachment } from './models/mastodon.interfaces'; -import { MastodonService } from './mastodon.service'; +import { MastodonWrapperService } from './mastodon-wrapper.service'; import { NotificationService } from './notification.service'; @@ -15,7 +15,7 @@ export class MediaService { constructor( private readonly notificationService: NotificationService, - private readonly mastodonService: MastodonService) { } + private readonly mastodonService: MastodonWrapperService) { } uploadMedia(account: AccountInfo, files: File[]) { for (let file of files) { diff --git a/src/app/services/scheduled-status.service.ts b/src/app/services/scheduled-status.service.ts index 68bab4de..70bae01b 100644 --- a/src/app/services/scheduled-status.service.ts +++ b/src/app/services/scheduled-status.service.ts @@ -2,7 +2,7 @@ import { Injectable } from '@angular/core'; import { Store } from '@ngxs/store'; import { BehaviorSubject } from 'rxjs'; -import { MastodonService } from './mastodon.service'; +import { MastodonWrapperService } from './mastodon-wrapper.service'; import { AccountInfo } from '../states/accounts.state'; import { ScheduledStatus } from './models/mastodon.interfaces'; import { NotificationService } from './notification.service'; @@ -15,7 +15,7 @@ export class ScheduledStatusService { constructor( private readonly notificationService: NotificationService, - private readonly mastodonService: MastodonService, + private readonly mastodonService: MastodonWrapperService, private readonly store: Store) { this.fetchScheduledStatus(); @@ -46,7 +46,7 @@ export class ScheduledStatusService { } }) .catch(err => { - this.notificationService.notifyHttpError(err, account); + //this.notificationService.notifyHttpError(err, account); }); } diff --git a/src/app/services/streaming.service.ts b/src/app/services/streaming.service.ts index 0a9cc903..b0cde3ab 100644 --- a/src/app/services/streaming.service.ts +++ b/src/app/services/streaming.service.ts @@ -4,8 +4,9 @@ import { BehaviorSubject } from "rxjs"; import { Status } from "./models/mastodon.interfaces"; import { ApiRoutes } from "./models/api.settings"; import { StreamTypeEnum, StreamElement } from "../states/streams.state"; -import { MastodonService } from "./mastodon.service"; +import { MastodonWrapperService } from "./mastodon-wrapper.service"; import { AccountInfo } from "../states/accounts.state"; +import { AccountIconComponent } from '../components/left-side-bar/account-icon/account-icon.component'; @Injectable() export class StreamingService { @@ -13,7 +14,7 @@ export class StreamingService { public readonly nbStatusPerIteration: number = 20; constructor( - private readonly mastodonService: MastodonService) { } + private readonly mastodonService: MastodonWrapperService) { } getStreaming(accountInfo: AccountInfo, stream: StreamElement): StreamingWrapper { return new StreamingWrapper(this.mastodonService, accountInfo, stream, this.nbStatusPerIteration); @@ -29,13 +30,12 @@ export class StreamingWrapper { private disposed: boolean; constructor( - private readonly mastodonService: MastodonService, + private readonly mastodonService: MastodonWrapperService, private readonly account: AccountInfo, private readonly stream: StreamElement, private readonly nbStatusPerIteration: number) { - const route = this.getRoute(account, stream); - this.start(route); + this.start(account, stream); } dispose(): any { @@ -43,34 +43,41 @@ export class StreamingWrapper { this.eventSource.close(); } - private start(route: string) { - this.eventSource = new WebSocket(route); - this.eventSource.onmessage = x => { - if (x.data !== '') { - this.statusParsing(JSON.parse(x.data)); - } - } - this.eventSource.onerror = x => this.webSocketGotError(x); - this.eventSource.onopen = x => { }; - this.eventSource.onclose = x => this.webSocketClosed(route, x); + private start(account: AccountInfo, stream: StreamElement) { + this.mastodonService.refreshAccountIfNeeded(account) + .catch(err => { + return account; + }) + .then((refreshedAccount: AccountInfo) => { + const route = this.getRoute(refreshedAccount, stream); + this.eventSource = new WebSocket(route); + this.eventSource.onmessage = x => { + if (x.data !== '') { + this.statusParsing(JSON.parse(x.data)); + } + } + this.eventSource.onerror = x => this.webSocketGotError(x); + this.eventSource.onopen = x => { }; + this.eventSource.onclose = x => this.webSocketClosed(refreshedAccount, stream, x); + }); } private webSocketGotError(x: Event) { this.errorClosing = true; } - private webSocketClosed(domain, x: Event) { + private webSocketClosed(account: AccountInfo, stream: StreamElement, x: Event) { if (this.errorClosing) { setTimeout(() => { - this.pullNewStatuses(domain); + this.pullNewStatuses(); this.errorClosing = false; }, 60 * 1000); } else if (!this.disposed) { - setTimeout(() => { this.start(domain) }, 60 * 1000); + setTimeout(() => { this.start(account, stream) }, 60 * 1000); } } - private pullNewStatuses(domain) { + private pullNewStatuses() { this.mastodonService.getTimeline(this.account, this.stream.type, null, this.since_id, this.nbStatusPerIteration, this.stream.tag, this.stream.listId) .then((status: Status[]) => { // status = status.sort((n1, n2) => { return (n1.id) < (n2.id); }); @@ -89,7 +96,7 @@ export class StreamingWrapper { .then(() => { // setTimeout(() => { this.start(domain) }, 20 * 1000); if (!this.disposed) { - setTimeout(() => { this.pullNewStatuses(domain) }, 60 * 1000); + setTimeout(() => { this.pullNewStatuses() }, 60 * 1000); } }); } diff --git a/src/app/services/tools.service.ts b/src/app/services/tools.service.ts index 173eb614..3f1c3ac6 100644 --- a/src/app/services/tools.service.ts +++ b/src/app/services/tools.service.ts @@ -2,10 +2,11 @@ import { Injectable } from '@angular/core'; import { Store } from '@ngxs/store'; import { AccountInfo } from '../states/accounts.state'; -import { MastodonService } from './mastodon.service'; +import { MastodonWrapperService } from './mastodon-wrapper.service'; import { Account, Results, Status, Emoji } from "./models/mastodon.interfaces"; import { StatusWrapper } from '../models/common.model'; import { AccountSettings, SaveAccountSettings } from '../states/settings.state'; +import { AppInfo, RegisteredAppsStateModel } from '../states/registered-apps.state'; @Injectable({ providedIn: 'root' @@ -15,7 +16,7 @@ export class ToolsService { private instanceInfos: { [id: string]: InstanceInfo } = {}; constructor( - private readonly mastodonService: MastodonService, + private readonly mastodonService: MastodonWrapperService, private readonly store: Store) { } getInstanceInfo(acc: AccountInfo): Promise { diff --git a/src/app/services/user-notification.service.ts b/src/app/services/user-notification.service.ts index c66b44ff..4fed8c2a 100644 --- a/src/app/services/user-notification.service.ts +++ b/src/app/services/user-notification.service.ts @@ -3,7 +3,7 @@ import { BehaviorSubject, Subject, Observable, Subscription } from 'rxjs'; import { Store } from '@ngxs/store'; import { Status, Notification } from './models/mastodon.interfaces'; -import { MastodonService } from './mastodon.service'; +import { MastodonWrapperService } from './mastodon-wrapper.service'; import { AccountInfo } from '../states/accounts.state'; import { NotificationService } from './notification.service'; import { ToolsService } from './tools.service'; @@ -19,7 +19,7 @@ export class UserNotificationService { constructor( private readonly toolsService: ToolsService, private readonly notificationService: NotificationService, - private readonly mastodonService: MastodonService, + private readonly mastodonService: MastodonWrapperService, private readonly store: Store) { this.fetchNotifications(); diff --git a/src/app/states/accounts.state.ts b/src/app/states/accounts.state.ts index 038caed9..714c4385 100644 --- a/src/app/states/accounts.state.ts +++ b/src/app/states/accounts.state.ts @@ -11,6 +11,11 @@ export class SelectAccount { constructor(public account: AccountInfo, public multiselection: boolean = false) {} } +export class UpdateAccount { + static readonly type = '[Accounts] Update account'; + constructor(public account: AccountInfo) {} +} + export class RemoveAccount { static readonly type = '[Accounts] Remove account'; constructor(public accountId: string) {} @@ -41,6 +46,18 @@ export class AccountsState { }); } + @Action(UpdateAccount) + UpdateAccount(ctx: StateContext, action: UpdateAccount){ + const state = ctx.getState(); + + let editedAcc = state.accounts.find(x => x.id === action.account.id); + editedAcc.token = action.account.token; + + ctx.patchState({ + accounts: [...state.accounts] + }); + } + @Action(SelectAccount) SelectAccount(ctx: StateContext, action: SelectAccount){ const state = ctx.getState();