From 71139eb4c092ae8f8f5fedde47df70f1eef58b37 Mon Sep 17 00:00:00 2001 From: Nicolas Constant Date: Wed, 1 Apr 2020 02:29:51 -0400 Subject: [PATCH 1/2] fix cw analysis issues in thread --- .../create-status/create-status.component.ts | 6 +- .../bookmarks/bookmarks.component.ts | 10 ++- .../direct-messages.component.ts | 16 ++-- .../favorites/favorites.component.ts | 9 +- .../mentions/mentions.component.ts | 9 +- .../notifications/notifications.component.ts | 13 +-- .../search/search.component.ts | 3 +- .../status/action-bar/action-bar.component.ts | 4 +- .../status-user-context-menu.component.ts | 3 +- .../stream/status/poll/poll.component.ts | 3 +- .../stream/status/status.component.ts | 89 ++++++++++--------- .../stream-notifications.component.ts | 21 +++-- .../stream-statuses.component.ts | 12 ++- .../stream/thread/thread.component.ts | 5 +- .../user-profile/user-profile.component.ts | 6 +- src/app/models/common.model.ts | 4 +- src/app/services/tools.service.ts | 65 +++++++++++++- 17 files changed, 187 insertions(+), 91 deletions(-) diff --git a/src/app/components/create-status/create-status.component.ts b/src/app/components/create-status/create-status.component.ts index 7dd6acb0..41f05df0 100644 --- a/src/app/components/create-status/create-status.component.ts +++ b/src/app/components/create-status/create-status.component.ts @@ -81,7 +81,8 @@ export class CreateStatusComponent implements OnInit, OnDestroy { this.isSending = true; this.mastodonService.getStatus(value.provider, value.status.in_reply_to_id) .then((status: Status) => { - this.statusReplyingToWrapper = new StatusWrapper(status, value.provider); + let cwResult = this.toolsService.checkContentWarning(status); + this.statusReplyingToWrapper = new StatusWrapper(cwResult.status, value.provider, cwResult.applyCw, cwResult.hide); const mentions = this.getMentions(this.statusReplyingToWrapper.status, this.statusReplyingToWrapper.provider); for (const mention of mentions) { @@ -564,7 +565,8 @@ export class CreateStatusComponent implements OnInit, OnDestroy { }) .then((status: Status) => { if (this.statusReplyingToWrapper) { - this.notificationService.newStatusPosted(this.statusReplyingToWrapper.status.id, new StatusWrapper(status, account)); + let cwPolicy = this.toolsService.checkContentWarning(status); + this.notificationService.newStatusPosted(this.statusReplyingToWrapper.status.id, new StatusWrapper(cwPolicy.status, account, cwPolicy.applyCw, cwPolicy.hide)); } return status; diff --git a/src/app/components/floating-column/manage-account/bookmarks/bookmarks.component.ts b/src/app/components/floating-column/manage-account/bookmarks/bookmarks.component.ts index 87f6aad1..05f5ded4 100644 --- a/src/app/components/floating-column/manage-account/bookmarks/bookmarks.component.ts +++ b/src/app/components/floating-column/manage-account/bookmarks/bookmarks.component.ts @@ -1,7 +1,7 @@ import { Component, OnInit, Output, EventEmitter, Input, ViewChild, ElementRef } from '@angular/core'; import { StatusWrapper } from '../../../../models/common.model'; -import { OpenThreadEvent } from '../../../../services/tools.service'; +import { OpenThreadEvent, ToolsService } from '../../../../services/tools.service'; import { AccountWrapper } from '../../../../models/account.models'; import { FavoriteResult, BookmarkResult } from '../../../../services/mastodon.service'; import { MastodonWrapperService } from '../../../../services/mastodon-wrapper.service'; @@ -41,8 +41,8 @@ export class BookmarksComponent implements OnInit { @ViewChild('statusstream') public statustream: ElementRef; - constructor( + private readonly toolsService: ToolsService, private readonly notificationService: NotificationService, private readonly mastodonService: MastodonWrapperService) { } @@ -63,7 +63,8 @@ export class BookmarksComponent implements OnInit { .then((result: BookmarkResult) => { this.maxId = result.max_id; for (const s of result.bookmarked) { - const wrapper = new StatusWrapper(s, this.account.info); + let cwPolicy = this.toolsService.checkContentWarning(s); + const wrapper = new StatusWrapper(cwPolicy.status, this.account.info, cwPolicy.applyCw, cwPolicy.hide); this.statuses.push(wrapper); } }) @@ -99,7 +100,8 @@ export class BookmarksComponent implements OnInit { this.maxId = result.max_id; for (const s of statuses) { - const wrapper = new StatusWrapper(s, this.account.info); + let cwPolicy = this.toolsService.checkContentWarning(s); + const wrapper = new StatusWrapper(cwPolicy.status, this.account.info, cwPolicy.applyCw, cwPolicy.hide); this.statuses.push(wrapper); } }) diff --git a/src/app/components/floating-column/manage-account/direct-messages/direct-messages.component.ts b/src/app/components/floating-column/manage-account/direct-messages/direct-messages.component.ts index 31966c44..da6d00f2 100644 --- a/src/app/components/floating-column/manage-account/direct-messages/direct-messages.component.ts +++ b/src/app/components/floating-column/manage-account/direct-messages/direct-messages.component.ts @@ -2,7 +2,7 @@ import { Component, OnInit, Input, Output, EventEmitter, ViewChild, ElementRef } import { faUserFriends } from "@fortawesome/free-solid-svg-icons"; import { AccountWrapper } from '../../../../models/account.models'; -import { OpenThreadEvent } from '../../../../services/tools.service'; +import { OpenThreadEvent, ToolsService } from '../../../../services/tools.service'; import { StatusWrapper } from '../../../../models/common.model'; import { NotificationService } from '../../../../services/notification.service'; import { MastodonWrapperService } from '../../../../services/mastodon-wrapper.service'; @@ -42,6 +42,7 @@ export class DirectMessagesComponent implements OnInit { @ViewChild('statusstream') public statustream: ElementRef; constructor( + private readonly toolsService: ToolsService, private readonly notificationService: NotificationService, private readonly mastodonService: MastodonWrapperService) { } @@ -60,7 +61,8 @@ export class DirectMessagesComponent implements OnInit { this.mastodonService.getConversations(this.account.info) .then((conversations: Conversation[]) => { for (const c of conversations) { - const wrapper = new ConversationWrapper(c, this.account.info, this.account.avatar); + let cwPolicy = this.toolsService.checkContentWarning(c.last_status); + const wrapper = new ConversationWrapper(c, this.account.info, this.account.avatar, cwPolicy.applyCw, cwPolicy.hide); this.conversations.push(wrapper); } }) @@ -95,7 +97,8 @@ export class DirectMessagesComponent implements OnInit { } for (const c of conversations) { - const wrapper = new ConversationWrapper(c, this.account.info, this.account.avatar); + let cwPolicy = this.toolsService.checkContentWarning(c.last_status); + const wrapper = new ConversationWrapper(c, this.account.info, this.account.avatar, cwPolicy.applyCw, cwPolicy.hide); this.conversations.push(wrapper); } }) @@ -121,13 +124,14 @@ export class DirectMessagesComponent implements OnInit { } class ConversationWrapper { - constructor( public conversation: Conversation, public provider: AccountInfo, - public userAvatar: string + public userAvatar: string, + applyCw: boolean, + hideStatus: boolean ) { - this.lastStatus = new StatusWrapper(conversation.last_status, provider); + this.lastStatus = new StatusWrapper(conversation.last_status, provider, applyCw, hideStatus); } lastStatus: StatusWrapper; diff --git a/src/app/components/floating-column/manage-account/favorites/favorites.component.ts b/src/app/components/floating-column/manage-account/favorites/favorites.component.ts index a40efc13..dbd0ccd6 100644 --- a/src/app/components/floating-column/manage-account/favorites/favorites.component.ts +++ b/src/app/components/floating-column/manage-account/favorites/favorites.component.ts @@ -1,7 +1,7 @@ import { Component, OnInit, Output, EventEmitter, Input, ViewChild, ElementRef } from '@angular/core'; import { StatusWrapper } from '../../../../models/common.model'; -import { OpenThreadEvent } from '../../../../services/tools.service'; +import { OpenThreadEvent, ToolsService } from '../../../../services/tools.service'; import { AccountWrapper } from '../../../../models/account.models'; import { FavoriteResult } from '../../../../services/mastodon.service'; import { MastodonWrapperService } from '../../../../services/mastodon-wrapper.service'; @@ -42,6 +42,7 @@ export class FavoritesComponent implements OnInit { @ViewChild('statusstream') public statustream: ElementRef; constructor( + private readonly toolsService: ToolsService, private readonly notificationService: NotificationService, private readonly mastodonService: MastodonWrapperService) { } @@ -62,7 +63,8 @@ export class FavoritesComponent implements OnInit { .then((result: FavoriteResult) => { this.maxId = result.max_id; for (const s of result.favorites) { - const wrapper = new StatusWrapper(s, this.account.info); + let cwPolicy = this.toolsService.checkContentWarning(s); + const wrapper = new StatusWrapper(cwPolicy.status, this.account.info, cwPolicy.applyCw, cwPolicy.hide); this.statuses.push(wrapper); } }) @@ -99,7 +101,8 @@ export class FavoritesComponent implements OnInit { this.maxId = result.max_id; for (const s of statuses) { - const wrapper = new StatusWrapper(s, this.account.info); + let cwPolicy = this.toolsService.checkContentWarning(s); + const wrapper = new StatusWrapper(cwPolicy.status, this.account.info, cwPolicy.applyCw, cwPolicy.hide); this.statuses.push(wrapper); } }) diff --git a/src/app/components/floating-column/manage-account/mentions/mentions.component.ts b/src/app/components/floating-column/manage-account/mentions/mentions.component.ts index fcf2efa1..9b9095e8 100644 --- a/src/app/components/floating-column/manage-account/mentions/mentions.component.ts +++ b/src/app/components/floating-column/manage-account/mentions/mentions.component.ts @@ -7,7 +7,7 @@ import { StatusWrapper } from '../../../../models/common.model'; import { Status, Notification } from '../../../../services/models/mastodon.interfaces'; import { MastodonWrapperService } from '../../../../services/mastodon-wrapper.service'; import { NotificationService } from '../../../../services/notification.service'; -import { OpenThreadEvent } from '../../../../services/tools.service'; +import { OpenThreadEvent, ToolsService } from '../../../../services/tools.service'; @Component({ @@ -45,6 +45,7 @@ export class MentionsComponent implements OnInit, OnDestroy { private lastId: string; constructor( + private readonly toolsService: ToolsService, private readonly notificationService: NotificationService, private readonly userNotificationService: UserNotificationService, private readonly mastodonService: MastodonWrapperService) { @@ -80,7 +81,8 @@ export class MentionsComponent implements OnInit, OnDestroy { let orderedMentions = [...userNotification.mentions.map(x => x.status)].reverse(); for (let m of orderedMentions) { if (!this.statuses.find(x => x.status.id === m.id)) { - const statusWrapper = new StatusWrapper(m, this.account.info); + let cwPolicy = this.toolsService.checkContentWarning(m); + const statusWrapper = new StatusWrapper(cwPolicy.status, this.account.info, cwPolicy.applyCw, cwPolicy.hide); this.statuses.unshift(statusWrapper); } } @@ -113,7 +115,8 @@ export class MentionsComponent implements OnInit, OnDestroy { } for (const s of statuses) { - const wrapper = new StatusWrapper(s, this.account.info); + let cwPolicy = this.toolsService.checkContentWarning(s); + const wrapper = new StatusWrapper(cwPolicy.status, this.account.info, cwPolicy.applyCw, cwPolicy.hide); this.statuses.push(wrapper); } diff --git a/src/app/components/floating-column/manage-account/notifications/notifications.component.ts b/src/app/components/floating-column/manage-account/notifications/notifications.component.ts index da862a74..03545b1f 100644 --- a/src/app/components/floating-column/manage-account/notifications/notifications.component.ts +++ b/src/app/components/floating-column/manage-account/notifications/notifications.component.ts @@ -40,6 +40,7 @@ export class NotificationsComponent implements OnInit, OnDestroy { private lastId: string; constructor( + private readonly toolsService: ToolsService, private readonly notificationService: NotificationService, private readonly userNotificationService: UserNotificationService, private readonly mastodonService: MastodonWrapperService) { } @@ -72,7 +73,8 @@ export class NotificationsComponent implements OnInit, OnDestroy { if (userNotification && userNotification.notifications) { let orderedNotifications = [...userNotification.notifications].reverse(); for (let n of orderedNotifications) { - const notificationWrapper = new NotificationWrapper(n, this.account.info); + let cwPolicy = this.toolsService.checkContentWarning(n.status); + const notificationWrapper = new NotificationWrapper(n, this.account.info, cwPolicy.applyCw, cwPolicy.hide); if (!this.notifications.find(x => x.wrapperId === notificationWrapper.wrapperId)) { this.notifications.unshift(notificationWrapper); } @@ -105,7 +107,8 @@ export class NotificationsComponent implements OnInit, OnDestroy { } for (const s of notifications) { - const wrapper = new NotificationWrapper(s, this.account.info); + let cwPolicy = this.toolsService.checkContentWarning(s.status); + const wrapper = new NotificationWrapper(s, this.account.info, cwPolicy.applyCw, cwPolicy.hide); this.notifications.push(wrapper); } @@ -133,14 +136,14 @@ export class NotificationsComponent implements OnInit, OnDestroy { } export class NotificationWrapper { - constructor(notification: Notification, provider: AccountInfo) { + constructor(notification: Notification, provider: AccountInfo, applyCw: boolean, hideStatus: boolean) { this.type = notification.type; switch(this.type){ case 'mention': case 'reblog': case 'favourite': - case 'poll': - this.status= new StatusWrapper(notification.status, provider); + case 'poll': + this.status= new StatusWrapper(notification.status, provider, applyCw, hideStatus); break; } this.account = notification.account; diff --git a/src/app/components/floating-column/search/search.component.ts b/src/app/components/floating-column/search/search.component.ts index d31271a6..530e71a7 100644 --- a/src/app/components/floating-column/search/search.component.ts +++ b/src/app/components/floating-column/search/search.component.ts @@ -92,7 +92,8 @@ export class SearchComponent implements OnInit { this.hashtags = results.hashtags; for (let status of results.statuses) { - const statusWrapper = new StatusWrapper(status, this.lastAccountUsed); + let cwPolicy = this.toolsService.checkContentWarning(status); + const statusWrapper = new StatusWrapper(cwPolicy.status, this.lastAccountUsed, cwPolicy.applyCw, cwPolicy.hide); this.statuses.push(statusWrapper); } } 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 05160c57..b23c9957 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 @@ -149,9 +149,7 @@ export class ActionBarComponent implements OnInit, OnDestroy { this.isLocked = false; } - if (status.sensitive || status.spoiler_text) { - this.isContentWarningActive = true; - } + this.isContentWarningActive = this.statusWrapper.applyCw; this.checkIfBookmarksAreAvailable(this.selectedAccounts[0]); this.checkIfFavorited(); diff --git a/src/app/components/stream/status/action-bar/status-user-context-menu/status-user-context-menu.component.ts b/src/app/components/stream/status/action-bar/status-user-context-menu/status-user-context-menu.component.ts index b25d6406..6f822947 100644 --- a/src/app/components/stream/status/action-bar/status-user-context-menu/status-user-context-menu.component.ts +++ b/src/app/components/stream/status/action-bar/status-user-context-menu/status-user-context-menu.component.ts @@ -244,7 +244,8 @@ export class StatusUserContextMenuComponent implements OnInit, OnDestroy { this.navigationService.redraft(this.statusWrapper) } - const deletedStatus = new StatusWrapper(this.displayedStatus, selectedAccount); + let cwPolicy = this.toolsService.checkContentWarning(this.displayedStatus); + const deletedStatus = new StatusWrapper(cwPolicy.status, selectedAccount, cwPolicy.applyCw, cwPolicy.hide); this.notificationService.deleteStatus(deletedStatus); }) .catch(err => { diff --git a/src/app/components/stream/status/poll/poll.component.ts b/src/app/components/stream/status/poll/poll.component.ts index 6894b7b5..7cd8ac94 100644 --- a/src/app/components/stream/status/poll/poll.component.ts +++ b/src/app/components/stream/status/poll/poll.component.ts @@ -89,7 +89,8 @@ export class PollComponent implements OnInit { if (accountChanged && !this.pollPerAccountId[newSelectedAccount.id] && (this.statusWrapper.status.visibility === 'public' || this.statusWrapper.status.visibility === 'unlisted')) { this.setStatsAtZero(); - this.pollPerAccountId[newSelectedAccount.id] = this.toolsService.getStatusUsableByAccount(newSelectedAccount, new StatusWrapper(this.statusWrapper.status, this.statusWrapper.provider)) + let statusWrapper = new StatusWrapper(this.statusWrapper.status, this.statusWrapper.provider, this.statusWrapper.applyCw, this.statusWrapper.hide); + this.pollPerAccountId[newSelectedAccount.id] = this.toolsService.getStatusUsableByAccount(newSelectedAccount, statusWrapper) .then((status: Status) => { if(!status || !(status.poll)) return null; return this.mastodonService.getPoll(newSelectedAccount, status.poll.id); diff --git a/src/app/components/stream/status/status.component.ts b/src/app/components/stream/status/status.component.ts index 2c4b928b..e825f3cb 100644 --- a/src/app/components/stream/status/status.component.ts +++ b/src/app/components/stream/status/status.component.ts @@ -70,10 +70,11 @@ export class StatusComponent implements OnInit { } this.isDirectMessage = this.displayedStatus.visibility === 'direct'; - this.displayedStatusWrapper = new StatusWrapper(this.displayedStatus, value.provider); + let cwPolicy = this.toolsService.checkContentWarning(this.displayedStatus); + this.displayedStatusWrapper = new StatusWrapper(cwPolicy.status, value.provider, cwPolicy.applyCw, cwPolicy.hide); this.checkLabels(this.displayedStatus); - this.checkContentWarning(this.displayedStatus); + this.setContentWarning(this.displayedStatusWrapper); if (!this.displayedStatus.account.display_name) { this.displayedStatus.account.display_name = this.displayedStatus.account.username; @@ -98,53 +99,53 @@ export class StatusComponent implements OnInit { ngOnInit() { } - private checkContentWarning(status: Status) { - let cwPolicy = this.toolsService.getSettings().contentWarningPolicy; + // private checkContentWarning(status: Status) { + // let cwPolicy = this.toolsService.getSettings().contentWarningPolicy; - let splittedContent = []; - if ((cwPolicy.policy === ContentWarningPolicyEnum.HideAll && cwPolicy.addCwOnContent.length > 0) - || (cwPolicy.policy === ContentWarningPolicyEnum.AddOnAllContent && cwPolicy.removeCwOnContent.length > 0) - || (cwPolicy.hideCompletlyContent && cwPolicy.hideCompletlyContent.length > 0)) { - let parser = new DOMParser(); - let dom = parser.parseFromString((status.content + ' ' + status.spoiler_text).replace("
", " ").replace("
", " ").replace(/\n/g, ' '), 'text/html') - let contentToParse = dom.body.textContent; - splittedContent = contentToParse.toLowerCase().split(' '); - } + // let splittedContent = []; + // if ((cwPolicy.policy === ContentWarningPolicyEnum.HideAll && cwPolicy.addCwOnContent.length > 0) + // || (cwPolicy.policy === ContentWarningPolicyEnum.AddOnAllContent && cwPolicy.removeCwOnContent.length > 0) + // || (cwPolicy.hideCompletlyContent && cwPolicy.hideCompletlyContent.length > 0)) { + // let parser = new DOMParser(); + // let dom = parser.parseFromString((status.content + ' ' + status.spoiler_text).replace("
", " ").replace("
", " ").replace(/\n/g, ' '), 'text/html') + // let contentToParse = dom.body.textContent; + // splittedContent = contentToParse.toLowerCase().split(' '); + // } - if (cwPolicy.policy === ContentWarningPolicyEnum.None && (status.sensitive || status.spoiler_text)) { - this.setContentWarning(status); - } else if (cwPolicy.policy === ContentWarningPolicyEnum.HideAll) { - let detected = cwPolicy.addCwOnContent.filter(x => splittedContent.find(y => y == x || y == `#${x}`)); - if (!detected || detected.length === 0) { - this.status.sensitive = false; - } else { - if (!status.spoiler_text) { - status.spoiler_text = detected.join(' '); - } - this.setContentWarning(status); - } - } else if (cwPolicy.policy === ContentWarningPolicyEnum.AddOnAllContent) { - let detected = cwPolicy.removeCwOnContent.filter(x => splittedContent.find(y => y == x || y == `#${x}`)); + // if (cwPolicy.policy === ContentWarningPolicyEnum.None && (status.sensitive || status.spoiler_text)) { + // this.setContentWarning(status); + // } else if (cwPolicy.policy === ContentWarningPolicyEnum.HideAll) { + // let detected = cwPolicy.addCwOnContent.filter(x => splittedContent.find(y => y == x || y == `#${x}`)); + // if (!detected || detected.length === 0) { + // this.status.sensitive = false; + // } else { + // if (!status.spoiler_text) { + // status.spoiler_text = detected.join(' '); + // } + // this.setContentWarning(status); + // } + // } else if (cwPolicy.policy === ContentWarningPolicyEnum.AddOnAllContent) { + // let detected = cwPolicy.removeCwOnContent.filter(x => splittedContent.find(y => y == x || y == `#${x}`)); - if (detected && detected.length > 0) { - this.status.sensitive = false; - } else { - this.setContentWarning(status); - } - } + // if (detected && detected.length > 0) { + // this.status.sensitive = false; + // } else { + // this.setContentWarning(status); + // } + // } - if (cwPolicy.hideCompletlyContent && cwPolicy.hideCompletlyContent.length > 0) { - let detected = cwPolicy.hideCompletlyContent.filter(x => splittedContent.find(y => y == x || y == `#${x}`)); - if (detected && detected.length > 0) { - this.hideStatus = true; - } - } - } + // if (cwPolicy.hideCompletlyContent && cwPolicy.hideCompletlyContent.length > 0) { + // let detected = cwPolicy.hideCompletlyContent.filter(x => splittedContent.find(y => y == x || y == `#${x}`)); + // if (detected && detected.length > 0) { + // this.hideStatus = true; + // } + // } + // } - private setContentWarning(status: Status) { - this.status.sensitive = true; - this.isContentWarned = true; - this.contentWarningText = this.emojiConverter.applyEmojis(this.displayedStatus.emojis, status.spoiler_text, EmojiTypeEnum.medium); + private setContentWarning(status: StatusWrapper) { + this.hideStatus = status.hide; + this.isContentWarned = status.applyCw; + this.contentWarningText = this.emojiConverter.applyEmojis(this.displayedStatus.emojis, status.status.spoiler_text, EmojiTypeEnum.medium); } removeContentWarning(): boolean { diff --git a/src/app/components/stream/stream-notifications/stream-notifications.component.ts b/src/app/components/stream/stream-notifications/stream-notifications.component.ts index e9c101ff..b53561e1 100644 --- a/src/app/components/stream/stream-notifications/stream-notifications.component.ts +++ b/src/app/components/stream/stream-notifications/stream-notifications.component.ts @@ -103,7 +103,12 @@ export class StreamNotificationsComponent implements OnInit, OnDestroy { if (!userNotification) return; - let mentions = userNotification.mentions.map(x => new NotificationWrapper(x, this.account)).reverse(); + let mentions = userNotification.mentions + .map(x => { + let cwPolicy = this.toolsService.checkContentWarning(x.status); + return new NotificationWrapper(x, this.account, cwPolicy.applyCw, cwPolicy.hide); + }) + .reverse(); this.lastMentionId = userNotification.lastMentionsId; if (!mentions) return; @@ -126,7 +131,10 @@ export class StreamNotificationsComponent implements OnInit, OnDestroy { .then((notifications: Notification[]) => { this.isNotificationsLoading = false; - this.notifications = notifications.map(x => new NotificationWrapper(x, this.account)); + this.notifications = notifications.map(x => { + let cwPolicy = this.toolsService.checkContentWarning(x.status); + return new NotificationWrapper(x, this.account, cwPolicy.applyCw, cwPolicy.hide); + }); this.lastNotificationId = this.notifications[this.notifications.length - 1].notification.id; }) .catch(err => { @@ -138,7 +146,8 @@ export class StreamNotificationsComponent implements OnInit, OnDestroy { let streaming = this.streamingService.getStreaming(this.account, streamElement); this.notificationSubscription = streaming.statusUpdateSubjet.subscribe((notification: StatusUpdate) => { if (notification && notification.type === EventEnum.notification) { - const n = new NotificationWrapper(notification.notification, this.account); + let cwPolicy = this.toolsService.checkContentWarning(notification.status); + const n = new NotificationWrapper(notification.notification, this.account, cwPolicy.applyCw, cwPolicy.hide); this.notifications.unshift(n); } }); @@ -200,7 +209,8 @@ export class StreamNotificationsComponent implements OnInit, OnDestroy { } for (const s of result) { - const wrapper = new NotificationWrapper(s, this.account); + let cwPolicy = this.toolsService.checkContentWarning(s.status); + const wrapper = new NotificationWrapper(s, this.account, cwPolicy.applyCw, cwPolicy.hide); this.notifications.push(wrapper); } @@ -228,7 +238,8 @@ export class StreamNotificationsComponent implements OnInit, OnDestroy { } for (const s of result) { - const wrapper = new NotificationWrapper(s, this.account); + let cwPolicy = this.toolsService.checkContentWarning(s.status); + const wrapper = new NotificationWrapper(s, this.account, cwPolicy.applyCw, cwPolicy.hide); this.mentions.push(wrapper); } diff --git a/src/app/components/stream/stream-statuses/stream-statuses.component.ts b/src/app/components/stream/stream-statuses/stream-statuses.component.ts index 5c63e718..64a3ecfd 100644 --- a/src/app/components/stream/stream-statuses/stream-statuses.component.ts +++ b/src/app/components/stream/stream-statuses/stream-statuses.component.ts @@ -152,7 +152,8 @@ export class StreamStatusesComponent implements OnInit, OnDestroy { return; } - const wrapper = new StatusWrapper(update.status, this.account); + let cwPolicy = this.toolsService.checkContentWarning(update.status); + const wrapper = new StatusWrapper(cwPolicy.status, this.account, cwPolicy.applyCw, cwPolicy.hide); this.statuses.unshift(wrapper); } else { this.bufferStream.push(update.status); @@ -235,7 +236,8 @@ export class StreamStatusesComponent implements OnInit, OnDestroy { continue; } - const wrapper = new StatusWrapper(status, this.account); + let cwPolicy = this.toolsService.checkContentWarning(status); + const wrapper = new StatusWrapper(cwPolicy.status, this.account, cwPolicy.applyCw, cwPolicy.hide); this.statuses.unshift(wrapper); } @@ -256,7 +258,8 @@ export class StreamStatusesComponent implements OnInit, OnDestroy { continue; } - const wrapper = new StatusWrapper(s, this.account); + let cwPolicy = this.toolsService.checkContentWarning(s); + const wrapper = new StatusWrapper(cwPolicy.status, this.account, cwPolicy.applyCw, cwPolicy.hide); this.statuses.push(wrapper); } }) @@ -292,7 +295,8 @@ export class StreamStatusesComponent implements OnInit, OnDestroy { continue; } - const wrapper = new StatusWrapper(s, this.account); + let cwPolicy = this.toolsService.checkContentWarning(s); + const wrapper = new StatusWrapper(cwPolicy.status, this.account, cwPolicy.applyCw, cwPolicy.hide); this.statuses.push(wrapper); } }) diff --git a/src/app/components/stream/thread/thread.component.ts b/src/app/components/stream/thread/thread.component.ts index 0bae1c75..77d2972d 100644 --- a/src/app/components/stream/thread/thread.component.ts +++ b/src/app/components/stream/thread/thread.component.ts @@ -167,14 +167,15 @@ export class ThreadComponent implements OnInit, OnDestroy { for (let i = 0; i < contextStatuses.length; i++) { let s = contextStatuses[i]; - const wrapper = new StatusWrapper(s, currentAccount); + let cwPolicy = this.toolsService.checkContentWarning(s); + const wrapper = new StatusWrapper(cwPolicy.status, currentAccount, cwPolicy.applyCw, cwPolicy.hide); if(i == position) wrapper.isSelected = true; this.statuses.push(wrapper); } - this.hasContentWarnings = this.statuses.filter(x => x.status.sensitive || x.status.spoiler_text).length > 1; + this.hasContentWarnings = this.statuses.filter(x => x.applyCw).length > 1; return position; }); diff --git a/src/app/components/stream/user-profile/user-profile.component.ts b/src/app/components/stream/user-profile/user-profile.component.ts index a969ae98..0db5ff92 100644 --- a/src/app/components/stream/user-profile/user-profile.component.ts +++ b/src/app/components/stream/user-profile/user-profile.component.ts @@ -203,7 +203,8 @@ export class UserProfileComponent implements OnInit { .then((statuses: Status[]) => { for (const status of statuses) { status.pinned = true; - const wrapper = new StatusWrapper(status, userAccount); + let cwPolicy = this.toolsService.checkContentWarning(status); + const wrapper = new StatusWrapper(cwPolicy.status, userAccount, cwPolicy.applyCw, cwPolicy.hide); this.pinnedStatuses.push(wrapper); } }) @@ -355,7 +356,8 @@ export class UserProfileComponent implements OnInit { } for (const status of statuses) { - const wrapper = new StatusWrapper(status, userAccount); + let cwPolicy = this.toolsService.checkContentWarning(status); + const wrapper = new StatusWrapper(cwPolicy.status, userAccount, cwPolicy.applyCw, cwPolicy.hide); this.statuses.push(wrapper); } diff --git a/src/app/models/common.model.ts b/src/app/models/common.model.ts index 5ae2580f..29462572 100644 --- a/src/app/models/common.model.ts +++ b/src/app/models/common.model.ts @@ -15,7 +15,9 @@ export class OpenMediaEvent { export class StatusWrapper { constructor( public status: Status, - public provider: AccountInfo + public provider: AccountInfo, + public applyCw: boolean, + public hide: boolean ) { } public isSelected: boolean; diff --git a/src/app/services/tools.service.ts b/src/app/services/tools.service.ts index 2938bddf..4a3cbf19 100644 --- a/src/app/services/tools.service.ts +++ b/src/app/services/tools.service.ts @@ -5,13 +5,13 @@ import { AccountInfo } from '../states/accounts.state'; import { MastodonWrapperService } from './mastodon-wrapper.service'; import { Account, Results, Status, Emoji } from "./models/mastodon.interfaces"; import { StatusWrapper } from '../models/common.model'; -import { AccountSettings, SaveAccountSettings, GlobalSettings, SaveSettings, ContentWarningPolicy, SaveContentWarningPolicy } from '../states/settings.state'; +import { AccountSettings, SaveAccountSettings, GlobalSettings, SaveSettings, ContentWarningPolicy, SaveContentWarningPolicy, ContentWarningPolicyEnum } from '../states/settings.state'; import { AppInfo, RegisteredAppsStateModel } from '../states/registered-apps.state'; @Injectable({ providedIn: 'root' }) -export class ToolsService { +export class ToolsService { private accountAvatar: { [id: string]: string; } = {}; private instanceInfos: { [id: string]: InstanceInfo } = {}; @@ -19,6 +19,58 @@ export class ToolsService { private readonly mastodonService: MastodonWrapperService, private readonly store: Store) { } + checkContentWarning(status: Status): StatusWithCwPolicyResult { + if(!status) { + return new StatusWithCwPolicyResult(status, false, false); + } + + let applyCw = false; + let hideStatus = false; + + let cwPolicy = this.getSettings().contentWarningPolicy; + + let splittedContent = []; + if ((cwPolicy.policy === ContentWarningPolicyEnum.HideAll && cwPolicy.addCwOnContent.length > 0) + || (cwPolicy.policy === ContentWarningPolicyEnum.AddOnAllContent && cwPolicy.removeCwOnContent.length > 0) + || (cwPolicy.hideCompletlyContent && cwPolicy.hideCompletlyContent.length > 0)) { + let parser = new DOMParser(); + let dom = parser.parseFromString((status.content + ' ' + status.spoiler_text).replace("
", " ").replace("
", " ").replace(/\n/g, ' '), 'text/html') + let contentToParse = dom.body.textContent; + splittedContent = contentToParse.toLowerCase().split(' '); + } + + if (cwPolicy.policy === ContentWarningPolicyEnum.None && (status.sensitive || status.spoiler_text)) { + applyCw = true; + } else if (cwPolicy.policy === ContentWarningPolicyEnum.HideAll) { + let detected = cwPolicy.addCwOnContent.filter(x => splittedContent.find(y => y == x || y == `#${x}`)); + if (!detected || detected.length === 0) { + applyCw = false; + } else { + if (!status.spoiler_text) { + status.spoiler_text = detected.join(' '); + } + applyCw = true; + } + } else if (cwPolicy.policy === ContentWarningPolicyEnum.AddOnAllContent) { + let detected = cwPolicy.removeCwOnContent.filter(x => splittedContent.find(y => y == x || y == `#${x}`)); + + if (detected && detected.length > 0) { + applyCw = false; + } else { + applyCw = true; + } + } + + if (cwPolicy.hideCompletlyContent && cwPolicy.hideCompletlyContent.length > 0) { + let detected = cwPolicy.hideCompletlyContent.filter(x => splittedContent.find(y => y == x || y == `#${x}`)); + if (detected && detected.length > 0) { + hideStatus = true; + } + } + + return new StatusWithCwPolicyResult(status, applyCw, hideStatus); + } + getInstanceInfo(acc: AccountInfo): Promise { if (this.instanceInfos[acc.instance]) { return Promise.resolve(this.instanceInfos[acc.instance]); @@ -97,7 +149,7 @@ export class ToolsService { getSettings(): GlobalSettings { let settings = this.store.snapshot().globalsettings.settings; - if(!settings.contentWarningPolicy){ + if (!settings.contentWarningPolicy) { var newCwPolicy = new ContentWarningPolicy(); this.saveContentWarningPolicy(newCwPolicy); return this.store.snapshot().globalsettings.settings; @@ -112,7 +164,7 @@ export class ToolsService { ]); } - saveContentWarningPolicy(cwSettings: ContentWarningPolicy){ + saveContentWarningPolicy(cwSettings: ContentWarningPolicy) { this.store.dispatch([ new SaveContentWarningPolicy(cwSettings) ]); @@ -220,4 +272,9 @@ export enum InstanceType { GlitchSoc = 3, Florence = 4, Pixelfed = 5 +} + +export class StatusWithCwPolicyResult { + constructor(public status: Status, public applyCw: boolean, public hide: boolean) { + } } \ No newline at end of file From e76d1d84bc4e34b7c3ff7477218c0ea7bc45ce22 Mon Sep 17 00:00:00 2001 From: Nicolas Constant Date: Wed, 1 Apr 2020 20:16:12 -0400 Subject: [PATCH 2/2] road to 0.23.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 940ea329..13b6b975 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "sengi", - "version": "0.23.0", + "version": "0.23.1", "license": "AGPL-3.0-or-later", "main": "main-electron.js", "description": "A multi-account desktop client for Mastodon and Pleroma",