import { Component, OnInit, Input, Output, EventEmitter, ViewChild, ElementRef } from "@angular/core"; import { faStar, faRetweet, faList, faThumbtack, faEdit } from "@fortawesome/free-solid-svg-icons"; import { Subscription } from "rxjs"; import { Status, Account, Translation } from "../../../services/models/mastodon.interfaces"; import { OpenThreadEvent, ToolsService } from "../../../services/tools.service"; import { ActionBarComponent } from "./action-bar/action-bar.component"; import { StatusWrapper } from '../../../models/common.model'; import { EmojiConverter, EmojiTypeEnum } from '../../../tools/emoji.tools'; import { ContentWarningPolicyEnum } from '../../../states/settings.state'; import { StatusesStateService, StatusState } from "../../../services/statuses-state.service"; import { DatabindedTextComponent } from "./databinded-text/databinded-text.component"; @Component({ selector: "app-status", templateUrl: "./status.component.html", styleUrls: ["./status.component.scss"] }) export class StatusComponent implements OnInit { private emojiConverter = new EmojiConverter(); faStar = faStar; faRetweet = faRetweet; faList = faList; faThumbtack = faThumbtack; faEdit = faEdit; displayedStatus: Status; displayedStatusWrapper: StatusWrapper; // statusAccountName: string; statusContent: string; reblog: boolean; hasAttachments: boolean; replyingToStatus: boolean; isCrossPoster: boolean; isThread: boolean; isOld: boolean; isContentWarned: boolean; hasReply: boolean; contentWarningText: string; isDirectMessage: boolean; isSelected: boolean; isRemote: boolean; hideStatus: boolean = false; @Output() browseAccountEvent = new EventEmitter(); @Output() browseHashtagEvent = new EventEmitter(); @Output() browseThreadEvent = new EventEmitter(); @ViewChild('appActionBar') appActionBar: ActionBarComponent; @Input() isThreadDisplay: boolean; @Input() notificationType: 'mention' | 'reblog' | 'favourite' | 'poll' | 'update'; @Input() notificationAccount: Account; private _statusWrapper: StatusWrapper; status: Status; private statusesStateServiceSub: Subscription; @Input('statusWrapper') set statusWrapper(value: StatusWrapper) { this._statusWrapper = value; this.status = value.status; this.isSelected = value.isSelected; this.isRemote = value.isRemote; if (this.status.reblog) { this.reblog = true; this.displayedStatus = this.status.reblog; } else { this.displayedStatus = this.status; } this.isDirectMessage = this.displayedStatus.visibility === 'direct'; let cwPolicy = this.toolsService.checkContentWarning(this.displayedStatus); this.displayedStatusWrapper = new StatusWrapper(cwPolicy.status, value.provider, cwPolicy.applyCw, cwPolicy.hide); this.displayedStatusWrapper.isRemote = value.isRemote; this.checkLabels(this.displayedStatus); this.setContentWarning(this.displayedStatusWrapper); if (!this.displayedStatus.account.display_name) { this.displayedStatus.account.display_name = this.displayedStatus.account.username; } if (this.displayedStatus.media_attachments && this.displayedStatus.media_attachments.length > 0) { this.hasAttachments = true; } // const instanceUrl = 'https://' + this.status.uri.split('https://')[1].split('/')[0]; // this.statusAccountName = this.emojiConverter.applyEmojis(this.displayedStatus.account.emojis, this.displayedStatus.account.display_name, EmojiTypeEnum.small); let statusContent = this.emojiConverter.applyEmojis(this.displayedStatus.emojis, this.displayedStatus.content, EmojiTypeEnum.medium); this.statusContent = this.ensureMentionAreDisplayed(statusContent); } get statusWrapper(): StatusWrapper { return this._statusWrapper; } constructor( public elem: ElementRef, private readonly toolsService: ToolsService, private readonly statusesStateService: StatusesStateService) { } ngOnInit() { this.statusesStateServiceSub = this.statusesStateService.stateNotification.subscribe(notification => { if (this._statusWrapper.status.url === notification.statusId && notification.isEdited) { this.statusWrapper = notification.editedStatus; } }); } ngOnDestroy() { if (this.statusesStateServiceSub) this.statusesStateServiceSub.unsubscribe(); } private ensureMentionAreDisplayed(data: string): string { const mentions = this.displayedStatus.mentions; if (!mentions || mentions.length === 0) return data; let textMentions = ''; for (const m of mentions) { if (!data.includes(m.url)) { textMentions += `@${m.username} ` } } if (textMentions !== '') { data = textMentions + data; } return data; } private setContentWarning(status: StatusWrapper) { this.hideStatus = status.hide; this.isContentWarned = status.applyCw; let spoiler = this.htmlEncode(status.status.spoiler_text); this.contentWarningText = this.emojiConverter.applyEmojis(this.displayedStatus.emojis, spoiler, EmojiTypeEnum.medium); } private htmlEncode(str: string): string { var encodedStr = str.replace(/[\u00A0-\u9999<>\&]/gim, function (i) { return '&#' + i.charCodeAt(0) + ';'; }); return encodedStr; } removeContentWarning(): boolean { this.isContentWarned = false; this.appActionBar.showContent(); return false; } changeCw(cwIsActive: boolean) { this.isContentWarned = cwIsActive; } @ViewChild('databindedtext') public databindedText: DatabindedTextComponent; onTranslation(translation: Translation) { let statusContent = translation.content; // clean up a bit some issues (not reliable) while (statusContent.includes('@')) { statusContent = statusContent.replace('@', '@'); } while (statusContent.includes('h