From 018d3f24f0bb8b74ea0269cf427966de985bd5ef Mon Sep 17 00:00:00 2001 From: Nicolas Constant Date: Mon, 1 Oct 2018 21:44:59 -0400 Subject: [PATCH 01/25] added waiting icon --- src/app/app.module.ts | 4 +- .../search/search.component.html | 12 ++-- .../search/search.component.scss | 1 + .../search/search.component.ts | 6 +- .../waiting-animation.component.html | 7 ++ .../waiting-animation.component.scss | 67 +++++++++++++++++++ .../waiting-animation.component.spec.ts | 25 +++++++ .../waiting-animation.component.ts | 15 +++++ src/sass/_commons.scss | 5 ++ src/sass/_panel.scss | 3 +- 10 files changed, 137 insertions(+), 8 deletions(-) create mode 100644 src/app/components/waiting-animation/waiting-animation.component.html create mode 100644 src/app/components/waiting-animation/waiting-animation.component.scss create mode 100644 src/app/components/waiting-animation/waiting-animation.component.spec.ts create mode 100644 src/app/components/waiting-animation/waiting-animation.component.ts create mode 100644 src/sass/_commons.scss diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 0ef47812..53f78a19 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 { WaitingAnimationComponent } from './components/waiting-animation/waiting-animation.component'; const routes: Routes = [ { path: "", redirectTo: "home", pathMatch: "full" }, @@ -56,7 +57,8 @@ const routes: Routes = [ AttachementsComponent, SettingsComponent, AddNewAccountComponent, - SearchComponent + SearchComponent, + WaitingAnimationComponent ], imports: [ BrowserModule, diff --git a/src/app/components/floating-column/search/search.component.html b/src/app/components/floating-column/search/search.component.html index dcb5ad67..084383f0 100644 --- a/src/app/components/floating-column/search/search.component.html +++ b/src/app/components/floating-column/search/search.component.html @@ -3,27 +3,29 @@
+ placeholder="Search" autocomplete="off" />
+ +

Accounts

-
+

Statuses

-
+
\ No newline at end of file diff --git a/src/app/components/floating-column/search/search.component.scss b/src/app/components/floating-column/search/search.component.scss index 40e04779..3fba63fc 100644 --- a/src/app/components/floating-column/search/search.component.scss +++ b/src/app/components/floating-column/search/search.component.scss @@ -1,6 +1,7 @@ @import "variables"; @import "mixins"; @import "panel"; +@import "commons"; $separator-color:$color-primary; diff --git a/src/app/components/floating-column/search/search.component.ts b/src/app/components/floating-column/search/search.component.ts index b20db1ef..21f65ae6 100644 --- a/src/app/components/floating-column/search/search.component.ts +++ b/src/app/components/floating-column/search/search.component.ts @@ -18,6 +18,8 @@ export class SearchComponent implements OnInit { statuses: Status[] = []; hashtags: string[] = []; + isLoading: boolean; + constructor( private readonly store: Store, private readonly mastodonService: MastodonService) { } @@ -35,6 +37,7 @@ export class SearchComponent implements OnInit { this.accounts.length = 0; this.statuses.length = 0; this.hashtags.length = 0; + this.isLoading = true; console.warn(`search: ${data}`); @@ -57,7 +60,8 @@ export class SearchComponent implements OnInit { } } }) - .catch((err) => console.error(err)); + .catch((err) => console.error(err)) + .then(() => { this.isLoading = false; }); } } diff --git a/src/app/components/waiting-animation/waiting-animation.component.html b/src/app/components/waiting-animation/waiting-animation.component.html new file mode 100644 index 00000000..b550ca30 --- /dev/null +++ b/src/app/components/waiting-animation/waiting-animation.component.html @@ -0,0 +1,7 @@ + +
+
+
+
+
+
\ No newline at end of file diff --git a/src/app/components/waiting-animation/waiting-animation.component.scss b/src/app/components/waiting-animation/waiting-animation.component.scss new file mode 100644 index 00000000..6c6ae0d9 --- /dev/null +++ b/src/app/components/waiting-animation/waiting-animation.component.scss @@ -0,0 +1,67 @@ +//https://loading.io/css/ +.lds-ellipsis { + display: inline-block; + position: relative; + //width: 64px; + //height: 64px; + width: 40px; + height: 20px; + } + .lds-ellipsis div { + position: absolute; + // top: 27px; + // width: 11px; + // height: 11px; + + // top: 27px; + top: 8px; + width: 5px; + height: 5px; + + border-radius: 50%; + background: #fff; + animation-timing-function: cubic-bezier(0, 1, 1, 0); + } + .lds-ellipsis div:nth-child(1) { + left: 6px; + animation: lds-ellipsis1 0.6s infinite; + } + .lds-ellipsis div:nth-child(2) { + left: 6px; + animation: lds-ellipsis2 0.6s infinite; + } + .lds-ellipsis div:nth-child(3) { + left: 16px; + // left: 26px; + animation: lds-ellipsis2 0.6s infinite; + } + .lds-ellipsis div:nth-child(4) { + left: 25px; + // left: 45px; + animation: lds-ellipsis3 0.6s infinite; + } + @keyframes lds-ellipsis1 { + 0% { + transform: scale(0); + } + 100% { + transform: scale(1); + } + } + @keyframes lds-ellipsis2 { + 0% { + transform: translate(0, 0); + } + 100% { + transform: translate(10px, 0); + } + } + @keyframes lds-ellipsis3 { + 0% { + transform: scale(1); + } + 100% { + transform: scale(0); + } + } + \ No newline at end of file diff --git a/src/app/components/waiting-animation/waiting-animation.component.spec.ts b/src/app/components/waiting-animation/waiting-animation.component.spec.ts new file mode 100644 index 00000000..e96e388b --- /dev/null +++ b/src/app/components/waiting-animation/waiting-animation.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { WaitingAnimationComponent } from './waiting-animation.component'; + +describe('WaitingAnimationComponent', () => { + let component: WaitingAnimationComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ WaitingAnimationComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(WaitingAnimationComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/components/waiting-animation/waiting-animation.component.ts b/src/app/components/waiting-animation/waiting-animation.component.ts new file mode 100644 index 00000000..bf8d762c --- /dev/null +++ b/src/app/components/waiting-animation/waiting-animation.component.ts @@ -0,0 +1,15 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'app-waiting-animation', + templateUrl: './waiting-animation.component.html', + styleUrls: ['./waiting-animation.component.scss'] +}) +export class WaitingAnimationComponent implements OnInit { + + constructor() { } + + ngOnInit() { + } + +} diff --git a/src/sass/_commons.scss b/src/sass/_commons.scss new file mode 100644 index 00000000..4bd0c225 --- /dev/null +++ b/src/sass/_commons.scss @@ -0,0 +1,5 @@ +.waiting-icon { + width: 40px; + display: block; + margin: 5px auto; +} \ No newline at end of file diff --git a/src/sass/_panel.scss b/src/sass/_panel.scss index aefae37a..4178e73f 100644 --- a/src/sass/_panel.scss +++ b/src/sass/_panel.scss @@ -1,4 +1,5 @@ .panel{ + width: 100%; padding: 10px 10px 0 7px; font-size: $small-font-size; &__title { @@ -6,4 +7,4 @@ text-transform: uppercase; margin: 6px 0 12px 0; } -} \ No newline at end of file +} \ No newline at end of file From 4dcf6e44317f97b4c89f70db889ebf02c305f2e4 Mon Sep 17 00:00:00 2001 From: Nicolas Constant Date: Mon, 1 Oct 2018 22:01:47 -0400 Subject: [PATCH 02/25] added loading icon --- src/index.html | 63 +++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 52 insertions(+), 11 deletions(-) diff --git a/src/index.html b/src/index.html index ff94bff9..1d470ce9 100644 --- a/src/index.html +++ b/src/index.html @@ -2,24 +2,65 @@ - - Sengi - + + Sengi + - - - + + + - + - - loading... - + +
+
+
+
+
- + \ No newline at end of file From 630dbf2f76606af1dcec316b54c62ad34dbcac42 Mon Sep 17 00:00:00 2001 From: Nicolas Constant Date: Mon, 1 Oct 2018 23:46:12 -0400 Subject: [PATCH 03/25] 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 04/25] 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 05/25] 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 06/25] 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 07/25] 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 08/25] 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; From 002debc8da5e07c535dce64877acd44e43bdb9ca Mon Sep 17 00:00:00 2001 From: Nicolas Constant Date: Sat, 13 Oct 2018 01:10:43 -0400 Subject: [PATCH 09/25] added the reply module --- src/app/app.module.ts | 4 ++- .../status/action-bar/action-bar.component.ts | 5 +-- .../reply-to-status.component.html | 8 +++++ .../reply-to-status.component.scss | 36 +++++++++++++++++++ .../reply-to-status.component.spec.ts | 25 +++++++++++++ .../reply-to-status.component.ts | 17 +++++++++ .../stream/status/status.component.html | 4 ++- .../stream/status/status.component.ts | 6 ++++ 8 files changed, 101 insertions(+), 4 deletions(-) create mode 100644 src/app/components/stream/status/reply-to-status/reply-to-status.component.html create mode 100644 src/app/components/stream/status/reply-to-status/reply-to-status.component.scss create mode 100644 src/app/components/stream/status/reply-to-status/reply-to-status.component.spec.ts create mode 100644 src/app/components/stream/status/reply-to-status/reply-to-status.component.ts diff --git a/src/app/app.module.ts b/src/app/app.module.ts index c3227cbe..495660e2 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -34,6 +34,7 @@ import { AddNewStatusComponent } from "./components/floating-column/add-new-stat import { ManageAccountComponent } from "./components/floating-column/manage-account/manage-account.component"; import { ActionBarComponent } from './components/stream/status/action-bar/action-bar.component'; import { WaitingAnimationComponent } from './components/waiting-animation/waiting-animation.component'; +import { ReplyToStatusComponent } from './components/stream/status/reply-to-status/reply-to-status.component'; const routes: Routes = [ { path: "", redirectTo: "home", pathMatch: "full" }, @@ -60,7 +61,8 @@ const routes: Routes = [ AddNewAccountComponent, SearchComponent, ActionBarComponent, - WaitingAnimationComponent + WaitingAnimationComponent, + ReplyToStatusComponent ], imports: [ BrowserModule, 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 f0fe0602..84828ec6 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,4 +1,4 @@ -import { Component, OnInit, OnDestroy, Input } from '@angular/core'; +import { Component, OnInit, OnDestroy, Input, Output, EventEmitter } from '@angular/core'; import { Store } from '@ngxs/store'; import { StatusWrapper } from '../../stream.component'; @@ -16,6 +16,7 @@ import { Status, Results } from '../../../../services/models/mastodon.interfaces export class ActionBarComponent implements OnInit, OnDestroy { @Input() statusWrapper: StatusWrapper; + @Output() replyEvent = new EventEmitter(); isFavorited: boolean; isBoosted: boolean; @@ -80,7 +81,7 @@ export class ActionBarComponent implements OnInit, OnDestroy { } reply(): boolean { - console.warn('reply'); + this.replyEvent.emit(); return false; } diff --git a/src/app/components/stream/status/reply-to-status/reply-to-status.component.html b/src/app/components/stream/status/reply-to-status/reply-to-status.component.html new file mode 100644 index 00000000..c3250f9d --- /dev/null +++ b/src/app/components/stream/status/reply-to-status/reply-to-status.component.html @@ -0,0 +1,8 @@ +
+ + + + +
\ No newline at end of file diff --git a/src/app/components/stream/status/reply-to-status/reply-to-status.component.scss b/src/app/components/stream/status/reply-to-status/reply-to-status.component.scss new file mode 100644 index 00000000..a5fd3b41 --- /dev/null +++ b/src/app/components/stream/status/reply-to-status/reply-to-status.component.scss @@ -0,0 +1,36 @@ +@import "variables"; +@import "panel"; +@import "buttons"; + + +$btn-send-status-width: 60px; + +.form-control { + margin-bottom: 5px; + + &--privacy{ + display: inline-block; + width: calc(100% - 5px - #{$btn-send-status-width}); + } +} + +.btn-custom-primary { + display: inline-block; + width: $btn-send-status-width; + position: relative; + top: -1px; + left: 5px; + // background-color: orange; + // border-color: orange; + // color: black; + font-weight: 500; + + // &:hover { + + // } + + // &:focus { + // border-color: darkblue; + // } +} + diff --git a/src/app/components/stream/status/reply-to-status/reply-to-status.component.spec.ts b/src/app/components/stream/status/reply-to-status/reply-to-status.component.spec.ts new file mode 100644 index 00000000..53e0c519 --- /dev/null +++ b/src/app/components/stream/status/reply-to-status/reply-to-status.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ReplyToStatusComponent } from './reply-to-status.component'; + +describe('ReplyToStatusComponent', () => { + let component: ReplyToStatusComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ ReplyToStatusComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ReplyToStatusComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/components/stream/status/reply-to-status/reply-to-status.component.ts b/src/app/components/stream/status/reply-to-status/reply-to-status.component.ts new file mode 100644 index 00000000..1224c936 --- /dev/null +++ b/src/app/components/stream/status/reply-to-status/reply-to-status.component.ts @@ -0,0 +1,17 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'app-reply-to-status', + templateUrl: './reply-to-status.component.html', + styleUrls: ['./reply-to-status.component.scss'] +}) +export class ReplyToStatusComponent implements OnInit { + + + + constructor() { } + + ngOnInit() { + } + +} diff --git a/src/app/components/stream/status/status.component.html b/src/app/components/stream/status/status.component.html index ce7f40d0..005bba5f 100644 --- a/src/app/components/stream/status/status.component.html +++ b/src/app/components/stream/status/status.component.html @@ -18,5 +18,7 @@ - + + +
\ 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 ca495536..0f62c46a 100644 --- a/src/app/components/stream/status/status.component.ts +++ b/src/app/components/stream/status/status.component.ts @@ -14,6 +14,7 @@ export class StatusComponent implements OnInit { displayedStatus: Status; reblog: boolean; hasAttachments: boolean; + replyingToStatus: boolean; private _statusWrapper: StatusWrapper; status: Status; @@ -66,4 +67,9 @@ export class StatusComponent implements OnInit { return formatDate(date, 'MM/dd', this.locale); } + + openReply(): boolean{ + this.replyingToStatus = !this.replyingToStatus; + return false; + } } From 34e593576dcc060a1f3ee75aa923f7daf37e693c Mon Sep 17 00:00:00 2001 From: Nicolas Constant Date: Sat, 13 Oct 2018 11:07:37 -0400 Subject: [PATCH 10/25] fix imports for AOT build --- .../add-new-status.component.ts | 3 ++- .../reply-to-status.component.ts | 27 ++++++++++++++++--- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/src/app/components/floating-column/add-new-status/add-new-status.component.ts b/src/app/components/floating-column/add-new-status/add-new-status.component.ts index 1389afd1..e4445c17 100644 --- a/src/app/components/floating-column/add-new-status/add-new-status.component.ts +++ b/src/app/components/floating-column/add-new-status/add-new-status.component.ts @@ -17,7 +17,8 @@ export class AddNewStatusComponent implements OnInit { selectedPrivacy = 'Public'; privacyList: string[] = ['Public', 'Unlisted', 'Follows-only', 'DM']; - constructor(private readonly store: Store, + constructor( + private readonly store: Store, private readonly mastodonService: MastodonService) { } ngOnInit() { diff --git a/src/app/components/stream/status/reply-to-status/reply-to-status.component.ts b/src/app/components/stream/status/reply-to-status/reply-to-status.component.ts index 1224c936..44c9856b 100644 --- a/src/app/components/stream/status/reply-to-status/reply-to-status.component.ts +++ b/src/app/components/stream/status/reply-to-status/reply-to-status.component.ts @@ -1,4 +1,7 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, Input } from '@angular/core'; +import { Store } from '@ngxs/store'; +import { MastodonService } from '../../../../services/mastodon.service'; +import { AccountInfo } from '../../../../states/accounts.state'; @Component({ selector: 'app-reply-to-status', @@ -6,12 +9,30 @@ import { Component, OnInit } from '@angular/core'; styleUrls: ['./reply-to-status.component.scss'] }) export class ReplyToStatusComponent implements OnInit { + @Input() status: string; - + selectedPrivacy = 'Public'; + privacyList: string[] = ['Public', 'Unlisted', 'Follows-only', 'DM']; - constructor() { } + constructor( + private readonly store: Store, + private readonly mastodonService: MastodonService) { } ngOnInit() { } + onSubmit(): boolean { + + return false; + } + + private getRegisteredAccounts(): AccountInfo[] { + var regAccounts = this.store.snapshot().registeredaccounts.accounts; + return regAccounts; + } + + onCtrlEnter(): boolean { + this.onSubmit(); + return false; + } } From 0d80f56c7cb9f6a02fa10de2c58f767fb69610cd Mon Sep 17 00:00:00 2001 From: Nicolas Constant Date: Sat, 13 Oct 2018 11:38:23 -0400 Subject: [PATCH 11/25] replying to status functionnal --- .../status/action-bar/action-bar.component.ts | 2 +- .../reply-to-status.component.ts | 47 +++++++++++++++++-- .../stream/status/status.component.html | 2 +- .../stream/status/status.component.ts | 5 ++ .../services/models/mastodon.interfaces.ts | 6 ++- 5 files changed, 55 insertions(+), 7 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 84828ec6..84005dad 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,10 +1,10 @@ import { Component, OnInit, OnDestroy, Input, Output, EventEmitter } from '@angular/core'; import { Store } from '@ngxs/store'; +import { Observable, Subscription } from 'rxjs'; 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"; diff --git a/src/app/components/stream/status/reply-to-status/reply-to-status.component.ts b/src/app/components/stream/status/reply-to-status/reply-to-status.component.ts index 44c9856b..81aee556 100644 --- a/src/app/components/stream/status/reply-to-status/reply-to-status.component.ts +++ b/src/app/components/stream/status/reply-to-status/reply-to-status.component.ts @@ -1,7 +1,9 @@ -import { Component, OnInit, Input } from '@angular/core'; +import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core'; import { Store } from '@ngxs/store'; -import { MastodonService } from '../../../../services/mastodon.service'; +import { MastodonService, VisibilityEnum } from '../../../../services/mastodon.service'; import { AccountInfo } from '../../../../states/accounts.state'; +import { StatusWrapper } from '../../stream.component'; +import { Status } from '../../../../services/models/mastodon.interfaces'; @Component({ selector: 'app-reply-to-status', @@ -9,7 +11,11 @@ import { AccountInfo } from '../../../../states/accounts.state'; styleUrls: ['./reply-to-status.component.scss'] }) export class ReplyToStatusComponent implements OnInit { - @Input() status: string; + @Input() status: string = ''; + @Input() statusReplyingToWrapper: StatusWrapper; + @Output() onClose = new EventEmitter(); + + private statusReplyingTo: Status; selectedPrivacy = 'Public'; privacyList: string[] = ['Public', 'Unlisted', 'Follows-only', 'DM']; @@ -19,9 +25,44 @@ export class ReplyToStatusComponent implements OnInit { private readonly mastodonService: MastodonService) { } ngOnInit() { + this.statusReplyingTo = this.statusReplyingToWrapper.status; + + this.status += `@${this.statusReplyingTo.account.acct} `; + for (const mention of this.statusReplyingTo.mentions) { + this.status += `@${mention.acct} `; + } } onSubmit(): boolean { + const accounts = this.getRegisteredAccounts(); + const selectedAccounts = accounts.filter(x => x.isSelected); + + let visibility: VisibilityEnum = VisibilityEnum.Unknown; + switch (this.selectedPrivacy) { + case 'Public': + visibility = VisibilityEnum.Public; + break; + case 'Unlisted': + visibility = VisibilityEnum.Unlisted; + break; + case 'Follows-only': + visibility = VisibilityEnum.Private; + break; + case 'DM': + visibility = VisibilityEnum.Direct; + break; + } + + let spoiler = this.statusReplyingTo.spoiler_text; + + for (const acc of selectedAccounts) { + this.mastodonService.postNewStatus(acc, this.status, visibility, spoiler) + .then((res: Status) => { + console.log(res); + this.status = ''; + this.onClose.emit(); + }); + } return false; } diff --git a/src/app/components/stream/status/status.component.html b/src/app/components/stream/status/status.component.html index 005bba5f..38d2c624 100644 --- a/src/app/components/stream/status/status.component.html +++ b/src/app/components/stream/status/status.component.html @@ -20,5 +20,5 @@ - + \ 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 0f62c46a..b9a452b2 100644 --- a/src/app/components/stream/status/status.component.ts +++ b/src/app/components/stream/status/status.component.ts @@ -72,4 +72,9 @@ export class StatusComponent implements OnInit { this.replyingToStatus = !this.replyingToStatus; return false; } + + closeReply(): boolean { + this.replyingToStatus = false; + return false; + } } diff --git a/src/app/services/models/mastodon.interfaces.ts b/src/app/services/models/mastodon.interfaces.ts index e2b50740..c07620cc 100644 --- a/src/app/services/models/mastodon.interfaces.ts +++ b/src/app/services/models/mastodon.interfaces.ts @@ -122,10 +122,12 @@ export interface Status { spoiler_text: string; visibility: string; media_attachments: Attachment[]; - mentions: string; - tags: string; + mentions: Mention[]; + tags: Tag[]; application: Application; emojis: any[]; + language: string; + pinned: boolean; } export interface Tag { name: string; From 7aed4569e5c1c54294c7ba99a3c9abc710c56f32 Mon Sep 17 00:00:00 2001 From: Nicolas Constant Date: Sat, 13 Oct 2018 18:23:09 -0400 Subject: [PATCH 12/25] enhancing reply design --- .../reply-to-status.component.html | 2 +- .../reply-to-status.component.scss | 34 +++++++++---------- .../reply-to-status.component.ts | 2 +- .../components/stream/stream.component.scss | 2 +- src/sass/_variables.scss | 12 +++++-- 5 files changed, 29 insertions(+), 23 deletions(-) diff --git a/src/app/components/stream/status/reply-to-status/reply-to-status.component.html b/src/app/components/stream/status/reply-to-status/reply-to-status.component.html index c3250f9d..1c7fe93c 100644 --- a/src/app/components/stream/status/reply-to-status/reply-to-status.component.html +++ b/src/app/components/stream/status/reply-to-status/reply-to-status.component.html @@ -1,5 +1,5 @@
- + + - + +