diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index 50e84682..a58959f7 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -41,6 +41,7 @@ import { HashtagComponent } from './components/stream/hashtag/hashtag.component'
import { StreamOverlayComponent } from './components/stream/stream-overlay/stream-overlay.component';
import { DatabindedTextComponent } from './components/stream/status/databinded-text/databinded-text.component';
import { TimeAgoPipe } from './pipes/time-ago.pipe';
+import { StreamStatusesComponent } from './components/stream/stream-statuses/stream-statuses.component';
const routes: Routes = [
{ path: "", redirectTo: "home", pathMatch: "full" },
@@ -74,7 +75,8 @@ const routes: Routes = [
HashtagComponent,
StreamOverlayComponent,
DatabindedTextComponent,
- TimeAgoPipe
+ TimeAgoPipe,
+ StreamStatusesComponent
],
imports: [
BrowserModule,
diff --git a/src/app/components/floating-column/floating-column.component.ts b/src/app/components/floating-column/floating-column.component.ts
index b35edbbd..8f5116eb 100644
--- a/src/app/components/floating-column/floating-column.component.ts
+++ b/src/app/components/floating-column/floating-column.component.ts
@@ -16,7 +16,6 @@ export class FloatingColumnComponent implements OnInit {
openPanel: string;
-
constructor(private readonly navigationService: NavigationService) { }
ngOnInit() {
diff --git a/src/app/components/stream/stream-statuses/stream-statuses.component.html b/src/app/components/stream/stream-statuses/stream-statuses.component.html
new file mode 100644
index 00000000..43918a72
--- /dev/null
+++ b/src/app/components/stream/stream-statuses/stream-statuses.component.html
@@ -0,0 +1,6 @@
+
\ No newline at end of file
diff --git a/src/app/components/stream/stream-statuses/stream-statuses.component.scss b/src/app/components/stream/stream-statuses/stream-statuses.component.scss
new file mode 100644
index 00000000..b7f225a0
--- /dev/null
+++ b/src/app/components/stream/stream-statuses/stream-statuses.component.scss
@@ -0,0 +1,13 @@
+@import "variables";
+@import "commons";
+
+.stream-toots {
+ height: calc(100%);
+ width: calc(100%);
+
+ overflow: auto;
+ &__status:not(:last-child) {
+ border: solid #06070b;
+ border-width: 0 0 1px 0;
+ }
+}
\ No newline at end of file
diff --git a/src/app/components/stream/stream-statuses/stream-statuses.component.spec.ts b/src/app/components/stream/stream-statuses/stream-statuses.component.spec.ts
new file mode 100644
index 00000000..3a391ce1
--- /dev/null
+++ b/src/app/components/stream/stream-statuses/stream-statuses.component.spec.ts
@@ -0,0 +1,25 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { StreamStatusesComponent } from './stream-statuses.component';
+
+describe('StreamStatusesComponent', () => {
+ let component: StreamStatusesComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ StreamStatusesComponent ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(StreamStatusesComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/components/stream/stream-statuses/stream-statuses.component.ts b/src/app/components/stream/stream-statuses/stream-statuses.component.ts
new file mode 100644
index 00000000..74ef3465
--- /dev/null
+++ b/src/app/components/stream/stream-statuses/stream-statuses.component.ts
@@ -0,0 +1,198 @@
+import { Component, OnInit, Input, ViewChild, ElementRef, OnDestroy, EventEmitter, Output } from '@angular/core';
+import { Store } from '@ngxs/store';
+
+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 { Observable, Subscription } from 'rxjs';
+import { StatusWrapper } from '../stream.component';
+
+
+@Component({
+ selector: 'app-stream-statuses',
+ templateUrl: './stream-statuses.component.html',
+ styleUrls: ['./stream-statuses.component.scss']
+})
+export class StreamStatusesComponent implements OnInit, OnDestroy {
+ private _streamElement: StreamElement;
+ private account: AccountInfo;
+ private websocketStreaming: StreamingWrapper;
+
+ statuses: StatusWrapper[] = [];
+ private bufferStream: Status[] = [];
+ private bufferWasCleared: boolean;
+
+ @Output() browseAccount = new EventEmitter();
+ @Output() browseHashtag = new EventEmitter();
+ @Output() browseThread = new EventEmitter();
+
+ @Input()
+ set streamElement(streamElement: StreamElement) {
+ this._streamElement = streamElement;
+
+ const splitedUserName = streamElement.accountId.split('@');
+ const user = splitedUserName[0];
+ const instance = splitedUserName[1];
+ this.account = this.getRegisteredAccounts().find(x => x.username == user && x.instance == instance);
+
+ this.retrieveToots();
+ this.launchWebsocket();
+ }
+ get streamElement(): StreamElement {
+ return this._streamElement;
+ }
+
+ @Input() goToTop: Observable;
+
+ private goToTopSubscription: Subscription;
+
+ constructor(
+ private readonly store: Store,
+ private readonly streamingService: StreamingService,
+ private readonly mastodonService: MastodonService) {
+ }
+
+ ngOnInit() {
+ this.goToTopSubscription = this.goToTop.subscribe(() => {
+ this.applyGoToTop();
+ });
+ }
+
+ ngOnDestroy(){
+ if( this.goToTopSubscription) this.goToTopSubscription.unsubscribe();
+ }
+
+ private launchWebsocket(): void {
+ this.websocketStreaming = this.streamingService.getStreaming(this.account, this._streamElement);
+ this.websocketStreaming.statusUpdateSubjet.subscribe((update: StatusUpdate) => {
+ if (update) {
+ if (update.type === EventEnum.update) {
+ if (!this.statuses.find(x => x.status.id == update.status.id)) {
+ if (this.streamPositionnedAtTop) {
+ const wrapper = new StatusWrapper(update.status, this.account);
+ this.statuses.unshift(wrapper);
+ } else {
+ this.bufferStream.push(update.status);
+ }
+ }
+ }
+ }
+
+ this.checkAndCleanUpStream();
+ });
+ }
+
+
+ @ViewChild('statusstream') public statustream: ElementRef;
+ private applyGoToTop(): boolean {
+ this.loadBuffer();
+ if (this.statuses.length > 2 * this.streamingService.nbStatusPerIteration) {
+ this.statuses.length = 2 * this.streamingService.nbStatusPerIteration;
+ }
+ const stream = this.statustream.nativeElement as HTMLElement;
+ stream.scrollTo({
+ top: 0,
+ behavior: 'smooth'
+ });
+ return false;
+ }
+
+ private streamPositionnedAtTop: boolean = true;
+ private isProcessingInfiniteScroll: boolean;
+
+ onScroll() {
+ var element = this.statustream.nativeElement as HTMLElement;
+ const atBottom = element.scrollHeight <= element.clientHeight + element.scrollTop + 1000;
+ const atTop = element.scrollTop === 0;
+
+ this.streamPositionnedAtTop = false;
+ if (atBottom && !this.isProcessingInfiniteScroll) {
+ this.scrolledToBottom();
+ } else if (atTop) {
+ this.scrolledToTop();
+ }
+ }
+
+ accountSelected(accountName: string): void {
+ console.warn(`status comp: accountSelected ${accountName}`);
+ this.browseAccount.next(accountName);
+ }
+
+ hashtagSelected(hashtag: string): void {
+ console.warn(`status comp: hashtagSelected ${hashtag}`);
+ this.browseHashtag.next(hashtag);
+ }
+
+ textSelected(): void {
+ console.warn(`status comp: textSelected`);
+ }
+
+ private scrolledToTop() {
+ this.streamPositionnedAtTop = true;
+
+ this.loadBuffer();
+ }
+
+ private loadBuffer(){
+ if(this.bufferWasCleared) {
+ this.statuses.length = 0;
+ this.bufferWasCleared = false;
+ }
+
+ for (const status of this.bufferStream) {
+ const wrapper = new StatusWrapper(status, this.account);
+ this.statuses.unshift(wrapper);
+ }
+
+ this.bufferStream.length = 0;
+ }
+
+ private scrolledToBottom() {
+ this.isProcessingInfiniteScroll = true;
+
+ const lastStatus = this.statuses[this.statuses.length - 1];
+ this.mastodonService.getTimeline(this.account, this._streamElement.type, lastStatus.status.id, null, this.streamingService.nbStatusPerIteration, this._streamElement.tag, this._streamElement.list)
+ .then((status: Status[]) => {
+ for (const s of status) {
+ const wrapper = new StatusWrapper(s, this.account);
+ this.statuses.push(wrapper);
+ }
+ })
+ .catch(err => {
+ console.error(err);
+ })
+ .then(() => {
+ this.isProcessingInfiniteScroll = false;
+ });
+ }
+
+ private getRegisteredAccounts(): AccountInfo[] {
+ var regAccounts = this.store.snapshot().registeredaccounts.accounts;
+ return regAccounts;
+ }
+
+
+ private retrieveToots(): void {
+ this.mastodonService.getTimeline(this.account, this._streamElement.type, null, null, this.streamingService.nbStatusPerIteration, this._streamElement.tag, this._streamElement.list)
+ .then((results: Status[]) => {
+ for (const s of results) {
+ const wrapper = new StatusWrapper(s, this.account);
+ this.statuses.push(wrapper);
+ }
+ });
+ }
+
+ private checkAndCleanUpStream(): void {
+ if (this.streamPositionnedAtTop && this.statuses.length > 3 * this.streamingService.nbStatusPerIteration) {
+ this.statuses.length = 2 * this.streamingService.nbStatusPerIteration;
+ }
+
+ if (this.bufferStream.length > 3 * this.streamingService.nbStatusPerIteration) {
+ this.bufferWasCleared = true;
+ this.bufferStream.length = 2 * this.streamingService.nbStatusPerIteration;
+ }
+ }
+}
+
diff --git a/src/app/components/stream/stream.component.html b/src/app/components/stream/stream.component.html
index a9f2099e..cd7b94dd 100644
--- a/src/app/components/stream/stream.component.html
+++ b/src/app/components/stream/stream.component.html
@@ -10,10 +10,10 @@
{{ streamElement.name.toUpperCase() }}
-
\ No newline at end of file
diff --git a/src/app/components/stream/stream.component.scss b/src/app/components/stream/stream.component.scss
index aeb3219c..ae66203e 100644
--- a/src/app/components/stream/stream.component.scss
+++ b/src/app/components/stream/stream.component.scss
@@ -22,16 +22,22 @@
}
}
-.stream-toots {
+.stream-statuses {
+ display: block;
height: calc(100% - 30px);
width: 320px;
- overflow: auto;
- &__status:not(:last-child) {
- border: solid #06070b;
- border-width: 0 0 1px 0;
- }
}
+// .stream-toots {
+// height: calc(100% - 30px);
+// width: 320px;
+// overflow: auto;
+// &__status:not(:last-child) {
+// border: solid #06070b;
+// border-width: 0 0 1px 0;
+// }
+// }
+
.stream-overlay {
position: absolute;
diff --git a/src/app/components/stream/stream.component.ts b/src/app/components/stream/stream.component.ts
index 33e379f7..c0456de4 100644
--- a/src/app/components/stream/stream.component.ts
+++ b/src/app/components/stream/stream.component.ts
@@ -1,11 +1,9 @@
import { Component, OnInit, Input, ElementRef, ViewChild, HostListener } from "@angular/core";
-import { AccountWrapper } from "../../models/account.models";
-import { StreamElement, StreamTypeEnum } from "../../states/streams.state";
-import { StreamingService, StreamingWrapper, EventEnum, StatusUpdate } from "../../services/streaming.service";
-import { Store } from "@ngxs/store";
-import { AccountInfo } from "../../states/accounts.state";
+import { Subject } from "rxjs";
+
+import { StreamElement } from "../../states/streams.state";
import { Status } from "../../services/models/mastodon.interfaces";
-import { MastodonService } from "../../services/mastodon.service";
+import { AccountInfo } from "../../states/accounts.state";
@Component({
selector: "app-stream",
@@ -13,54 +11,34 @@ import { MastodonService } from "../../services/mastodon.service";
styleUrls: ["./stream.component.scss"]
})
export class StreamComponent implements OnInit {
- private _streamElement: StreamElement;
- private account: AccountInfo;
- private websocketStreaming: StreamingWrapper;
-
- statuses: StatusWrapper[] = [];
- private bufferStream: Status[] = [];
- private bufferWasCleared: boolean;
-
overlayActive: boolean;
overlayAccountToBrowse: string;
overlayHashtagToBrowse: string;
- @Input()
- set streamElement(streamElement: StreamElement) {
- this._streamElement = streamElement;
+ private goToTopSubject: Subject = new Subject();
- const splitedUserName = streamElement.accountId.split('@');
- const user = splitedUserName[0];
- const instance = splitedUserName[1];
- this.account = this.getRegisteredAccounts().find(x => x.username == user && x.instance == instance);
+ @Input() streamElement: StreamElement;
- this.retrieveToots();
- this.launchWebsocket();
- }
-
- get streamElement(): StreamElement {
- return this._streamElement;
- }
-
- constructor(
- private readonly store: Store,
- private readonly streamingService: StreamingService,
- private readonly mastodonService: MastodonService) {
- }
+ constructor() { }
ngOnInit() {
}
+ goToTop(): boolean {
+ this.goToTopSubject.next();
+ return false;
+ }
+
browseAccount(account: string): void {
this.overlayAccountToBrowse = account;
this.overlayHashtagToBrowse = null;
- this.overlayActive = true;
+ this.overlayActive = true;
}
browseHashtag(hashtag: string): void {
this.overlayAccountToBrowse = null;
this.overlayHashtagToBrowse = hashtag;
- this.overlayActive = true;
+ this.overlayActive = true;
}
browseThread(thread: string): void {
@@ -72,126 +50,11 @@ export class StreamComponent implements OnInit {
this.overlayAccountToBrowse = null;
this.overlayActive = false;
}
-
- @ViewChild('statusstream') public statustream: ElementRef;
- goToTop(): boolean {
- this.loadBuffer();
- if (this.statuses.length > 2 * this.streamingService.nbStatusPerIteration) {
- this.statuses.length = 2 * this.streamingService.nbStatusPerIteration;
- }
- const stream = this.statustream.nativeElement as HTMLElement;
- stream.scrollTo({
- top: 0,
- behavior: 'smooth'
- });
- return false;
- }
-
- private streamPositionnedAtTop: boolean = true;
- private isProcessingInfiniteScroll: boolean;
-
- onScroll() {
- var element = this.statustream.nativeElement as HTMLElement;
- const atBottom = element.scrollHeight <= element.clientHeight + element.scrollTop + 1000;
- const atTop = element.scrollTop === 0;
-
- this.streamPositionnedAtTop = false;
- if (atBottom && !this.isProcessingInfiniteScroll) {
- this.scrolledToBottom();
- } else if (atTop) {
- this.scrolledToTop();
- }
- }
-
- private scrolledToTop() {
- this.streamPositionnedAtTop = true;
-
- this.loadBuffer();
- }
-
- private loadBuffer(){
- if(this.bufferWasCleared) {
- this.statuses.length = 0;
- this.bufferWasCleared = false;
- }
-
- for (const status of this.bufferStream) {
- const wrapper = new StatusWrapper(status, this.account);
- this.statuses.unshift(wrapper);
- }
-
- this.bufferStream.length = 0;
- }
-
- private scrolledToBottom() {
- this.isProcessingInfiniteScroll = true;
-
- const lastStatus = this.statuses[this.statuses.length - 1];
- this.mastodonService.getTimeline(this.account, this._streamElement.type, lastStatus.status.id, null, this.streamingService.nbStatusPerIteration, this._streamElement.tag, this._streamElement.list)
- .then((status: Status[]) => {
- for (const s of status) {
- const wrapper = new StatusWrapper(s, this.account);
- this.statuses.push(wrapper);
- }
- })
- .catch(err => {
- console.error(err);
- })
- .then(() => {
- this.isProcessingInfiniteScroll = false;
- });
- }
-
- private getRegisteredAccounts(): AccountInfo[] {
- var regAccounts = this.store.snapshot().registeredaccounts.accounts;
- return regAccounts;
- }
-
- private retrieveToots(): void {
- this.mastodonService.getTimeline(this.account, this._streamElement.type, null, null, this.streamingService.nbStatusPerIteration, this._streamElement.tag, this._streamElement.list)
- .then((results: Status[]) => {
- for (const s of results) {
- const wrapper = new StatusWrapper(s, this.account);
- this.statuses.push(wrapper);
- }
- });
- }
-
- private launchWebsocket(): void {
- this.websocketStreaming = this.streamingService.getStreaming(this.account, this._streamElement);
- this.websocketStreaming.statusUpdateSubjet.subscribe((update: StatusUpdate) => {
- if (update) {
- if (update.type === EventEnum.update) {
- if (!this.statuses.find(x => x.status.id == update.status.id)) {
- if (this.streamPositionnedAtTop) {
- const wrapper = new StatusWrapper(update.status, this.account);
- this.statuses.unshift(wrapper);
- } else {
- this.bufferStream.push(update.status);
- }
- }
- }
- }
-
- this.checkAndCleanUpStream();
- });
- }
-
- private checkAndCleanUpStream(): void {
- if (this.streamPositionnedAtTop && this.statuses.length > 3 * this.streamingService.nbStatusPerIteration) {
- this.statuses.length = 2 * this.streamingService.nbStatusPerIteration;
- }
-
- if (this.bufferStream.length > 3 * this.streamingService.nbStatusPerIteration) {
- this.bufferWasCleared = true;
- this.bufferStream.length = 2 * this.streamingService.nbStatusPerIteration;
- }
- }
}
export class StatusWrapper {
constructor(
public status: Status,
public provider: AccountInfo
- ) {}
+ ) { }
}
\ No newline at end of file