Sengi-Windows-MacOS-Linux/src/app/components/stream/stream.component.ts

162 lines
5.1 KiB
TypeScript

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 { Status } from "../../services/models/mastodon.interfaces";
import { MastodonService } from "../../services/mastodon.service";
@Component({
selector: "app-stream",
templateUrl: "./stream.component.html",
styleUrls: ["./stream.component.scss"]
})
export class StreamComponent implements OnInit {
private _streamElement: StreamElement;
private account: AccountInfo;
private websocketStreaming: StreamingWrapper;
statuses: Status[] = [];
private bufferStream: Status[] = [];
private bufferWasCleared: boolean;
@Input()
set streamElement(streamElement: StreamElement) {
this._streamElement = streamElement;
const splitedUserName = streamElement.username.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;
}
constructor(
private readonly store: Store,
private readonly streamingService: StreamingService,
private readonly mastodonService: MastodonService) {
}
ngOnInit() {
}
@ViewChild('statusstream') public statustream: ElementRef;
goToTop(): boolean {
this.loadBuffer();
if (this.statuses.length > 40) {
this.statuses.length = 40;
}
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 + 500;
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) {
this.statuses.unshift(status);
}
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.id)
.then((status: Status[]) => {
for (const s of status) {
this.statuses.push(s);
}
})
.catch(err => {
console.error(err);
})
.then(() => {
this.isProcessingInfiniteScroll = false;
});
}
private getRegisteredAccounts(): AccountInfo[] {
var regAccounts = <AccountInfo[]>this.store.snapshot().registeredaccounts.accounts;
return regAccounts;
}
private retrieveToots(): void {
this.mastodonService.getTimeline(this.account, this._streamElement.type)
.then((results: Status[]) => {
for (const s of results) {
this.statuses.push(s);
}
});
}
private launchWebsocket(): void {
this.websocketStreaming = this.streamingService.getStreaming(this.account, this._streamElement.type);
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.streamPositionnedAtTop) {
this.statuses.unshift(update.status);
} else {
this.bufferStream.push(update.status);
}
}
}
}
this.checkAndCleanUpStream();
});
}
private checkAndCleanUpStream(): void {
if (this.streamPositionnedAtTop && this.statuses.length > 60) {
this.statuses.length = 40;
}
if (this.bufferStream.length > 60) {
this.bufferWasCleared = true;
this.bufferStream.length = 40;
}
}
}