From 630dbf2f76606af1dcec316b54c62ad34dbcac42 Mon Sep 17 00:00:00 2001 From: Nicolas Constant Date: Mon, 1 Oct 2018 23:46:12 -0400 Subject: [PATCH 1/6] refactoring in prevision of favorite/boost wiring with the API --- src/app/app.module.ts | 4 +- .../action-bar/action-bar.component.html | 14 +++++++ .../action-bar/action-bar.component.scss | 33 +++++++++++++++ .../action-bar/action-bar.component.spec.ts | 25 +++++++++++ .../status/action-bar/action-bar.component.ts | 41 +++++++++++++++++++ .../stream/status/status.component.html | 21 ++-------- .../stream/status/status.component.scss | 41 ++++++++----------- .../stream/status/status.component.ts | 19 +++++---- .../components/stream/stream.component.html | 4 +- src/app/components/stream/stream.component.ts | 25 +++++++---- src/sass/_variables.scss | 9 ++-- 11 files changed, 173 insertions(+), 63 deletions(-) create mode 100644 src/app/components/stream/status/action-bar/action-bar.component.html create mode 100644 src/app/components/stream/status/action-bar/action-bar.component.scss create mode 100644 src/app/components/stream/status/action-bar/action-bar.component.spec.ts create mode 100644 src/app/components/stream/status/action-bar/action-bar.component.ts diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 0ef47812..0e1063bc 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -32,6 +32,7 @@ import { AddNewAccountComponent } from './components/floating-column/add-new-acc import { SearchComponent } from './components/floating-column/search/search.component'; import { AddNewStatusComponent } from "./components/floating-column/add-new-status/add-new-status.component"; import { ManageAccountComponent } from "./components/floating-column/manage-account/manage-account.component"; +import { ActionBarComponent } from './components/stream/status/action-bar/action-bar.component'; const routes: Routes = [ { path: "", redirectTo: "home", pathMatch: "full" }, @@ -56,7 +57,8 @@ const routes: Routes = [ AttachementsComponent, SettingsComponent, AddNewAccountComponent, - SearchComponent + SearchComponent, + ActionBarComponent ], imports: [ BrowserModule, diff --git a/src/app/components/stream/status/action-bar/action-bar.component.html b/src/app/components/stream/status/action-bar/action-bar.component.html new file mode 100644 index 00000000..7d93a47e --- /dev/null +++ b/src/app/components/stream/status/action-bar/action-bar.component.html @@ -0,0 +1,14 @@ +
+ + + + + + + + + + + + +
\ No newline at end of file diff --git a/src/app/components/stream/status/action-bar/action-bar.component.scss b/src/app/components/stream/status/action-bar/action-bar.component.scss new file mode 100644 index 00000000..86cdcc4c --- /dev/null +++ b/src/app/components/stream/status/action-bar/action-bar.component.scss @@ -0,0 +1,33 @@ +@import "variables"; +.action-bar { + // outline: 1px solid greenyellow; // height: 20px; + margin: 5px 10px 5px $avatar-column-space; + padding: 0; + font-size: 24px; + height: 30px; + &__link { + color: $status-secondary-color; + &:hover { + color: $status-links-color; + } + &:not(:last-child) { + margin-right: 15px; + } + } +} + +.boosted { + color: $boost-color; + + &:hover { + color: darken($boost-color, 10); + } +} + +.favorited { + color: $favorite-color; + + &:hover { + color: darken($favorite-color, 10); + } +} \ No newline at end of file diff --git a/src/app/components/stream/status/action-bar/action-bar.component.spec.ts b/src/app/components/stream/status/action-bar/action-bar.component.spec.ts new file mode 100644 index 00000000..be44980a --- /dev/null +++ b/src/app/components/stream/status/action-bar/action-bar.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ActionBarComponent } from './action-bar.component'; + +describe('ActionBarComponent', () => { + let component: ActionBarComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ ActionBarComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ActionBarComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); 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 new file mode 100644 index 00000000..4438fc4d --- /dev/null +++ b/src/app/components/stream/status/action-bar/action-bar.component.ts @@ -0,0 +1,41 @@ +import { Component, OnInit, Input } from '@angular/core'; +import { StatusWrapper } from '../../stream.component'; + +@Component({ + selector: 'app-action-bar', + templateUrl: './action-bar.component.html', + styleUrls: ['./action-bar.component.scss'] +}) +export class ActionBarComponent implements OnInit { + @Input() statusWrapper: StatusWrapper; + + isFavorited: boolean; + isBoosted: boolean; + + constructor() { } + + ngOnInit() { + } + + reply(): boolean { + console.warn('reply'); + return false; + } + + boost(): boolean { + console.warn('boost'); + this.isBoosted = !this.isBoosted; + return false; + } + + favorite(): boolean { + console.warn('favorite'); + this.isFavorited = !this.isFavorited; + return false; + } + + more(): boolean { + console.warn('more'); + return false; + } +} diff --git a/src/app/components/stream/status/status.component.html b/src/app/components/stream/status/status.component.html index 13612b9b..ce7f40d0 100644 --- a/src/app/components/stream/status/status.component.html +++ b/src/app/components/stream/status/status.component.html @@ -1,5 +1,6 @@
@@ -15,21 +16,7 @@ getCompactRelativeTime(status.created_at) }}
-
- -
+ -
- - - - -
- - + \ No newline at end of file diff --git a/src/app/components/stream/status/status.component.scss b/src/app/components/stream/status/status.component.scss index cd7dd691..4db923be 100644 --- a/src/app/components/stream/status/status.component.scss +++ b/src/app/components/stream/status/status.component.scss @@ -1,5 +1,5 @@ @import "variables"; -$avatar-column-space: 70px; + .reblog { position: relative; margin: 5px 0 0 10px; @@ -76,12 +76,12 @@ $avatar-column-space: 70px; &__content { /*width: calc(100% - 50px);*/ word-wrap: break-word; - margin: 0px 10px 10px $avatar-column-space; - } - &__content p { - margin: 0; - font-size: 0.85em; + margin: 0 10px 0 $avatar-column-space; } + // &__content p { + // margin: 0 !important; + // font-size: 0.85em; + // } &__created-at { color: $status-secondary-color; position: absolute; @@ -90,6 +90,10 @@ $avatar-column-space: 70px; } } +// .attachments { + +// } + //Mastodon styling :host ::ng-deep .status__content { color: $status-primary-color; @@ -101,24 +105,15 @@ $avatar-column-space: 70px; & .invisible { display: none; } + & p { + margin: 0px; + //font-size: .9em; + // font-size: 14px; + } } .attachments { - width: calc(100% - 80px); - margin: 0px 10px 10px $avatar-column-space; + display: block; + // width: calc(100% - 80px); + margin: 10px 10px 0 $avatar-column-space; } - -.action-bar { - // outline: 1px solid greenyellow; // height: 20px; - margin: 0px 10px 10px $avatar-column-space; - font-size: 24px; - &__link { - color: $status-secondary-color; - &:hover { - color: $status-links-color; - } - &:not(:last-child) { - margin-right: 15px; - } - } -} \ No newline at end of file diff --git a/src/app/components/stream/status/status.component.ts b/src/app/components/stream/status/status.component.ts index b0c36d3d..ca495536 100644 --- a/src/app/components/stream/status/status.component.ts +++ b/src/app/components/stream/status/status.component.ts @@ -2,6 +2,7 @@ import { Component, OnInit, Input, Inject, LOCALE_ID } from "@angular/core"; import { Status } from "../../../services/models/mastodon.interfaces"; import { formatDate } from '@angular/common'; import { stateNameErrorMessage } from "@ngxs/store/src/decorators/state"; +import { StatusWrapper } from "../stream.component"; @Component({ @@ -14,16 +15,18 @@ export class StatusComponent implements OnInit { reblog: boolean; hasAttachments: boolean; - private _status: Status; - @Input('status') - set status(value: Status) { - this._status = value; + private _statusWrapper: StatusWrapper; + status: Status; + @Input('statusWrapper') + set statusWrapper(value: StatusWrapper) { + this._statusWrapper = value; + this.status = value.status; if(this.status.reblog){ this.reblog = true; - this.displayedStatus = this._status.reblog; + this.displayedStatus = this.status.reblog; } else { - this.displayedStatus = this._status; + this.displayedStatus = this.status; } if(!this.displayedStatus.account.display_name){ @@ -36,8 +39,8 @@ export class StatusComponent implements OnInit { } - get status(): Status{ - return this._status; + get statusWrapper(): StatusWrapper{ + return this._statusWrapper; } diff --git a/src/app/components/stream/stream.component.html b/src/app/components/stream/stream.component.html index fbfd0357..8bb78cbf 100644 --- a/src/app/components/stream/stream.component.html +++ b/src/app/components/stream/stream.component.html @@ -3,8 +3,8 @@

{{ streamElement.name.toUpperCase() }}

-
- +
+
diff --git a/src/app/components/stream/stream.component.ts b/src/app/components/stream/stream.component.ts index 7cb6b257..10b94a81 100644 --- a/src/app/components/stream/stream.component.ts +++ b/src/app/components/stream/stream.component.ts @@ -17,7 +17,7 @@ export class StreamComponent implements OnInit { private account: AccountInfo; private websocketStreaming: StreamingWrapper; - statuses: Status[] = []; + statuses: StatusWrapper[] = []; private bufferStream: Status[] = []; private bufferWasCleared: boolean; @@ -90,7 +90,8 @@ export class StreamComponent implements OnInit { } for (const status of this.bufferStream) { - this.statuses.unshift(status); + const wrapper = new StatusWrapper(status, this.account); + this.statuses.unshift(wrapper); } this.bufferStream.length = 0; @@ -100,10 +101,11 @@ export class StreamComponent implements OnInit { this.isProcessingInfiniteScroll = true; const lastStatus = this.statuses[this.statuses.length - 1]; - this.mastodonService.getTimeline(this.account, this._streamElement.type, lastStatus.id) + this.mastodonService.getTimeline(this.account, this._streamElement.type, lastStatus.status.id) .then((status: Status[]) => { for (const s of status) { - this.statuses.push(s); + const wrapper = new StatusWrapper(s, this.account); + this.statuses.push(wrapper); } }) .catch(err => { @@ -123,7 +125,8 @@ export class StreamComponent implements OnInit { this.mastodonService.getTimeline(this.account, this._streamElement.type) .then((results: Status[]) => { for (const s of results) { - this.statuses.push(s); + const wrapper = new StatusWrapper(s, this.account); + this.statuses.push(wrapper); } }); } @@ -133,9 +136,10 @@ export class StreamComponent implements OnInit { this.websocketStreaming.statusUpdateSubjet.subscribe((update: StatusUpdate) => { if (update) { if (update.type === EventEnum.update) { - if (!this.statuses.find(x => x.id == update.status.id)) { + if (!this.statuses.find(x => x.status.id == update.status.id)) { if (this.streamPositionnedAtTop) { - this.statuses.unshift(update.status); + const wrapper = new StatusWrapper(update.status, this.account); + this.statuses.unshift(wrapper); } else { this.bufferStream.push(update.status); } @@ -159,4 +163,11 @@ export class StreamComponent implements OnInit { } } +} + +export class StatusWrapper { + constructor( + public status: Status, + public provider: AccountInfo + ) {} } \ No newline at end of file diff --git a/src/sass/_variables.scss b/src/sass/_variables.scss index ae8164e5..e8b45f14 100644 --- a/src/sass/_variables.scss +++ b/src/sass/_variables.scss @@ -6,13 +6,11 @@ $color-primary: #141824; $color-secondary: #090b10; $default-font-size: 15px; $small-font-size: 12px; - $btn-primary-color: #515a62; $btn-primary-color: #254d6f; $btn-primary-color: #444f74; $btn-primary-color-hover: darken($btn-primary-color, 10); $btn-primary-font-color: white; - // TEST 1 $status-primary-color: #fff; $status-secondary-color: #353e64; @@ -21,11 +19,12 @@ $status-links-color: #d9e1e8; // $status-primary-color : #8f93a2; // $status-primary-color : lighten(#8f93a2, 30); // $status-links-color : #b2ccd6; - +$boost-color : #5098eb; +$favorite-color: #ffc16f; // Block dispositions $stream-selector-height: 30px; $stream-column-separator: 7px; $stream-column-width: 320px; - +$avatar-column-space: 70px; //Bootstrap cuistomization -$enable-rounded : false; \ No newline at end of file +$enable-rounded: false; \ No newline at end of file From fa75e81685361e118151f69b63cbb6a6dba27f81 Mon Sep 17 00:00:00 2001 From: Nicolas Constant Date: Tue, 2 Oct 2018 00:19:11 -0400 Subject: [PATCH 2/6] adding dependencies for API wirering --- .../status/action-bar/action-bar.component.ts | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) 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 4438fc4d..e3a8a3ce 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 @@ -1,5 +1,9 @@ import { Component, OnInit, Input } from '@angular/core'; +import { Store } from '@ngxs/store'; + import { StatusWrapper } from '../../stream.component'; +import { MastodonService } from '../../../../services/mastodon.service'; +import { AccountInfo } from '../../../../states/accounts.state'; @Component({ selector: 'app-action-bar', @@ -11,10 +15,15 @@ export class ActionBarComponent implements OnInit { isFavorited: boolean; isBoosted: boolean; + + isBoostLocked: boolean; + isLocked: boolean; - constructor() { } + constructor( + private readonly store: Store, + private readonly mastodonService: MastodonService) { } - ngOnInit() { + ngOnInit() { } reply(): boolean { @@ -38,4 +47,9 @@ export class ActionBarComponent implements OnInit { console.warn('more'); return false; } + + private getSelectedAccounts(): AccountInfo[] { + var regAccounts = this.store.snapshot().registeredaccounts.accounts; + return regAccounts.filter(x => x.isSelected); + } } From 71a41ca9ba92ae986b2595b686c118bc799dece1 Mon Sep 17 00:00:00 2001 From: Nicolas Constant Date: Wed, 3 Oct 2018 00:37:41 -0400 Subject: [PATCH 3/6] change action bar based on account's rights --- .../action-bar/action-bar.component.html | 6 +- .../status/action-bar/action-bar.component.ts | 57 +++++++++++++++++-- 2 files changed, 54 insertions(+), 9 deletions(-) diff --git a/src/app/components/stream/status/action-bar/action-bar.component.html b/src/app/components/stream/status/action-bar/action-bar.component.html index 7d93a47e..7595c7f9 100644 --- a/src/app/components/stream/status/action-bar/action-bar.component.html +++ b/src/app/components/stream/status/action-bar/action-bar.component.html @@ -1,11 +1,11 @@
- + - + - + 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 e3a8a3ce..356a5f58 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 @@ -1,29 +1,71 @@ -import { Component, OnInit, Input } from '@angular/core'; +import { Component, OnInit, OnDestroy, Input } from '@angular/core'; import { Store } from '@ngxs/store'; import { StatusWrapper } from '../../stream.component'; import { MastodonService } from '../../../../services/mastodon.service'; import { AccountInfo } from '../../../../states/accounts.state'; +import { Observable, Subscription } from 'rxjs'; +// import { map } from "rxjs/operators"; @Component({ selector: 'app-action-bar', templateUrl: './action-bar.component.html', styleUrls: ['./action-bar.component.scss'] }) -export class ActionBarComponent implements OnInit { +export class ActionBarComponent implements OnInit, OnDestroy { + @Input() statusWrapper: StatusWrapper; isFavorited: boolean; isBoosted: boolean; - + isBoostLocked: boolean; isLocked: boolean; + private isProviderSelected: boolean; + private selectedAccounts: AccountInfo[]; + + private accounts$: Observable; + private accountSub: Subscription; + constructor( private readonly store: Store, - private readonly mastodonService: MastodonService) { } + private readonly mastodonService: MastodonService) { - ngOnInit() { + this.accounts$ = this.store.select(state => state.registeredaccounts.accounts); + } + + ngOnInit() { + // const selectedAccounts = this.getSelectedAccounts(); + // this.checkStatus(selectedAccounts); + + this.accountSub = this.accounts$.subscribe((accounts: AccountInfo[]) => { + console.warn('selectedAccounts'); + this.checkStatus(accounts); + }); + } + + ngOnDestroy(): void { + this.accountSub.unsubscribe(); + } + + private checkStatus(accounts: AccountInfo[]): void { + const status = this.statusWrapper.status; + const provider = this.statusWrapper.provider; + this.selectedAccounts = accounts.filter(x => x.isSelected); + this.isProviderSelected = this.selectedAccounts.filter(x => x.id === provider.id).length > 0; + + if (status.visibility === 'direct' || status.visibility === 'private') { + this.isBoostLocked = true; + } else { + this.isBoostLocked = false; + } + + if ((status.visibility === 'direct' || status.visibility === 'private') && !this.isProviderSelected) { + this.isLocked = true; + } else { + this.isLocked = false; + } } reply(): boolean { @@ -32,6 +74,9 @@ export class ActionBarComponent implements OnInit { } boost(): boolean { + + + console.warn('boost'); this.isBoosted = !this.isBoosted; return false; @@ -50,6 +95,6 @@ export class ActionBarComponent implements OnInit { private getSelectedAccounts(): AccountInfo[] { var regAccounts = this.store.snapshot().registeredaccounts.accounts; - return regAccounts.filter(x => x.isSelected); + return regAccounts; } } From 589cb8330c7b35e1b6a31777011f8fb8059c9006 Mon Sep 17 00:00:00 2001 From: Nicolas Constant Date: Wed, 3 Oct 2018 19:03:58 -0400 Subject: [PATCH 4/6] added lock icon --- .../stream/status/action-bar/action-bar.component.html | 7 +++++++ .../stream/status/action-bar/action-bar.component.scss | 9 +++++++++ 2 files changed, 16 insertions(+) diff --git a/src/app/components/stream/status/action-bar/action-bar.component.html b/src/app/components/stream/status/action-bar/action-bar.component.html index 7595c7f9..2f50011b 100644 --- a/src/app/components/stream/status/action-bar/action-bar.component.html +++ b/src/app/components/stream/status/action-bar/action-bar.component.html @@ -2,12 +2,19 @@ + + + + + + + diff --git a/src/app/components/stream/status/action-bar/action-bar.component.scss b/src/app/components/stream/status/action-bar/action-bar.component.scss index 86cdcc4c..ae753be3 100644 --- a/src/app/components/stream/status/action-bar/action-bar.component.scss +++ b/src/app/components/stream/status/action-bar/action-bar.component.scss @@ -14,6 +14,15 @@ margin-right: 15px; } } + + &__lock { + color: $status-secondary-color; + width: 24px; + + &:not(:last-child) { + margin-right: 15px; + } + } } .boosted { From afed572916a48e7365f609acd3591591f21ebc64 Mon Sep 17 00:00:00 2001 From: Nicolas Constant Date: Wed, 3 Oct 2018 20:13:31 -0400 Subject: [PATCH 5/6] reblogs and favorites now working --- .../status/action-bar/action-bar.component.ts | 67 +++++++++++++++++-- src/app/services/mastodon.service.ts | 27 +++++++- 2 files changed, 88 insertions(+), 6 deletions(-) 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 356a5f58..b6403040 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,6 +5,7 @@ import { StatusWrapper } from '../../stream.component'; import { MastodonService } from '../../../../services/mastodon.service'; import { AccountInfo } from '../../../../states/accounts.state'; import { Observable, Subscription } from 'rxjs'; +import { Status, Results } from '../../../../services/models/mastodon.interfaces'; // import { map } from "rxjs/operators"; @Component({ @@ -49,7 +50,7 @@ export class ActionBarComponent implements OnInit, OnDestroy { this.accountSub.unsubscribe(); } - private checkStatus(accounts: AccountInfo[]): void { + private checkStatus(accounts: AccountInfo[]): void { const status = this.statusWrapper.status; const provider = this.statusWrapper.provider; this.selectedAccounts = accounts.filter(x => x.isSelected); @@ -74,17 +75,73 @@ export class ActionBarComponent implements OnInit, OnDestroy { } boost(): boolean { + this.selectedAccounts.forEach((account: AccountInfo) => { + const isProvider = this.statusWrapper.provider.id === account.id; + let pipeline: Promise = Promise.resolve(this.statusWrapper.status); + if (!isProvider) { + pipeline = pipeline.then((foreignStatus: Status) => { + const statusUrl = foreignStatus.url; + return this.mastodonService.search(account, statusUrl) + .then((results: Results) => { + //TODO check and type errors + return results.statuses[0]; + }); + }); + } - console.warn('boost'); - this.isBoosted = !this.isBoosted; + pipeline + .then((status: Status) => { + if(this.isBoosted) { + return this.mastodonService.unreblog(account, status); + } else { + return this.mastodonService.reblog(account, status); + } + }) + .then(() => { + this.isBoosted = !this.isBoosted; + }) + .catch(err => { + console.error(err); + }); + }); + return false; } favorite(): boolean { - console.warn('favorite'); - this.isFavorited = !this.isFavorited; + this.selectedAccounts.forEach((account: AccountInfo) => { + const isProvider = this.statusWrapper.provider.id === account.id; + + let pipeline: Promise = Promise.resolve(this.statusWrapper.status); + + if (!isProvider) { + pipeline = pipeline.then((foreignStatus: Status) => { + const statusUrl = foreignStatus.url; + return this.mastodonService.search(account, statusUrl) + .then((results: Results) => { + //TODO check and type errors + return results.statuses[0]; + }); + }); + } + + pipeline + .then((status: Status) => { + if(this.isFavorited) { + return this.mastodonService.unfavorite(account, status); + } else { + return this.mastodonService.favorite(account, status); + } + }) + .then(() => { + this.isFavorited = !this.isFavorited; + }) + .catch(err => { + console.error(err); + }); + }); return false; } diff --git a/src/app/services/mastodon.service.ts b/src/app/services/mastodon.service.ts index a189e679..39c82a3f 100644 --- a/src/app/services/mastodon.service.ts +++ b/src/app/services/mastodon.service.ts @@ -5,10 +5,11 @@ import { ApiRoutes } from './models/api.settings'; import { Account, Status, Results } from "./models/mastodon.interfaces"; import { AccountInfo } from '../states/accounts.state'; import { StreamTypeEnum } from '../states/streams.state'; +import { stat } from 'fs'; @Injectable() export class MastodonService { - + private apiRoutes = new ApiRoutes(); constructor(private readonly httpClient: HttpClient) { } @@ -115,6 +116,30 @@ export class MastodonService { const headers = new HttpHeaders({ 'Authorization': `Bearer ${account.token.access_token}` }); return this.httpClient.get(route, { headers: headers }).toPromise() } + + reblog(account: AccountInfo, status: Status): Promise { + const route = `https://${account.instance}${this.apiRoutes.reblogStatus}`.replace('{0}', status.id); + const headers = new HttpHeaders({ 'Authorization': `Bearer ${account.token.access_token}` }); + return this.httpClient.post(route, null, { headers: headers }).toPromise() + } + + unreblog(account: AccountInfo, status: Status): Promise { + const route = `https://${account.instance}${this.apiRoutes.unreblogStatus}`.replace('{0}', status.id); + const headers = new HttpHeaders({ 'Authorization': `Bearer ${account.token.access_token}` }); + return this.httpClient.post(route, null, { headers: headers }).toPromise() + } + + favorite(account: AccountInfo, status: Status): any { + const route = `https://${account.instance}${this.apiRoutes.favouritingStatus}`.replace('{0}', status.id); + const headers = new HttpHeaders({ 'Authorization': `Bearer ${account.token.access_token}` }); + return this.httpClient.post(route, null, { headers: headers }).toPromise() + } + + unfavorite(account: AccountInfo, status: Status): any { + const route = `https://${account.instance}${this.apiRoutes.unfavouritingStatus}`.replace('{0}', status.id); + const headers = new HttpHeaders({ 'Authorization': `Bearer ${account.token.access_token}` }); + return this.httpClient.post(route, null, { headers: headers }).toPromise() + } } export enum VisibilityEnum { From a4c32b3464592cdc30bce0ef72a285bdc185b331 Mon Sep 17 00:00:00 2001 From: Nicolas Constant Date: Wed, 3 Oct 2018 20:58:39 -0400 Subject: [PATCH 6/6] better displaying of favs and boosts states --- .../status/action-bar/action-bar.component.ts | 51 +++++++++++++++---- .../services/models/mastodon.interfaces.ts | 7 +-- 2 files changed, 46 insertions(+), 12 deletions(-) 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 b6403040..f0fe0602 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 @@ -26,6 +26,9 @@ export class ActionBarComponent implements OnInit, OnDestroy { private isProviderSelected: boolean; private selectedAccounts: AccountInfo[]; + private favoriteStatePerAccountId: { [id: string]: boolean; } = {}; + private bootedStatePerAccountId: { [id: string]: boolean; } = {}; + private accounts$: Observable; private accountSub: Subscription; @@ -40,8 +43,12 @@ export class ActionBarComponent implements OnInit, OnDestroy { // const selectedAccounts = this.getSelectedAccounts(); // this.checkStatus(selectedAccounts); + const status = this.statusWrapper.status; + const account = this.statusWrapper.provider; + this.favoriteStatePerAccountId[account.id] = status.favourited; + this.bootedStatePerAccountId[account.id] = status.reblogged; + this.accountSub = this.accounts$.subscribe((accounts: AccountInfo[]) => { - console.warn('selectedAccounts'); this.checkStatus(accounts); }); } @@ -67,6 +74,9 @@ export class ActionBarComponent implements OnInit, OnDestroy { } else { this.isLocked = false; } + + this.checkIfFavorited(); + this.checkIfBoosted(); } reply(): boolean { @@ -93,20 +103,22 @@ export class ActionBarComponent implements OnInit, OnDestroy { pipeline .then((status: Status) => { - if(this.isBoosted) { + if (this.isBoosted) { return this.mastodonService.unreblog(account, status); } else { return this.mastodonService.reblog(account, status); } }) - .then(() => { - this.isBoosted = !this.isBoosted; + .then((boostedStatus: Status) => { + this.bootedStatePerAccountId[account.id] = boostedStatus.reblogged; + this.checkIfBoosted(); + // this.isBoosted = !this.isBoosted; }) .catch(err => { console.error(err); }); }); - + return false; } @@ -129,22 +141,43 @@ export class ActionBarComponent implements OnInit, OnDestroy { pipeline .then((status: Status) => { - if(this.isFavorited) { + if (this.isFavorited) { return this.mastodonService.unfavorite(account, status); } else { return this.mastodonService.favorite(account, status); } }) - .then(() => { - this.isFavorited = !this.isFavorited; + .then((favoritedStatus: Status) => { + this.favoriteStatePerAccountId[account.id] = favoritedStatus.favourited; + this.checkIfFavorited(); + // this.isFavorited = !this.isFavorited; }) .catch(err => { console.error(err); }); - }); + }); return false; } + private checkIfBoosted() { + const selectedAccount = this.selectedAccounts[0]; + if (selectedAccount) { + this.isBoosted = this.bootedStatePerAccountId[selectedAccount.id]; + } else { + this.isBoosted = false; + } + } + + private checkIfFavorited() { + const selectedAccount = this.selectedAccounts[0]; + + if (selectedAccount) { + this.isFavorited = this.favoriteStatePerAccountId[selectedAccount.id]; + } else { + this.isFavorited = false; + } + } + more(): boolean { console.warn('more'); return false; diff --git a/src/app/services/models/mastodon.interfaces.ts b/src/app/services/models/mastodon.interfaces.ts index 2d4aeb0a..e2b50740 100644 --- a/src/app/services/models/mastodon.interfaces.ts +++ b/src/app/services/models/mastodon.interfaces.ts @@ -116,15 +116,16 @@ export interface Status { created_at: string; reblogs_count: string; favourites_count: string; - reblogged: string; - favourited: string; - sensitive: string; + reblogged: boolean; + favourited: boolean; + sensitive: boolean; spoiler_text: string; visibility: string; media_attachments: Attachment[]; mentions: string; tags: string; application: Application; + emojis: any[]; } export interface Tag { name: string;