Merge pull request #26 from NicolasConstant/feature_browse-thread
Feature browse thread
This commit is contained in:
commit
f498b3f563
|
@ -1,5 +1,7 @@
|
||||||
<div class="floating-column">
|
<div class="floating-column">
|
||||||
<app-stream-overlay class="stream-overlay" *ngIf="overlayActive" (closeOverlay)="closeOverlay()" [browseAccount]="overlayAccountToBrowse" [browseHashtag]="overlayHashtagToBrowse"></app-stream-overlay>
|
<app-stream-overlay class="stream-overlay" *ngIf="overlayActive" (closeOverlay)="closeOverlay()"
|
||||||
|
[browseAccountData]="overlayAccountToBrowse"
|
||||||
|
[browseHashtagData]="overlayHashtagToBrowse"></app-stream-overlay>
|
||||||
|
|
||||||
<div class="floating-column__header">
|
<div class="floating-column__header">
|
||||||
<a class="close-button" href (click)="closePanel()" title="close">x</a>
|
<a class="close-button" href (click)="closePanel()" title="close">x</a>
|
||||||
|
@ -8,6 +10,8 @@
|
||||||
<app-manage-account *ngIf="openPanel === 'manageAccount'" [account]="userAccountUsed"></app-manage-account>
|
<app-manage-account *ngIf="openPanel === 'manageAccount'" [account]="userAccountUsed"></app-manage-account>
|
||||||
<app-add-new-status *ngIf="openPanel === 'createNewStatus'"></app-add-new-status>
|
<app-add-new-status *ngIf="openPanel === 'createNewStatus'"></app-add-new-status>
|
||||||
<app-add-new-account *ngIf="openPanel === 'addNewAccount'"></app-add-new-account>
|
<app-add-new-account *ngIf="openPanel === 'addNewAccount'"></app-add-new-account>
|
||||||
<app-search *ngIf="openPanel === 'search'" (browseAccount)="browseAccount($event)" (browseHashtag)="browseHashtag($event)"></app-search>
|
<app-search *ngIf="openPanel === 'search'"
|
||||||
|
(browseAccountEvent)="browseAccount($event)"
|
||||||
|
(browseHashtagEvent)="browseHashtag($event)"></app-search>
|
||||||
<app-settings *ngIf="openPanel === 'settings'"></app-settings>
|
<app-settings *ngIf="openPanel === 'settings'"></app-settings>
|
||||||
</div>
|
</div>
|
|
@ -12,7 +12,7 @@
|
||||||
<div *ngIf="accounts.length > 0" class="search-results">
|
<div *ngIf="accounts.length > 0" class="search-results">
|
||||||
<h3 class="search-results__title">Accounts</h3>
|
<h3 class="search-results__title">Accounts</h3>
|
||||||
<a href *ngFor="let account of accounts" class="account" title="open account"
|
<a href *ngFor="let account of accounts" class="account" title="open account"
|
||||||
(click)="selectAccount(account.acct)">
|
(click)="browseAccount(account.acct)">
|
||||||
<img src="{{account.avatar}}" class="account__avatar" />
|
<img src="{{account.avatar}}" class="account__avatar" />
|
||||||
<div class="account__name">{{ account.username }}</div>
|
<div class="account__name">{{ account.username }}</div>
|
||||||
<div class="account__fullhandle">@{{ account.acct }}</div>
|
<div class="account__fullhandle">@{{ account.acct }}</div>
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
|
|
||||||
<div *ngIf="hashtags.length > 0" class="search-results">
|
<div *ngIf="hashtags.length > 0" class="search-results">
|
||||||
<h3 class="search-results__title">Hashtags</h3>
|
<h3 class="search-results__title">Hashtags</h3>
|
||||||
<a (click)="selectHashtag(hashtag)" href *ngFor="let hashtag of hashtags" class="search-results__hashtag" title="browse hashtag">
|
<a (click)="browseHashtag(hashtag)" href *ngFor="let hashtag of hashtags" class="search-results__hashtag" title="browse hashtag">
|
||||||
#{{ hashtag }}
|
#{{ hashtag }}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
@ -30,7 +30,9 @@
|
||||||
<h3 class="search-results__title">Statuses</h3>
|
<h3 class="search-results__title">Statuses</h3>
|
||||||
|
|
||||||
<div class="search-results__status" *ngFor="let statusWrapper of statuses">
|
<div class="search-results__status" *ngFor="let statusWrapper of statuses">
|
||||||
<app-status [statusWrapper]="statusWrapper" (browseAccount)="browseAccount($event)" (browseHashtag)="browseHashtag($event)"></app-status>
|
<app-status [statusWrapper]="statusWrapper"
|
||||||
|
(browseAccountEvent)="browseAccount($event)"
|
||||||
|
(browseHashtagEvent)="browseHashtag($event)"></app-status>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
|
@ -23,12 +23,11 @@ export class SearchComponent implements OnInit {
|
||||||
|
|
||||||
isLoading: boolean;
|
isLoading: boolean;
|
||||||
|
|
||||||
@Output() browseAccount = new EventEmitter<string>();
|
@Output() browseAccountEvent = new EventEmitter<string>();
|
||||||
@Output() browseHashtag = new EventEmitter<string>();
|
@Output() browseHashtagEvent = new EventEmitter<string>();
|
||||||
@Output() browseThread = new EventEmitter<string>();
|
@Output() browseThreadEvent = new EventEmitter<string>();
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly store: Store,
|
|
||||||
private readonly toolsService: ToolsService,
|
private readonly toolsService: ToolsService,
|
||||||
private readonly mastodonService: MastodonService) { }
|
private readonly mastodonService: MastodonService) { }
|
||||||
|
|
||||||
|
@ -41,9 +40,9 @@ export class SearchComponent implements OnInit {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
selectHashtag(hashtag: string): boolean {
|
browseHashtag(hashtag: string): boolean {
|
||||||
if (hashtag) {
|
if (hashtag) {
|
||||||
this.browseHashtag.next(hashtag);
|
this.browseHashtagEvent.next(hashtag);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -57,10 +56,10 @@ export class SearchComponent implements OnInit {
|
||||||
// return false;
|
// return false;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
selectAccount(accountName: string): boolean {
|
browseAccount(accountName: string): boolean {
|
||||||
console.warn(accountName);
|
console.warn(accountName);
|
||||||
if (accountName) {
|
if (accountName) {
|
||||||
this.browseAccount.next(accountName);
|
this.browseAccountEvent.next(accountName);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -97,9 +96,4 @@ export class SearchComponent implements OnInit {
|
||||||
.then(() => { this.isLoading = false; });
|
.then(() => { this.isLoading = false; });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private getRegisteredAccounts(): AccountInfo[] {
|
|
||||||
var regAccounts = <AccountInfo[]>this.store.snapshot().registeredaccounts.accounts;
|
|
||||||
return regAccounts;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,10 @@
|
||||||
<button class="btn-custom-secondary hashtag-header__add-column" (click)="addColumn($event)" title="add column to board">add column</button>
|
<button class="btn-custom-secondary hashtag-header__add-column" (click)="addColumn($event)" title="add column to board">add column</button>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<app-stream-statuses class="hashtag-stream" *ngIf="hashtagElement" [streamElement]="hashtagElement" [goToTop]="goToTopSubject.asObservable()"
|
<app-stream-statuses class="hashtag-stream" *ngIf="hashtagElement"
|
||||||
(browseAccount)="selectAccount($event)" (browseHashtag)="selectHashtag($event)"></app-stream-statuses>
|
[streamElement]="hashtagElement"
|
||||||
|
[goToTop]="goToTopSubject.asObservable()"
|
||||||
|
(browseAccountEvent)="browseAccount($event)"
|
||||||
|
(browseHashtagEvent)="browseHashtag($event)"
|
||||||
|
(browseThreadEvent)="browseThread($event)"></app-stream-statuses>
|
||||||
</div>
|
</div>
|
|
@ -10,8 +10,9 @@ import { StreamElement, StreamTypeEnum, AddStream } from '../../../states/stream
|
||||||
styleUrls: ['./hashtag.component.scss']
|
styleUrls: ['./hashtag.component.scss']
|
||||||
})
|
})
|
||||||
export class HashtagComponent implements OnInit {
|
export class HashtagComponent implements OnInit {
|
||||||
@Output() browseAccount = new EventEmitter<string>();
|
@Output() browseAccountEvent = new EventEmitter<string>();
|
||||||
@Output() browseHashtag = new EventEmitter<string>();
|
@Output() browseHashtagEvent = new EventEmitter<string>();
|
||||||
|
@Output() browseThreadEvent = new EventEmitter<string>();
|
||||||
|
|
||||||
@Input() hashtagElement: StreamElement;
|
@Input() hashtagElement: StreamElement;
|
||||||
|
|
||||||
|
@ -38,11 +39,15 @@ export class HashtagComponent implements OnInit {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
selectAccount(account: string) {
|
browseAccount(account: string) {
|
||||||
this.browseAccount.next(account);
|
this.browseAccountEvent.next(account);
|
||||||
}
|
}
|
||||||
|
|
||||||
selectHashtag(hashtag: string) {
|
browseHashtag(hashtag: string) {
|
||||||
this.browseHashtag.next(hashtag);
|
this.browseHashtagEvent.next(hashtag);
|
||||||
|
}
|
||||||
|
|
||||||
|
browseThread(statusUri: string): void {
|
||||||
|
this.browseThreadEvent.next(statusUri);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,7 @@
|
||||||
import { Component, OnInit, Input, Output, Inject, LOCALE_ID, ElementRef, EventEmitter, Pipe, PipeTransform, ViewChild, Renderer2 } from "@angular/core";
|
import { Component, OnInit, Input, Output, EventEmitter } from "@angular/core";
|
||||||
import { Status, Account } from "../../../services/models/mastodon.interfaces";
|
import { Status, Account } from "../../../services/models/mastodon.interfaces";
|
||||||
import { formatDate } from '@angular/common';
|
|
||||||
import { stateNameErrorMessage } from "@ngxs/store/src/decorators/state";
|
|
||||||
import { StatusWrapper } from "../stream.component";
|
import { StatusWrapper } from "../stream.component";
|
||||||
|
|
||||||
import { DomSanitizer } from '@angular/platform-browser'
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: "app-status",
|
selector: "app-status",
|
||||||
templateUrl: "./status.component.html",
|
templateUrl: "./status.component.html",
|
||||||
|
@ -17,9 +13,9 @@ export class StatusComponent implements OnInit {
|
||||||
hasAttachments: boolean;
|
hasAttachments: boolean;
|
||||||
replyingToStatus: boolean;
|
replyingToStatus: boolean;
|
||||||
|
|
||||||
@Output() browseAccount = new EventEmitter<string>();
|
@Output() browseAccountEvent = new EventEmitter<string>();
|
||||||
@Output() browseHashtag = new EventEmitter<string>();
|
@Output() browseHashtagEvent = new EventEmitter<string>();
|
||||||
@Output() browseThread = new EventEmitter<string>();
|
@Output() browseThreadEvent = new EventEmitter<string>();
|
||||||
|
|
||||||
private _statusWrapper: StatusWrapper;
|
private _statusWrapper: StatusWrapper;
|
||||||
status: Status;
|
status: Status;
|
||||||
|
@ -28,10 +24,6 @@ export class StatusComponent implements OnInit {
|
||||||
this._statusWrapper = value;
|
this._statusWrapper = value;
|
||||||
this.status = value.status;
|
this.status = value.status;
|
||||||
|
|
||||||
//TEST
|
|
||||||
//this.status.content += '<br/><br/><a href class="test">TEST</a>';
|
|
||||||
|
|
||||||
|
|
||||||
if (this.status.reblog) {
|
if (this.status.reblog) {
|
||||||
this.reblog = true;
|
this.reblog = true;
|
||||||
this.displayedStatus = this.status.reblog;
|
this.displayedStatus = this.status.reblog;
|
||||||
|
@ -46,58 +38,25 @@ export class StatusComponent implements OnInit {
|
||||||
if (this.displayedStatus.media_attachments && this.displayedStatus.media_attachments.length > 0) {
|
if (this.displayedStatus.media_attachments && this.displayedStatus.media_attachments.length > 0) {
|
||||||
this.hasAttachments = true;
|
this.hasAttachments = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
get statusWrapper(): StatusWrapper {
|
get statusWrapper(): StatusWrapper {
|
||||||
return this._statusWrapper;
|
return this._statusWrapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constructor() { }
|
||||||
constructor(@Inject(LOCALE_ID) private locale: string) { }
|
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ngAfterViewInit() {
|
|
||||||
// let el = this.contentElement.nativeElement.querySelector('.test');
|
|
||||||
// console.log(this.contentElement.nativeElement);
|
|
||||||
// console.log(el);
|
|
||||||
// if (el)
|
|
||||||
// this.renderer.listen(el, 'click', (el2) => {
|
|
||||||
// console.log(el2);
|
|
||||||
// console.warn('YOOOOO');
|
|
||||||
// return false;
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
|
|
||||||
openAccount(account: Account): boolean {
|
openAccount(account: Account): boolean {
|
||||||
let accountName = account.acct;
|
let accountName = account.acct;
|
||||||
if(!accountName.includes('@'))
|
if (!accountName.includes('@'))
|
||||||
accountName += `@${account.url.replace('https://', '').split('/')[0]}`;
|
accountName += `@${account.url.replace('https://', '').split('/')[0]}`;
|
||||||
|
|
||||||
this.browseAccount.next(accountName);
|
this.browseAccountEvent.next(accountName);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// getCompactRelativeTime(d: string): string {
|
|
||||||
// const date = (new Date(d)).getTime();
|
|
||||||
// const now = Date.now();
|
|
||||||
// const timeDelta = (now - date) / (1000);
|
|
||||||
|
|
||||||
// if (timeDelta < 60) {
|
|
||||||
// return `${timeDelta | 0}s`;
|
|
||||||
// } else if (timeDelta < 60 * 60) {
|
|
||||||
// return `${timeDelta / 60 | 0}m`;
|
|
||||||
// } else if (timeDelta < 60 * 60 * 24) {
|
|
||||||
// return `${timeDelta / (60 * 60) | 0}h`;
|
|
||||||
// } else if (timeDelta < 60 * 60 * 24 * 31) {
|
|
||||||
// return `${timeDelta / (60 * 60 * 24) | 0}d`;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return formatDate(date, 'MM/dd', this.locale);
|
|
||||||
// }
|
|
||||||
|
|
||||||
openReply(): boolean {
|
openReply(): boolean {
|
||||||
this.replyingToStatus = !this.replyingToStatus;
|
this.replyingToStatus = !this.replyingToStatus;
|
||||||
|
|
||||||
|
@ -109,22 +68,21 @@ export class StatusComponent implements OnInit {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// test(): boolean {
|
|
||||||
// console.warn('heeeeyaaa!');
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
|
|
||||||
accountSelected(accountName: string): void {
|
accountSelected(accountName: string): void {
|
||||||
console.warn(`status comp: accountSelected ${accountName}`);
|
this.browseAccountEvent.next(accountName);
|
||||||
this.browseAccount.next(accountName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hashtagSelected(hashtag: string): void {
|
hashtagSelected(hashtag: string): void {
|
||||||
console.warn(`status comp: hashtagSelected ${hashtag}`);
|
this.browseHashtagEvent.next(hashtag);
|
||||||
this.browseHashtag.next(hashtag);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
textSelected(): void {
|
textSelected(): void {
|
||||||
console.warn(`status comp: textSelected`);
|
const status = this._statusWrapper.status;
|
||||||
|
|
||||||
|
if (status.reblog) {
|
||||||
|
this.browseThreadEvent.next(status.reblog.uri);
|
||||||
|
} else {
|
||||||
|
this.browseThreadEvent.next(this._statusWrapper.status.uri);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,11 +5,17 @@
|
||||||
<a href class="overlay-refresh" *ngIf="canRefresh" (click)="refresh()">REFRESH</a>
|
<a href class="overlay-refresh" *ngIf="canRefresh" (click)="refresh()">REFRESH</a>
|
||||||
<a href class="overlay-next" *ngIf="canGoForward" (click)="next()">NEXT</a>
|
<a href class="overlay-next" *ngIf="canGoForward" (click)="next()">NEXT</a>
|
||||||
</div>
|
</div>
|
||||||
<!-- <div class="stream-overlay__title">
|
|
||||||
Account
|
|
||||||
</div> -->
|
|
||||||
|
|
||||||
<app-user-profile *ngIf="accountName" [currentAccount]="accountName" (browseAccount)="accountSelected($event)" (browseHashtag)="hashtagSelected($event)"></app-user-profile>
|
<app-user-profile *ngIf="accountName" [currentAccount]="accountName"
|
||||||
<app-hashtag *ngIf="hashtagElement" [hashtagElement]="hashtagElement" (browseAccount)="accountSelected($event)" (browseHashtag)="hashtagSelected($event)"></app-hashtag>
|
(browseAccountEvent)="browseAccount($event)"
|
||||||
<app-thread *ngIf="browseThread"></app-thread>
|
(browseHashtagEvent)="browseHashtag($event)"
|
||||||
|
(browseThreadEvent)="browseThread($event)"></app-user-profile>
|
||||||
|
<app-hashtag *ngIf="hashtagElement" [hashtagElement]="hashtagElement"
|
||||||
|
(browseAccountEvent)="browseAccount($event)"
|
||||||
|
(browseHashtagEvent)="browseHashtag($event)"
|
||||||
|
(browseThreadEvent)="browseThread($event)"></app-hashtag>
|
||||||
|
<app-thread *ngIf="browseThread" [currentThread]="thread"
|
||||||
|
(browseAccountEvent)="browseAccount($event)"
|
||||||
|
(browseHashtagEvent)="browseHashtag($event)"
|
||||||
|
(browseThreadEvent)="browseThread($event)"></app-thread>
|
||||||
</div>
|
</div>
|
|
@ -10,6 +10,7 @@ import { StreamElement, StreamTypeEnum } from '../../../states/streams.state';
|
||||||
styleUrls: ['./stream-overlay.component.scss']
|
styleUrls: ['./stream-overlay.component.scss']
|
||||||
})
|
})
|
||||||
export class StreamOverlayComponent implements OnInit {
|
export class StreamOverlayComponent implements OnInit {
|
||||||
|
|
||||||
private previousElements: OverlayBrowsing[] = [];
|
private previousElements: OverlayBrowsing[] = [];
|
||||||
private nextElements: OverlayBrowsing[] = [];
|
private nextElements: OverlayBrowsing[] = [];
|
||||||
private currentElement: OverlayBrowsing;
|
private currentElement: OverlayBrowsing;
|
||||||
|
@ -24,21 +25,20 @@ export class StreamOverlayComponent implements OnInit {
|
||||||
|
|
||||||
@Output() closeOverlay = new EventEmitter();
|
@Output() closeOverlay = new EventEmitter();
|
||||||
|
|
||||||
@Input('browseAccount')
|
@Input('browseAccountData')
|
||||||
set browseAccount(accountName: string) {
|
set browseAccountData(accountName: string) {
|
||||||
this.accountSelected(accountName);
|
this.browseAccount(accountName);
|
||||||
// this.accountName = accountName;
|
// this.accountName = accountName;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Input('browseThread')
|
@Input('browseThreadData')
|
||||||
set browseThread(thread: string) {
|
set browseThreadData(statusUri: string) {
|
||||||
// this.thread = thread;
|
this.browseThread(statusUri);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Input('browseHashtag')
|
@Input('browseHashtagData')
|
||||||
set browseHashtag(hashtag: string) {
|
set browseHashtagData(hashtag: string) {
|
||||||
this.hashtagSelected(hashtag);
|
this.browseHashtag(hashtag);
|
||||||
// this.hashtag = hashtag;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(private toolsService: ToolsService) { }
|
constructor(private toolsService: ToolsService) { }
|
||||||
|
@ -93,7 +93,7 @@ export class StreamOverlayComponent implements OnInit {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
accountSelected(accountName: string): void {
|
browseAccount(accountName: string): void {
|
||||||
if(!accountName) return;
|
if(!accountName) return;
|
||||||
|
|
||||||
console.log('accountSelected');
|
console.log('accountSelected');
|
||||||
|
@ -106,7 +106,7 @@ export class StreamOverlayComponent implements OnInit {
|
||||||
this.canGoForward = false;
|
this.canGoForward = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
hashtagSelected(hashtag: string): void {
|
browseHashtag(hashtag: string): void {
|
||||||
if(!hashtag) return;
|
if(!hashtag) return;
|
||||||
|
|
||||||
console.log('hashtagSelected');
|
console.log('hashtagSelected');
|
||||||
|
@ -122,6 +122,20 @@ export class StreamOverlayComponent implements OnInit {
|
||||||
this.canGoForward = false;
|
this.canGoForward = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
browseThread(statusUri: string): any {
|
||||||
|
if(!statusUri) return;
|
||||||
|
|
||||||
|
console.log('thread selected')
|
||||||
|
this.nextElements.length = 0;
|
||||||
|
if (this.currentElement) {
|
||||||
|
this.previousElements.push(this.currentElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
const newElement = new OverlayBrowsing(null, null, statusUri);
|
||||||
|
this.loadElement(newElement);
|
||||||
|
this.canGoForward = false;
|
||||||
|
}
|
||||||
|
|
||||||
private loadElement(element: OverlayBrowsing) {
|
private loadElement(element: OverlayBrowsing) {
|
||||||
this.currentElement = element;
|
this.currentElement = element;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
<div class="stream-toots flexcroll" #statusstream (scroll)="onScroll()">
|
<div class="stream-toots flexcroll" #statusstream (scroll)="onScroll()">
|
||||||
|
<app-waiting-animation *ngIf="isLoading" class="waiting-icon"></app-waiting-animation>
|
||||||
|
|
||||||
<!-- data-simplebar -->
|
<!-- data-simplebar -->
|
||||||
<div class="stream-toots__status" *ngFor="let statusWrapper of statuses">
|
<div class="stream-toots__status" *ngFor="let statusWrapper of statuses">
|
||||||
<app-status [statusWrapper]="statusWrapper" (browseAccount)="accountSelected($event)" (browseHashtag)="hashtagSelected($event)"></app-status>
|
<app-status [statusWrapper]="statusWrapper" (browseAccountEvent)="browseAccount($event)" (browseHashtagEvent)="browseHashtag($event)"
|
||||||
|
(browseThreadEvent)="browseThread($event)"></app-status>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
|
@ -16,6 +16,7 @@ import { StatusWrapper } from '../stream.component';
|
||||||
styleUrls: ['./stream-statuses.component.scss']
|
styleUrls: ['./stream-statuses.component.scss']
|
||||||
})
|
})
|
||||||
export class StreamStatusesComponent implements OnInit, OnDestroy {
|
export class StreamStatusesComponent implements OnInit, OnDestroy {
|
||||||
|
isLoading = false; //TODO
|
||||||
|
|
||||||
private _streamElement: StreamElement;
|
private _streamElement: StreamElement;
|
||||||
private account: AccountInfo;
|
private account: AccountInfo;
|
||||||
|
@ -25,9 +26,9 @@ export class StreamStatusesComponent implements OnInit, OnDestroy {
|
||||||
private bufferStream: Status[] = [];
|
private bufferStream: Status[] = [];
|
||||||
private bufferWasCleared: boolean;
|
private bufferWasCleared: boolean;
|
||||||
|
|
||||||
@Output() browseAccount = new EventEmitter<string>();
|
@Output() browseAccountEvent = new EventEmitter<string>();
|
||||||
@Output() browseHashtag = new EventEmitter<string>();
|
@Output() browseHashtagEvent = new EventEmitter<string>();
|
||||||
@Output() browseThread = new EventEmitter<string>();
|
@Output() browseThreadEvent = new EventEmitter<string>();
|
||||||
|
|
||||||
@Input()
|
@Input()
|
||||||
set streamElement(streamElement: StreamElement) {
|
set streamElement(streamElement: StreamElement) {
|
||||||
|
@ -125,14 +126,16 @@ export class StreamStatusesComponent implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
accountSelected(accountName: string): void {
|
browseAccount(accountName: string): void {
|
||||||
console.warn(`status comp: accountSelected ${accountName}`);
|
this.browseAccountEvent.next(accountName);
|
||||||
this.browseAccount.next(accountName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hashtagSelected(hashtag: string): void {
|
browseHashtag(hashtag: string): void {
|
||||||
console.warn(`status comp: hashtagSelected ${hashtag}`);
|
this.browseHashtagEvent.next(hashtag);
|
||||||
this.browseHashtag.next(hashtag);
|
}
|
||||||
|
|
||||||
|
browseThread(statusUri: string): void {
|
||||||
|
this.browseThreadEvent.next(statusUri);
|
||||||
}
|
}
|
||||||
|
|
||||||
textSelected(): void {
|
textSelected(): void {
|
||||||
|
|
|
@ -2,15 +2,16 @@
|
||||||
|
|
||||||
<app-stream-overlay class="stream-overlay" *ngIf="overlayActive"
|
<app-stream-overlay class="stream-overlay" *ngIf="overlayActive"
|
||||||
(closeOverlay)="closeOverlay()"
|
(closeOverlay)="closeOverlay()"
|
||||||
[browseAccount]="overlayAccountToBrowse"
|
[browseAccountData]="overlayAccountToBrowse"
|
||||||
[browseHashtag]="overlayHashtagToBrowse"></app-stream-overlay>
|
[browseHashtagData]="overlayHashtagToBrowse"
|
||||||
|
[browseThreadData]="overlayThreadToBrowse"></app-stream-overlay>
|
||||||
|
|
||||||
<div class="stream-column__stream-header">
|
<div class="stream-column__stream-header">
|
||||||
<a href title="return to top" (click)="goToTop()">
|
<a href title="return to top" (click)="goToTop()">
|
||||||
<h1>{{ streamElement.name.toUpperCase() }}</h1>
|
<h1>{{ streamElement.name.toUpperCase() }}</h1>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<app-stream-statuses class="stream-statuses" [streamElement]="streamElement" [goToTop]="goToTopSubject.asObservable()" (browseAccount)="browseAccount($event)" (browseHashtag)="browseHashtag($event)"></app-stream-statuses>
|
<app-stream-statuses class="stream-statuses" [streamElement]="streamElement" [goToTop]="goToTopSubject.asObservable()" (browseAccountEvent)="browseAccount($event)" (browseHashtagEvent)="browseHashtag($event)" (browseThreadEvent)="browseThread($event)"></app-stream-statuses>
|
||||||
<!-- <div class="stream-toots flexcroll" #statusstream (scroll)="onScroll()">
|
<!-- <div class="stream-toots flexcroll" #statusstream (scroll)="onScroll()">
|
||||||
<div class="stream-toots__status" *ngFor="let statusWrapper of statuses">
|
<div class="stream-toots__status" *ngFor="let statusWrapper of statuses">
|
||||||
<app-status [statusWrapper]="statusWrapper" (browseAccount)="browseAccount($event)" (browseHashtag)="browseHashtag($event)"></app-status>
|
<app-status [statusWrapper]="statusWrapper" (browseAccount)="browseAccount($event)" (browseHashtag)="browseHashtag($event)"></app-status>
|
||||||
|
|
|
@ -14,6 +14,7 @@ export class StreamComponent implements OnInit {
|
||||||
overlayActive: boolean;
|
overlayActive: boolean;
|
||||||
overlayAccountToBrowse: string;
|
overlayAccountToBrowse: string;
|
||||||
overlayHashtagToBrowse: string;
|
overlayHashtagToBrowse: string;
|
||||||
|
overlayThreadToBrowse: string;
|
||||||
|
|
||||||
goToTopSubject: Subject<void> = new Subject<void>();
|
goToTopSubject: Subject<void> = new Subject<void>();
|
||||||
|
|
||||||
|
@ -32,22 +33,28 @@ export class StreamComponent implements OnInit {
|
||||||
browseAccount(account: string): void {
|
browseAccount(account: string): void {
|
||||||
this.overlayAccountToBrowse = account;
|
this.overlayAccountToBrowse = account;
|
||||||
this.overlayHashtagToBrowse = null;
|
this.overlayHashtagToBrowse = null;
|
||||||
|
this.overlayThreadToBrowse = null;
|
||||||
this.overlayActive = true;
|
this.overlayActive = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
browseHashtag(hashtag: string): void {
|
browseHashtag(hashtag: string): void {
|
||||||
this.overlayAccountToBrowse = null;
|
this.overlayAccountToBrowse = null;
|
||||||
this.overlayHashtagToBrowse = hashtag;
|
this.overlayHashtagToBrowse = hashtag;
|
||||||
|
this.overlayThreadToBrowse = null;
|
||||||
this.overlayActive = true;
|
this.overlayActive = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
browseThread(thread: string): void {
|
browseThread(statusUri: string): void {
|
||||||
console.warn('browseThread');
|
this.overlayAccountToBrowse = null;
|
||||||
console.warn(thread);
|
this.overlayHashtagToBrowse = null;
|
||||||
|
this.overlayThreadToBrowse = statusUri;
|
||||||
|
this.overlayActive = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
closeOverlay(): void {
|
closeOverlay(): void {
|
||||||
this.overlayAccountToBrowse = null;
|
this.overlayAccountToBrowse = null;
|
||||||
|
this.overlayHashtagToBrowse = null;
|
||||||
|
this.overlayThreadToBrowse = null;
|
||||||
this.overlayActive = false;
|
this.overlayActive = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
<p>
|
|
||||||
thread works!
|
|
||||||
</p>
|
|
|
@ -1,15 +1,77 @@
|
||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
|
||||||
|
import { StatusWrapper } from '../stream.component';
|
||||||
|
import { MastodonService } from '../../../services/mastodon.service';
|
||||||
|
import { ToolsService } from '../../../services/tools.service';
|
||||||
|
import { Status, Results, Context } from '../../../services/models/mastodon.interfaces';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-thread',
|
selector: 'app-thread',
|
||||||
templateUrl: './thread.component.html',
|
templateUrl: '../stream-statuses/stream-statuses.component.html',
|
||||||
styleUrls: ['./thread.component.scss']
|
styleUrls: ['../stream-statuses/stream-statuses.component.scss']
|
||||||
})
|
})
|
||||||
export class ThreadComponent implements OnInit {
|
export class ThreadComponent implements OnInit {
|
||||||
|
statuses: StatusWrapper[] = [];
|
||||||
|
isLoading: boolean;
|
||||||
|
|
||||||
constructor() { }
|
@Output() browseAccountEvent = new EventEmitter<string>();
|
||||||
|
@Output() browseHashtagEvent = new EventEmitter<string>();
|
||||||
|
@Output() browseThreadEvent = new EventEmitter<string>();
|
||||||
|
|
||||||
|
@Input('currentThread')
|
||||||
|
set currentThread(thread: string) {
|
||||||
|
if (thread) {
|
||||||
|
this.isLoading = true;
|
||||||
|
this.getThread(thread);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private readonly toolsService: ToolsService,
|
||||||
|
private readonly mastodonService: MastodonService) { }
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private getThread(thread: string) {
|
||||||
|
this.statuses.length = 0;
|
||||||
|
|
||||||
|
let currentAccount = this.toolsService.getSelectedAccounts()[0];
|
||||||
|
|
||||||
|
this.mastodonService.search(currentAccount, thread, true)
|
||||||
|
.then((result: Results) => {
|
||||||
|
if (result.statuses.length === 1) {
|
||||||
|
const retrievedStatus = result.statuses[0];
|
||||||
|
this.mastodonService.getStatusContext(currentAccount, retrievedStatus.id)
|
||||||
|
.then((context: Context) => {
|
||||||
|
this.isLoading = false;
|
||||||
|
let contextStatuses = [...context.ancestors, retrievedStatus, ...context.descendants]
|
||||||
|
|
||||||
|
for (const s of contextStatuses) {
|
||||||
|
const wrapper = new StatusWrapper(s, currentAccount);
|
||||||
|
this.statuses.push(wrapper);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
//TODO handle error
|
||||||
|
this.isLoading = false;
|
||||||
|
console.error('could not retrieve status');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onScroll() {
|
||||||
|
//Do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
browseAccount(accountName: string): void {
|
||||||
|
this.browseAccountEvent.next(accountName);
|
||||||
|
}
|
||||||
|
|
||||||
|
browseHashtag(hashtag: string): void {
|
||||||
|
this.browseHashtagEvent.next(hashtag);
|
||||||
|
}
|
||||||
|
|
||||||
|
browseThread(statusUri: string): void {
|
||||||
|
this.browseThreadEvent.next(statusUri);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,8 @@
|
||||||
<div class="profile-sub-header flexcroll">
|
<div class="profile-sub-header flexcroll">
|
||||||
<div *ngIf="account && hasNote" class="profile-description">
|
<div *ngIf="account && hasNote" class="profile-description">
|
||||||
<app-databinded-text class="status__content" [textIsSelectable]="false" [text]="account.note"
|
<app-databinded-text class="status__content" [textIsSelectable]="false" [text]="account.note"
|
||||||
(accountSelected)="accountSelected($event)" (hashtagSelected)="hashtagSelected($event)"></app-databinded-text>
|
(accountSelected)="browseAccount($event)"
|
||||||
|
(hashtagSelected)="browseHashtag($event)"></app-databinded-text>
|
||||||
<!-- <p innerHTML="{{account.note}}"></p> -->
|
<!-- <p innerHTML="{{account.note}}"></p> -->
|
||||||
</div>
|
</div>
|
||||||
<div class="profile-statuses">
|
<div class="profile-statuses">
|
||||||
|
@ -24,7 +25,10 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div *ngFor="let statusWrapper of statuses">
|
<div *ngFor="let statusWrapper of statuses">
|
||||||
<app-status [statusWrapper]="statusWrapper" (browseAccount)="accountSelected($event)"></app-status>
|
<app-status [statusWrapper]="statusWrapper"
|
||||||
|
(browseHashtagEvent)="browseHashtag($event)"
|
||||||
|
(browseAccountEvent)="browseAccount($event)"
|
||||||
|
(browseThreadEvent)="browseThread($event)"></app-status>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -21,8 +21,9 @@ export class UserProfileComponent implements OnInit {
|
||||||
|
|
||||||
private accountName: string;
|
private accountName: string;
|
||||||
|
|
||||||
@Output() browseAccount = new EventEmitter<string>();
|
@Output() browseAccountEvent = new EventEmitter<string>();
|
||||||
@Output() browseHashtag = new EventEmitter<string>();
|
@Output() browseHashtagEvent = new EventEmitter<string>();
|
||||||
|
@Output() browseThreadEvent = new EventEmitter<string>();
|
||||||
|
|
||||||
@Input('currentAccount')
|
@Input('currentAccount')
|
||||||
//set currentAccount(account: Account) {
|
//set currentAccount(account: Account) {
|
||||||
|
@ -51,12 +52,16 @@ export class UserProfileComponent implements OnInit {
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
}
|
}
|
||||||
|
|
||||||
accountSelected(accountName: string): void {
|
browseAccount(accountName: string): void {
|
||||||
this.browseAccount.next(accountName);
|
this.browseAccountEvent.next(accountName);
|
||||||
}
|
}
|
||||||
|
|
||||||
hashtagSelected(hashtag: string): void {
|
browseHashtag(hashtag: string): void {
|
||||||
this.browseHashtag.next(hashtag);
|
this.browseHashtagEvent.next(hashtag);
|
||||||
|
}
|
||||||
|
|
||||||
|
browseThread(statusUri: string): void {
|
||||||
|
this.browseThreadEvent.next(statusUri);
|
||||||
}
|
}
|
||||||
|
|
||||||
private loadAccount(accountName: string): Promise<Account> {
|
private loadAccount(accountName: string): Promise<Account> {
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { Injectable } from '@angular/core';
|
||||||
import { HttpHeaders, HttpClient } from '@angular/common/http';
|
import { HttpHeaders, HttpClient } from '@angular/common/http';
|
||||||
|
|
||||||
import { ApiRoutes } from './models/api.settings';
|
import { ApiRoutes } from './models/api.settings';
|
||||||
import { Account, Status, Results } from "./models/mastodon.interfaces";
|
import { Account, Status, Results, Context } from "./models/mastodon.interfaces";
|
||||||
import { AccountInfo } from '../states/accounts.state';
|
import { AccountInfo } from '../states/accounts.state';
|
||||||
import { StreamTypeEnum } from '../states/streams.state';
|
import { StreamTypeEnum } from '../states/streams.state';
|
||||||
import { stat } from 'fs';
|
import { stat } from 'fs';
|
||||||
|
@ -129,6 +129,14 @@ export class MastodonService {
|
||||||
return this.httpClient.get<Status[]>(route+params, { headers: headers }).toPromise();
|
return this.httpClient.get<Status[]>(route+params, { headers: headers }).toPromise();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getStatusContext(account: AccountInfo, targetStatusId: string): Promise<Context>{
|
||||||
|
const params = this.apiRoutes.getStatusContext.replace('{0}', targetStatusId);
|
||||||
|
const route = `https://${account.instance}${params}`;
|
||||||
|
|
||||||
|
const headers = new HttpHeaders({ 'Authorization': `Bearer ${account.token.access_token}` });
|
||||||
|
return this.httpClient.get<Context>(route, { headers: headers }).toPromise();
|
||||||
|
}
|
||||||
|
|
||||||
searchAccount(account: AccountInfo, query: string, limit: number = 40, following: boolean = false): Promise<Account[]>{
|
searchAccount(account: AccountInfo, query: string, limit: number = 40, following: boolean = false): Promise<Account[]>{
|
||||||
const route = `https://${account.instance}${this.apiRoutes.searchForAccounts}?q=${query}&limit=${limit}&following=${following}`;
|
const route = `https://${account.instance}${this.apiRoutes.searchForAccounts}?q=${query}&limit=${limit}&following=${following}`;
|
||||||
const headers = new HttpHeaders({ 'Authorization': `Bearer ${account.token.access_token}` });
|
const headers = new HttpHeaders({ 'Authorization': `Bearer ${account.token.access_token}` });
|
||||||
|
|
Loading…
Reference in New Issue