From 15bed586dcd1d10a6a05c664cf5bab72cdbf2a46 Mon Sep 17 00:00:00 2001 From: Shpuld Shpuldson Date: Sun, 15 Nov 2020 13:57:02 +0200 Subject: [PATCH 0001/1033] report notification wip --- src/components/interactions/interactions.js | 2 ++ src/components/interactions/interactions.vue | 9 +++++++++ .../entity_normalizer/entity_normalizer.service.js | 7 +++++++ src/services/notification_utils/notification_utils.js | 6 +++++- 4 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/components/interactions/interactions.js b/src/components/interactions/interactions.js index 7fe5e76d97..54275a7b4a 100644 --- a/src/components/interactions/interactions.js +++ b/src/components/interactions/interactions.js @@ -4,6 +4,8 @@ const tabModeDict = { mentions: ['mention'], 'likes+repeats': ['repeat', 'like'], follows: ['follow'], + reactions: ['pleroma:emoji_reaction'], + reports: ['pleroma:report'], moves: ['move'] } diff --git a/src/components/interactions/interactions.vue b/src/components/interactions/interactions.vue index 57d5d87c3d..b7291c02ca 100644 --- a/src/components/interactions/interactions.vue +++ b/src/components/interactions/interactions.vue @@ -21,6 +21,15 @@ key="follows" :label="$t('interactions.follows')" /> + + { : parseUser(data.target) output.from_profile = parseUser(data.account) output.emoji = data.emoji + if (data.report) { + output.report = data.report + output.report.content = data.report.content + output.report.acct = parseUser(data.report.acct) + output.report.actor = parseUser(data.report.actor) + output.report.statuses = data.report.statuses.map(parseStatus) + } } else { const parsedNotice = parseStatus(data.notice) output.type = data.ntype diff --git a/src/services/notification_utils/notification_utils.js b/src/services/notification_utils/notification_utils.js index d912d19f2f..dff97aa295 100644 --- a/src/services/notification_utils/notification_utils.js +++ b/src/services/notification_utils/notification_utils.js @@ -14,7 +14,8 @@ export const visibleTypes = store => { rootState.config.notificationVisibility.follows && 'follow', rootState.config.notificationVisibility.followRequest && 'follow_request', rootState.config.notificationVisibility.moves && 'move', - rootState.config.notificationVisibility.emojiReactions && 'pleroma:emoji_reaction' + rootState.config.notificationVisibility.emojiReactions && 'pleroma:emoji_reaction', + rootState.config.notificationVisibility.reports && 'pleroma:report' ].filter(_ => _)) } @@ -91,6 +92,9 @@ export const prepareNotificationObject = (notification, i18n) => { case 'follow_request': i18nString = 'follow_request' break + case 'pleroma:report': + i18nString = 'reported' + break } if (notification.type === 'pleroma:emoji_reaction') { From 5e96260a4f855e2d93915c1b428a7209a882c8cb Mon Sep 17 00:00:00 2001 From: Shpuld Shpuldson Date: Fri, 4 Dec 2020 12:48:15 +0200 Subject: [PATCH 0002/1033] add test data for dev --- src/services/api/api.service.js | 282 ++++++++++++++++++ .../entity_normalizer.service.js | 2 +- .../notifications_fetcher.service.js | 1 + 3 files changed, 284 insertions(+), 1 deletion(-) diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js index 8da933c41c..6b825c3746 100644 --- a/src/services/api/api.service.js +++ b/src/services/api/api.service.js @@ -484,6 +484,285 @@ const deleteUser = ({ credentials, user }) => { }) } +/* eslint-disable */ +const report = { + "account": { + "acct": "reporting_account", + "avatar": "https://develop.ilja.space/images/avi.png", + "avatar_static": "https://develop.ilja.space/images/avi.png", + "bot": false, + "created_at": "2020-09-03T14:17:00.000Z", + "display_name": "Reporting Account", + "emojis": [], + "fields": [], + "followers_count": 0, + "following_count": 0, + "header": "https://develop.ilja.space/images/banner.png", + "header_static": "https://develop.ilja.space/images/banner.png", + "id": "9ymg9LnKk74wuk9lXk", + "locked": false, + "note": "I'm an account made for an example report notification. I'm the one that will do the reporting.", + "pleroma": { + "accepts_chat_messages": true, + "ap_id": "https://develop.ilja.space/users/reporting_account", + "background_image": null, + "confirmation_pending": false, + "deactivated": false, + "favicon": null, + "hide_favorites": true, + "hide_followers": false, + "hide_followers_count": false, + "hide_follows": false, + "hide_follows_count": false, + "is_admin": false, + "is_moderator": false, + "relationship": {}, + "skip_thread_containment": false, + "tags": [] + }, + "source": { + "fields": [], + "note": "", + "pleroma": { + "actor_type": "Person", + "discoverable": false + }, + "sensitive": false + }, + "statuses_count": 0, + "url": "https://develop.ilja.space/users/reporting_account", + "username": "reporting_account" + }, + "created_at": "2020-09-03T14:22:59.000Z", + "id": "5", + "pleroma": { + "is_muted": false, + "is_seen": false + }, + "report": { + "account": { + "local": true, + "locked": false, + "acct": "reported_account", + "followers_count": 0, + "fields": [], + "avatar": "https://develop.ilja.space/images/avi.png", + "actor_type": "Person", + "url": "https://develop.ilja.space/users/reported_account", + "deactivated": false, + "id": "9ymgGklmHjZ2OpxVLM", + "bot": false, + "roles": { + "admin": false, + "moderator": false + }, + "statuses_count": 1, + "nickname": "reported_account", + "display_name": "Reported Account", + "source": { + "fields": [], + "note": "", + "pleroma": { + "actor_type": "Person", + "discoverable": false + }, + "sensitive": false + }, + "pleroma": { + "accepts_chat_messages": true, + "ap_id": "https://develop.ilja.space/users/reported_account", + "background_image": null, + "confirmation_pending": false, + "favicon": null, + "hide_favorites": true, + "hide_followers": false, + "hide_followers_count": false, + "hide_follows": false, + "hide_follows_count": false, + "is_admin": false, + "is_moderator": false, + "relationship": {}, + "skip_thread_containment": false, + "tags": [] + }, + "emojis": [], + "created_at": "2020-09-03T14:18:21.000Z", + "username": "reported_account", + "note": "I'm an account made for an example report notification. I'm the one that will be reported.", + "approval_pending": false, + "avatar_static": "https://develop.ilja.space/images/avi.png", + "header": "https://develop.ilja.space/images/banner.png", + "registration_reason": null, + "confirmation_pending": false, + "header_static": "https://develop.ilja.space/images/banner.png", + "following_count": 0, + "tags": [] + }, + "actor": { + "local": true, + "locked": false, + "acct": "reporting_account", + "followers_count": 0, + "fields": [], + "avatar": "https://develop.ilja.space/images/avi.png", + "actor_type": "Person", + "url": "https://develop.ilja.space/users/reporting_account", + "deactivated": false, + "id": "9ymg9LnKk74wuk9lXk", + "bot": false, + "roles": { + "admin": false, + "moderator": false + }, + "statuses_count": 0, + "nickname": "reporting_account", + "display_name": "Reporting Account", + "source": { + "fields": [], + "note": "", + "pleroma": { + "actor_type": "Person", + "discoverable": false + }, + "sensitive": false + }, + "pleroma": { + "accepts_chat_messages": true, + "ap_id": "https://develop.ilja.space/users/reporting_account", + "background_image": null, + "confirmation_pending": false, + "favicon": null, + "hide_favorites": true, + "hide_followers": false, + "hide_followers_count": false, + "hide_follows": false, + "hide_follows_count": false, + "is_admin": false, + "is_moderator": false, + "relationship": {}, + "skip_thread_containment": false, + "tags": [] + }, + "emojis": [], + "created_at": "2020-09-03T14:17:00.000Z", + "username": "reporting_account", + "note": "I'm an account made for an example report notification. I'm the one that will do the reporting.", + "approval_pending": false, + "avatar_static": "https://develop.ilja.space/images/avi.png", + "header": "https://develop.ilja.space/images/banner.png", + "registration_reason": null, + "confirmation_pending": false, + "header_static": "https://develop.ilja.space/images/banner.png", + "following_count": 0, + "tags": [] + }, + "content": "This is the report created by "reporting_account". It reports "reported_account".", + "created_at": "2020-09-03T14:22:59.000Z", + "id": "9ymggNcUyfIW8Cq1zM", + "notes": [], + "state": "open", + "statuses": [ + { + "account": { + "acct": "reported_account", + "avatar": "https://develop.ilja.space/images/avi.png", + "avatar_static": "https://develop.ilja.space/images/avi.png", + "bot": false, + "created_at": "2020-09-03T14:18:21.000Z", + "display_name": "Reported Account", + "emojis": [], + "fields": [], + "followers_count": 0, + "following_count": 0, + "header": "https://develop.ilja.space/images/banner.png", + "header_static": "https://develop.ilja.space/images/banner.png", + "id": "9ymgGklmHjZ2OpxVLM", + "locked": false, + "note": "I'm an account made for an example report notification. I'm the one that will be reported.", + "pleroma": { + "accepts_chat_messages": true, + "ap_id": "https://develop.ilja.space/users/reported_account", + "background_image": null, + "confirmation_pending": false, + "favicon": null, + "hide_favorites": true, + "hide_followers": false, + "hide_followers_count": false, + "hide_follows": false, + "hide_follows_count": false, + "is_admin": false, + "is_moderator": false, + "relationship": {}, + "skip_thread_containment": false, + "tags": [] + }, + "source": { + "fields": [], + "note": "", + "pleroma": { + "actor_type": "Person", + "discoverable": false + }, + "sensitive": false + }, + "statuses_count": 1, + "url": "https://develop.ilja.space/users/reported_account", + "username": "reported_account" + }, + "application": { + "name": "Web", + "website": null + }, + "bookmarked": false, + "card": null, + "content": "A post I made that will be included in the report", + "created_at": "2020-09-03T14:18:51.000Z", + "emojis": [], + "favourited": false, + "favourites_count": 0, + "id": "9ymgJaQxAbTzDDZMJs", + "in_reply_to_account_id": null, + "in_reply_to_id": null, + "language": null, + "media_attachments": [], + "mentions": [], + "muted": false, + "pinned": false, + "pleroma": { + "content": { + "text/plain": "A post I made that will be included in the report" + }, + "conversation_id": 7, + "direct_conversation_id": null, + "emoji_reactions": [], + "expires_at": null, + "in_reply_to_account_acct": null, + "local": true, + "parent_visible": false, + "spoiler_text": { + "text/plain": "" + }, + "thread_muted": false + }, + "poll": null, + "reblog": null, + "reblogged": false, + "reblogs_count": 0, + "replies_count": 0, + "sensitive": false, + "spoiler_text": "", + "tags": [], + "text": null, + "uri": "https://develop.ilja.space/objects/8fe7611a-07e7-403a-ae08-f74580b6cc53", + "url": "https://develop.ilja.space/notice/9ymgJaQxAbTzDDZMJs", + "visibility": "public" + } + ] + }, + "type": "pleroma:report" +} +/* eslint-enable */ + const fetchTimeline = ({ timeline, credentials, @@ -561,6 +840,9 @@ const fetchTimeline = ({ .then((data) => data.json()) .then((data) => { if (!data.errors) { + if (isNotifications) { + return { data: [parseNotification(report)], pagination } + } return { data: data.map(isNotifications ? parseNotification : parseStatus), pagination } } else { data.status = status diff --git a/src/services/entity_normalizer/entity_normalizer.service.js b/src/services/entity_normalizer/entity_normalizer.service.js index 0fd01176d6..c71bc15af8 100644 --- a/src/services/entity_normalizer/entity_normalizer.service.js +++ b/src/services/entity_normalizer/entity_normalizer.service.js @@ -376,7 +376,7 @@ export const parseNotification = (data) => { if (data.report) { output.report = data.report output.report.content = data.report.content - output.report.acct = parseUser(data.report.acct) + output.report.acct = parseUser(data.report.account) output.report.actor = parseUser(data.report.actor) output.report.statuses = data.report.statuses.map(parseStatus) } diff --git a/src/services/notifications_fetcher/notifications_fetcher.service.js b/src/services/notifications_fetcher/notifications_fetcher.service.js index beeb167c44..91861b21bd 100644 --- a/src/services/notifications_fetcher/notifications_fetcher.service.js +++ b/src/services/notifications_fetcher/notifications_fetcher.service.js @@ -61,6 +61,7 @@ const fetchNotifications = ({ store, args, older }) => { messageArgs: [error.message], timeout: 5000 }) + console.error(error) }) } From a4e3cccf1cba238e5bfd96ea8c60f0d12bc6b7aa Mon Sep 17 00:00:00 2001 From: Shpuld Shpuldson Date: Wed, 6 Jan 2021 18:31:34 +0200 Subject: [PATCH 0003/1033] somewhat workign version still with fixture --- src/components/notification/notification.js | 3 + src/components/notification/notification.scss | 28 +++ src/components/notification/notification.vue | 34 +++ src/components/notifications/notifications.js | 1 + .../notifications/notifications.scss | 6 +- src/i18n/en.json | 3 +- src/modules/config.js | 3 +- src/services/api/api.service.js | 197 +++++++++--------- .../entity_normalizer.service.js | 1 - 9 files changed, 177 insertions(+), 99 deletions(-) diff --git a/src/components/notification/notification.js b/src/components/notification/notification.js index 4aa9affd8c..a920bb3e77 100644 --- a/src/components/notification/notification.js +++ b/src/components/notification/notification.js @@ -76,6 +76,9 @@ const Notification = { this.$store.dispatch('dismissNotificationLocal', { id: this.notification.id }) this.$store.dispatch('removeFollowRequest', this.user) }) + }, + testlog (a) { + console.log(a) } }, computed: { diff --git a/src/components/notification/notification.scss b/src/components/notification/notification.scss index f59055604a..b103db861d 100644 --- a/src/components/notification/notification.scss +++ b/src/components/notification/notification.scss @@ -56,6 +56,34 @@ margin: 0 0.1em; } + .report-content { + margin: 0.5em 0; + } + + .reported-status { + border: 1px solid $fallback--faint; + border-color: var(--faint, $fallback--faint); + border-radius: $fallback--inputRadius; + border-radius: var(--inputRadius, $fallback--inputRadius); + color: $fallback--text; + color: var(--text, $fallback--text); + display: block; + padding: 0.5em; + margin: 0.5em 0; + + .status-content { + pointer-events: none; + } + + .reported-status-name { + font-weight: bold; + } + + .reported-status-timeago { + float: right; + } + } + &.-type--repeat .type-icon { color: $fallback--cGreen; color: var(--cGreen, $fallback--cGreen); diff --git a/src/components/notification/notification.vue b/src/components/notification/notification.vue index f56aa977da..39e3bda0bd 100644 --- a/src/components/notification/notification.vue +++ b/src/components/notification/notification.vue @@ -106,6 +106,9 @@ + + {{ $t('notifications.submitted_report') }} +
+
+ Reported user: + + @{{ notification.report.acct.screen_name }} + + +
+
+ Reported statuses: + + + {{ status.user.name }} + + + +
+
diff --git a/src/components/settings_modal/tabs/profile_tab.js b/src/components/settings_modal/tabs/profile_tab.js index 64079fcdd6..bee8a7bb4c 100644 --- a/src/components/settings_modal/tabs/profile_tab.js +++ b/src/components/settings_modal/tabs/profile_tab.js @@ -8,6 +8,9 @@ import EmojiInput from 'src/components/emoji_input/emoji_input.vue' import suggestor from 'src/components/emoji_input/suggestor.js' import Autosuggest from 'src/components/autosuggest/autosuggest.vue' import Checkbox from 'src/components/checkbox/checkbox.vue' +import BooleanSetting from '../helpers/boolean_setting.vue' +import SharedComputedObject from '../helpers/shared_computed_object.js' + import { library } from '@fortawesome/fontawesome-svg-core' import { faTimes, @@ -27,18 +30,10 @@ const ProfileTab = { newName: this.$store.state.users.currentUser.name_unescaped, newBio: unescape(this.$store.state.users.currentUser.description), newLocked: this.$store.state.users.currentUser.locked, - newNoRichText: this.$store.state.users.currentUser.no_rich_text, - newDefaultScope: this.$store.state.users.currentUser.default_scope, newFields: this.$store.state.users.currentUser.fields.map(field => ({ name: field.name, value: field.value })), - hideFollows: this.$store.state.users.currentUser.hide_follows, - hideFollowers: this.$store.state.users.currentUser.hide_followers, - hideFollowsCount: this.$store.state.users.currentUser.hide_follows_count, - hideFollowersCount: this.$store.state.users.currentUser.hide_followers_count, showRole: this.$store.state.users.currentUser.show_role, role: this.$store.state.users.currentUser.role, - discoverable: this.$store.state.users.currentUser.discoverable, bot: this.$store.state.users.currentUser.bot, - allowFollowingMove: this.$store.state.users.currentUser.allow_following_move, pickAvatarBtnVisible: true, bannerUploading: false, backgroundUploading: false, @@ -54,12 +49,14 @@ const ProfileTab = { EmojiInput, Autosuggest, ProgressButton, - Checkbox + Checkbox, + BooleanSetting }, computed: { user () { return this.$store.state.users.currentUser }, + ...SharedComputedObject(), emojiUserSuggestor () { return suggestor({ emoji: [ @@ -123,15 +120,7 @@ const ProfileTab = { /* eslint-disable camelcase */ display_name: this.newName, fields_attributes: this.newFields.filter(el => el != null), - default_scope: this.newDefaultScope, - no_rich_text: this.newNoRichText, - hide_follows: this.hideFollows, - hide_followers: this.hideFollowers, - discoverable: this.discoverable, bot: this.bot, - allow_following_move: this.allowFollowingMove, - hide_follows_count: this.hideFollowsCount, - hide_followers_count: this.hideFollowersCount, show_role: this.showRole /* eslint-enable camelcase */ } }).then((user) => { diff --git a/src/components/settings_modal/tabs/profile_tab.vue b/src/components/settings_modal/tabs/profile_tab.vue index bb3c301d5c..2cf3e8bed5 100644 --- a/src/components/settings_modal/tabs/profile_tab.vue +++ b/src/components/settings_modal/tabs/profile_tab.vue @@ -25,61 +25,6 @@ class="bio resize-height" /> -

- - {{ $t('settings.lock_account_description') }} - -

-
- -
- -
-
-

- - {{ $t('settings.no_rich_text_description') }} - -

-

- - {{ $t('settings.hide_follows_description') }} - -

-

- - {{ $t('settings.hide_follows_count_description') }} - -

-

- - {{ $t('settings.hide_followers_description') }} - -

-

- - {{ $t('settings.hide_followers_count_description') }} - -

-

- - {{ $t('settings.allow_following_move') }} - -

-

- - {{ $t('settings.discoverable') }} - -

{{ $t('settings.profile_fields.label') }}

{{ $t('settings.avatar_size_instruction') }}

-
- @@ -269,6 +208,67 @@ {{ $t('settings.save') }}
+
+

{{ $t('settings.account_privacy') }}

+
    +
  • + + {{ $t('settings.lock_account_description') }} + +
  • +
  • + + {{ $t('settings.discoverable') }} + +
  • +
  • + + {{ $t('settings.allow_following_move') }} + +
  • +
  • + + {{ $t('settings.hide_favorites_description') }} + +
  • +
  • + + {{ $t('settings.hide_followers_description') }} + +
      +
    • + + {{ $t('settings.hide_followers_count_description') }} + +
    • +
    +
  • +
  • + + {{ $t('settings.hide_follows_description') }} + +
      +
    • + + {{ $t('settings.hide_follows_count_description') }} + +
    • +
    +
  • +
+
diff --git a/src/i18n/en.json b/src/i18n/en.json index 8eb7fcc6ea..932e8af531 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -259,11 +259,14 @@ }, "settings": { "app_name": "App name", + "expert_mode": "Expert mode", "save": "Save changes", "security": "Security", "setting_changed": "Setting is different from default", + "setting_server_side": "This setting is tied to your profile and affects all sessions and clients", "enter_current_password_to_confirm": "Enter your current password to confirm your identity", "post_look_feel": "Posts Look & Feel", + "mention_links": "Mention links", "mfa": { "otp": "OTP", "setup_otp": "Setup OTP", @@ -400,6 +403,7 @@ "name": "Label", "value": "Content" }, + "account_privacy": "Privacy", "use_contain_fit": "Don't crop the attachment in thumbnails", "name": "Name", "name_bio": "Name & bio", @@ -417,6 +421,7 @@ "no_rich_text_description": "Strip rich text formatting from all posts", "no_blocks": "No blocks", "no_mutes": "No mutes", + "hide_favorites_description": "Don't show list of my favorites (people still get notified)", "hide_follows_description": "Don't show who I'm following", "hide_followers_description": "Don't show who's following me", "hide_follows_count_description": "Don't show follow count", diff --git a/src/main.js b/src/main.js index 3895da89b8..73bd49ed59 100644 --- a/src/main.js +++ b/src/main.js @@ -11,6 +11,7 @@ import statusesModule from './modules/statuses.js' import usersModule from './modules/users.js' import apiModule from './modules/api.js' import configModule from './modules/config.js' +import serverSideConfigModule from './modules/serverSideConfig.js' import shoutModule from './modules/shout.js' import oauthModule from './modules/oauth.js' import authFlowModule from './modules/auth_flow.js' @@ -88,6 +89,7 @@ const persistedStateOptions = { users: usersModule, api: apiModule, config: configModule, + serverSideConfig: serverSideConfigModule, shout: shoutModule, oauth: oauthModule, authFlow: authFlowModule, diff --git a/src/modules/config.js b/src/modules/config.js index 20979174a6..775ee39849 100644 --- a/src/modules/config.js +++ b/src/modules/config.js @@ -16,6 +16,7 @@ export const multiChoiceProperties = [ ] export const defaultState = { + expertLevel: 0, // used to track which settings to show and hide colors: {}, theme: undefined, customTheme: undefined, diff --git a/src/modules/serverSideConfig.js b/src/modules/serverSideConfig.js new file mode 100644 index 0000000000..75ea91befc --- /dev/null +++ b/src/modules/serverSideConfig.js @@ -0,0 +1,111 @@ +import { get, set } from 'lodash' + +export const settingsMapGet = { + 'defaultScope': 'source.privacy', + 'defaultNSFW': 'source.sensitive', + 'stripRichContent': 'source.pleroma.no_rich_content', + // Privacy + 'locked': 'locked', + 'acceptChatMessages': 'pleroma.accepts_chat_messages', + 'allowFollowingMove': 'pleroma.allow_following_move', + 'discoverable': 'source.discoverable', + 'hideFavorites': 'pleroma.hide_favorites', + 'hideFollowers': 'pleroma.hide_followers', + 'hideFollows': 'pleroma.hide_follows', + 'hideFollowersCount': 'pleroma.hide_followers_count', + 'hideFollowsCount': 'pleroma.hide_follows_count', + // NotificationSettingsAPIs + 'webPushHideContents': 'pleroma.notification_settings.hide_notification_contents', + 'blockNotificationsFromStrangers': 'pleroma.notification_settings.block_from_strangers' +} + +export const settingsMapSet = { + 'defaultScope': 'source.privacy', + 'defaultNSFW': 'source.sensitive', + 'stripRichContent': 'source.pleroma.no_rich_content', + // Privacy + 'locked': 'locked', + 'acceptChatMessages': 'accepts_chat_messages', + 'allowFollowingMove': 'allow_following_move', + 'discoverable': 'source.discoverable', + 'hideFavorites': 'hide_favorites', + 'hideFollowers': 'hide_followers', + 'hideFollows': 'hide_follows', + 'hideFollowersCount': 'hide_followers_count', + 'hideFollowsCount': 'hide_follows_count', + // NotificationSettingsAPIs + 'webPushHideContents': 'hide_notification_contents', + 'blockNotificationsFromStrangers': 'block_from_strangers' +} + +export const customAPIs = { + __defaultApi: 'updateProfile', + 'webPushHideContents': 'updateNotificationSettings', + 'blockNotificationsFromStrangers': 'updateNotificationSettings' +} + +export const defaultState = Object.fromEntries(Object.keys(settingsMapGet).map(key => [key, undefined])) + +const serverSideConfig = { + state: { ...defaultState }, + mutations: { + confirmServerSideOption (state, { name, value }) { + set(state, name, value) + }, + wipeServerSideOption (state, { name }) { + set(state, name, undefined) + }, + // Set the settings based on their path location + setCurrentUser (state, user) { + Object.entries(settingsMapGet).forEach(([name, path]) => { + set(state, name, get(user._original, path)) + }) + } + }, + actions: { + setServerSideOption ({ rootState, state, commit, dispatch }, { name, value }) { + const oldValue = get(state, name) + const params = {} + const path = settingsMapSet[name] + if (!path) throw new Error('Invalid server-side setting') + commit('wipeServerSideOption', { name }) + const customAPIName = customAPIs[name] || customAPIs.__defaultApi + const api = rootState.api.backendInteractor[customAPIName] + let prefix = '' + switch (customAPIName) { + case 'updateNotificationSettings': + prefix = 'settings.' + break + default: + prefix = 'params.' + break + } + + set(params, prefix + path, value) + api(params) + .then((result) => { + switch (customAPIName) { + case 'updateNotificationSettings': + console.log(result) + if (result.status === 'success') { + commit('confirmServerSideOption', { name, value }) + } else { + commit('confirmServerSideOption', { name, value: oldValue }) + } + break + default: + commit('addNewUsers', [result]) + commit('setCurrentUser', result) + break + } + console.log(state) + }) + .catch((e) => { + console.warn('Error setting server-side option:', e) + commit('confirmServerSideOption', { name, value: oldValue }) + }) + } + } +} + +export default serverSideConfig diff --git a/src/services/entity_normalizer/entity_normalizer.service.js b/src/services/entity_normalizer/entity_normalizer.service.js index 7025d80324..f219c161f4 100644 --- a/src/services/entity_normalizer/entity_normalizer.service.js +++ b/src/services/entity_normalizer/entity_normalizer.service.js @@ -44,6 +44,7 @@ export const parseUser = (data) => { const mastoShort = masto && !data.hasOwnProperty('avatar') output.id = String(data.id) + output._original = data // used for server-side settings if (masto) { output.screen_name = data.acct From b1b9260a1df561a38b9bb904e103cccb37df8ea6 Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Tue, 22 Feb 2022 23:32:12 +0200 Subject: [PATCH 0129/1033] new defaults --- src/modules/config.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/modules/config.js b/src/modules/config.js index 775ee39849..e5321507ee 100644 --- a/src/modules/config.js +++ b/src/modules/config.js @@ -37,12 +37,12 @@ export const defaultState = { preloadImage: true, loopVideo: true, loopVideoSilentOnly: true, - streaming: false, + streaming: true, emojiReactionsOnTimeline: true, alwaysShowNewPostButton: false, autohideFloatingPostButton: false, pauseOnUnfocused: true, - stopGifs: false, + stopGifs: true, replyVisibility: 'all', notificationVisibility: { follows: true, @@ -70,7 +70,7 @@ export const defaultState = { hideFilteredStatuses: undefined, // instance default playVideosInModal: false, useOneClickNsfw: false, - useContainFit: false, + useContainFit: true, greentext: undefined, // instance default useAtIcon: undefined, // instance default mentionLinkDisplay: undefined, // instance default From 9623b0e1409e85c5598989f0cd13f3ccbb504bd2 Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Thu, 24 Feb 2022 14:41:55 +0200 Subject: [PATCH 0130/1033] better phrasing --- src/i18n/en.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i18n/en.json b/src/i18n/en.json index 932e8af531..a66aaa0bd4 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -259,7 +259,7 @@ }, "settings": { "app_name": "App name", - "expert_mode": "Expert mode", + "expert_mode": "Show advanced", "save": "Save changes", "security": "Security", "setting_changed": "Setting is different from default", From f626da838a7abeb3a2d3cd5f71ee4eb2ca272361 Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Thu, 24 Feb 2022 15:00:08 +0200 Subject: [PATCH 0131/1033] revert to using local setting for default nsfw since backend is broken --- src/components/post_status_form/post_status_form.js | 1 + src/components/settings_modal/tabs/general_tab.vue | 3 ++- src/modules/serverSideConfig.js | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/components/post_status_form/post_status_form.js b/src/components/post_status_form/post_status_form.js index fe07309fc9..9d7bbd753b 100644 --- a/src/components/post_status_form/post_status_form.js +++ b/src/components/post_status_form/post_status_form.js @@ -117,6 +117,7 @@ const PostStatusForm = { ? this.copyMessageScope : this.$store.state.users.currentUser.default_scope + // const { defaultNSFW: sensitiveByDefault } = this.$store.state.serverSideConfig const { postContentType: contentType, sensitiveByDefault } = this.$store.getters.mergedConfig return { diff --git a/src/components/settings_modal/tabs/general_tab.vue b/src/components/settings_modal/tabs/general_tab.vue index 4accf0c1c8..5db70d770c 100644 --- a/src/components/settings_modal/tabs/general_tab.vue +++ b/src/components/settings_modal/tabs/general_tab.vue @@ -221,7 +221,8 @@
  • - + + {{ $t('settings.sensitive_by_default') }}
  • diff --git a/src/modules/serverSideConfig.js b/src/modules/serverSideConfig.js index 75ea91befc..ea2dc5e369 100644 --- a/src/modules/serverSideConfig.js +++ b/src/modules/serverSideConfig.js @@ -2,7 +2,7 @@ import { get, set } from 'lodash' export const settingsMapGet = { 'defaultScope': 'source.privacy', - 'defaultNSFW': 'source.sensitive', + 'defaultNSFW': 'source.sensitive', // BROKEN: pleroma/pleroma#2837 'stripRichContent': 'source.pleroma.no_rich_content', // Privacy 'locked': 'locked', From 819b76026101ddc0363118f240049a0019ebb4d6 Mon Sep 17 00:00:00 2001 From: Ilja Date: Sat, 26 Feb 2022 01:53:01 +0100 Subject: [PATCH 0132/1033] Fix up and code review * Check if it works properly * Notifs are shown as BE returns them * The Interaction view has Reports, but only when you're mod or admin * Do some extra translations * Fix some console spam --- src/components/interactions/interactions.js | 3 ++- src/i18n/en.json | 2 ++ src/i18n/nl.json | 13 +++++++++++++ src/modules/reports.js | 5 +---- src/services/api/api.service.js | 3 ++- .../notification_utils/notification_utils.js | 2 +- .../notifications_fetcher.service.js | 4 +--- 7 files changed, 22 insertions(+), 10 deletions(-) diff --git a/src/components/interactions/interactions.js b/src/components/interactions/interactions.js index 54275a7b4a..53ec7d4932 100644 --- a/src/components/interactions/interactions.js +++ b/src/components/interactions/interactions.js @@ -13,7 +13,8 @@ const Interactions = { data () { return { allowFollowingMove: this.$store.state.users.currentUser.allow_following_move, - filterMode: tabModeDict['mentions'] + filterMode: tabModeDict['mentions'], + canSeeReports: ['moderator', 'admin'].includes(this.$store.state.users.currentUser.role) } }, methods: { diff --git a/src/i18n/en.json b/src/i18n/en.json index 3bdd42e3bb..9e74840fc3 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -176,6 +176,8 @@ "interactions": { "favs_repeats": "Repeats and Favorites", "follows": "New follows", + "emoji_reactions": "Emoji Reactions", + "reports": "Reports", "moves": "User migrates", "load_older": "Load older interactions" }, diff --git a/src/i18n/nl.json b/src/i18n/nl.json index a01e57a097..8da07ac7c9 100644 --- a/src/i18n/nl.json +++ b/src/i18n/nl.json @@ -661,6 +661,8 @@ "interactions": { "favs_repeats": "Herhalingen en Favorieten", "follows": "Nieuwe volgingen", + "emoji_reactions": "Emoji Reacties", + "reports": "Rapportages", "moves": "Gebruiker migreert", "load_older": "Oudere interacties laden" }, @@ -669,6 +671,17 @@ "error": "Niet gevonden.", "remote_user_resolver": "Externe gebruikers zoeker" }, + "report": { + "reporter": "Reporteerder:", + "reported_user": "Gerapporteerde gebruiker:", + "reported_statuses": "Gerapporteerde statussen:", + "notes": "Notas:", + "state": "Status:", + "state_open": "Open", + "state_closed": "Gesloten", + "state_resolved": "Opgelost" + }, + "selectable_list": { "select_all": "Alles selecteren" }, diff --git a/src/modules/reports.js b/src/modules/reports.js index b25e9ee9a5..925792c031 100644 --- a/src/modules/reports.js +++ b/src/modules/reports.js @@ -43,11 +43,8 @@ const reports = { }, setReportState ({ commit, dispatch, rootState }, { id, state }) { const oldState = rootState.reports.reports[id].state - console.log(oldState, state) commit('setReportState', { id, state }) - rootState.api.backendInteractor.setReportState({ id, state }).then(report => { - console.log(report) - }).catch(e => { + rootState.api.backendInteractor.setReportState({ id, state }).catch(e => { console.error('Failed to set report state', e) dispatch('pushGlobalNotice', { level: 'error', diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js index e60010fe72..27ea5199b1 100644 --- a/src/services/api/api.service.js +++ b/src/services/api/api.service.js @@ -1270,7 +1270,8 @@ const deleteChatMessage = ({ chatId, messageId, credentials }) => { } const setReportState = ({ id, state, credentials }) => { - // Can't use promisedRequest because on OK this does not return json + // TODO: Can't use promisedRequest because on OK this does not return json + // See https://git.pleroma.social/pleroma/pleroma-fe/-/merge_requests/1322 return fetch(PLEROMA_ADMIN_REPORTS, { headers: { ...authHeaders(credentials), diff --git a/src/services/notification_utils/notification_utils.js b/src/services/notification_utils/notification_utils.js index dff97aa295..b338eb8b3b 100644 --- a/src/services/notification_utils/notification_utils.js +++ b/src/services/notification_utils/notification_utils.js @@ -93,7 +93,7 @@ export const prepareNotificationObject = (notification, i18n) => { i18nString = 'follow_request' break case 'pleroma:report': - i18nString = 'reported' + i18nString = 'submitted_report' break } diff --git a/src/services/notifications_fetcher/notifications_fetcher.service.js b/src/services/notifications_fetcher/notifications_fetcher.service.js index 2da6d64618..4ecb348efc 100644 --- a/src/services/notifications_fetcher/notifications_fetcher.service.js +++ b/src/services/notifications_fetcher/notifications_fetcher.service.js @@ -24,9 +24,7 @@ const fetchAndUpdate = ({ store, credentials, older = false }) => { const timelineData = rootState.statuses.notifications const hideMutedPosts = getters.mergedConfig.hideMutedPosts - if (rootState.users.currentUser.role === 'admin') { - args['includeTypes'] = mastoApiNotificationTypes - } + args['includeTypes'] = mastoApiNotificationTypes args['withMuted'] = !hideMutedPosts args['timeline'] = 'notifications' From c9e4b6e7a10b614bcf0cc0b91b7540b7b4fdcca2 Mon Sep 17 00:00:00 2001 From: Ilja Date: Sat, 26 Feb 2022 02:13:43 +0100 Subject: [PATCH 0133/1033] Make linter happy `npm run lint` gave warnings for two files, fixed them with `./node_modules/.bin/eslint --fix $FILENAME` --- src/components/attachment/attachment.vue | 19 +++++++++++-------- src/components/gallery/gallery.vue | 4 ++-- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/components/attachment/attachment.vue b/src/components/attachment/attachment.vue index 5917375984..c4399f3066 100644 --- a/src/components/attachment/attachment.vue +++ b/src/components/attachment/attachment.vue @@ -81,56 +81,56 @@ @@ -160,7 +160,10 @@ :href="attachment.url" target="_blank" > - +

    {{ localDescription }}

    diff --git a/src/components/gallery/gallery.vue b/src/components/gallery/gallery.vue index f9cad8a9c1..f2e1b5ce51 100644 --- a/src/components/gallery/gallery.vue +++ b/src/components/gallery/gallery.vue @@ -26,8 +26,8 @@ :size="size" :editable="editable" :remove="removeAttachment" - :shiftUp="!(attachmentIndex === 0 && rowIndex === 0) && shiftUpAttachment" - :shiftDn="!(attachmentIndex === row.items.length - 1 && rowIndex === rows.length - 1) && shiftDnAttachment" + :shift-up="!(attachmentIndex === 0 && rowIndex === 0) && shiftUpAttachment" + :shift-dn="!(attachmentIndex === row.items.length - 1 && rowIndex === rows.length - 1) && shiftDnAttachment" :edit="editAttachment" :description="descriptions && descriptions[attachment.id]" :hide-description="size === 'small' || tooManyAttachments && hidingLong" From c07c0b22604ac57f91f08ed330eee98ee82e214e Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Mon, 28 Feb 2022 17:43:08 +0200 Subject: [PATCH 0134/1033] fix firefox rendering (??????????) --- src/components/settings_modal/helpers/boolean_setting.vue | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/components/settings_modal/helpers/boolean_setting.vue b/src/components/settings_modal/helpers/boolean_setting.vue index c82cf23f83..3a7bd8053d 100644 --- a/src/components/settings_modal/helpers/boolean_setting.vue +++ b/src/components/settings_modal/helpers/boolean_setting.vue @@ -14,9 +14,7 @@ > - - - + From e3d602fdccb0dfe211fd3950210cdf8fda43bf95 Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Mon, 28 Feb 2022 17:45:07 +0200 Subject: [PATCH 0135/1033] revert changes related to streaming/firehose setting, reword it so it's not confused with websocket streaming --- src/components/settings_modal/tabs/general_tab.vue | 3 +-- src/i18n/en.json | 4 ++-- src/modules/config.js | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/components/settings_modal/tabs/general_tab.vue b/src/components/settings_modal/tabs/general_tab.vue index 5db70d770c..7944b03cf2 100644 --- a/src/components/settings_modal/tabs/general_tab.vue +++ b/src/components/settings_modal/tabs/general_tab.vue @@ -27,7 +27,7 @@
  • - + {{ $t('settings.streaming') }}
      {{ $t('settings.pause_on_unfocused') }} diff --git a/src/i18n/en.json b/src/i18n/en.json index a66aaa0bd4..da5e662dba 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -435,7 +435,7 @@ "valid_until": "Valid until", "revoke_token": "Revoke", "panelRadius": "Panels", - "pause_on_unfocused": "Pause streaming when tab is not focused", + "pause_on_unfocused": "Pause when tab is not focused", "presets": "Presets", "profile_background": "Profile background", "profile_banner": "Profile banner", @@ -473,7 +473,7 @@ "post_status_content_type": "Post status content type", "sensitive_by_default": "Mark posts as sensitive by default", "stop_gifs": "Pause animated images until you hover on them", - "streaming": "Enable automatic streaming of new posts when scrolled to the top", + "streaming": "Automatically show new posts when scrolled to the top", "user_mutes": "Users", "useStreamingApi": "Receive posts and notifications real-time", "useStreamingApiWarning": "(Not recommended, experimental, known to skip posts)", diff --git a/src/modules/config.js b/src/modules/config.js index e5321507ee..866015649d 100644 --- a/src/modules/config.js +++ b/src/modules/config.js @@ -37,7 +37,7 @@ export const defaultState = { preloadImage: true, loopVideo: true, loopVideoSilentOnly: true, - streaming: true, + streaming: false, emojiReactionsOnTimeline: true, alwaysShowNewPostButton: false, autohideFloatingPostButton: false, From 3a5ad18aca6a7303e6f6b97dd3f0919d5532184c Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Mon, 28 Feb 2022 18:00:38 +0200 Subject: [PATCH 0136/1033] fix stripping rich content not working --- src/modules/serverSideConfig.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/serverSideConfig.js b/src/modules/serverSideConfig.js index ea2dc5e369..c9d148d1a2 100644 --- a/src/modules/serverSideConfig.js +++ b/src/modules/serverSideConfig.js @@ -3,7 +3,7 @@ import { get, set } from 'lodash' export const settingsMapGet = { 'defaultScope': 'source.privacy', 'defaultNSFW': 'source.sensitive', // BROKEN: pleroma/pleroma#2837 - 'stripRichContent': 'source.pleroma.no_rich_content', + 'stripRichContent': 'source.pleroma.no_rich_text', // Privacy 'locked': 'locked', 'acceptChatMessages': 'pleroma.accepts_chat_messages', @@ -22,7 +22,7 @@ export const settingsMapGet = { export const settingsMapSet = { 'defaultScope': 'source.privacy', 'defaultNSFW': 'source.sensitive', - 'stripRichContent': 'source.pleroma.no_rich_content', + 'stripRichContent': 'no_rich_text', // Privacy 'locked': 'locked', 'acceptChatMessages': 'accepts_chat_messages', From 8bb97fbfeb8f34c36aec96ee175d6eced49c1fb4 Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Mon, 28 Feb 2022 18:01:41 +0200 Subject: [PATCH 0137/1033] fix settings behaving erratically and not updating properly --- src/modules/serverSideConfig.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/serverSideConfig.js b/src/modules/serverSideConfig.js index c9d148d1a2..2db6fc0654 100644 --- a/src/modules/serverSideConfig.js +++ b/src/modules/serverSideConfig.js @@ -44,7 +44,7 @@ export const customAPIs = { 'blockNotificationsFromStrangers': 'updateNotificationSettings' } -export const defaultState = Object.fromEntries(Object.keys(settingsMapGet).map(key => [key, undefined])) +export const defaultState = Object.fromEntries(Object.keys(settingsMapGet).map(key => [key, null])) const serverSideConfig = { state: { ...defaultState }, @@ -53,7 +53,7 @@ const serverSideConfig = { set(state, name, value) }, wipeServerSideOption (state, { name }) { - set(state, name, undefined) + set(state, name, null) }, // Set the settings based on their path location setCurrentUser (state, user) { From cf58df17f6624362ea51f8813874250eff6d185a Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Mon, 28 Feb 2022 18:04:13 +0200 Subject: [PATCH 0138/1033] hidden away more settings when logged out --- src/components/settings_modal/tabs/filtering_tab.vue | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/components/settings_modal/tabs/filtering_tab.vue b/src/components/settings_modal/tabs/filtering_tab.vue index cd7f0bc41b..0352e88785 100644 --- a/src/components/settings_modal/tabs/filtering_tab.vue +++ b/src/components/settings_modal/tabs/filtering_tab.vue @@ -22,6 +22,7 @@
    • {{ $t('settings.hide_muted_threads') }} @@ -30,6 +31,7 @@
    • {{ $t('settings.hide_muted_posts') }} @@ -46,6 +48,7 @@ id="replyVisibility" path="replyVisibility" :options="replyVisibilityOptions" + v-if="user" > {{ $t('settings.replies_in_timeline') }} From 67319d0e5b0b36a440dcaf35119e41046cc6e3fd Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Mon, 28 Feb 2022 18:15:07 +0200 Subject: [PATCH 0139/1033] fix typos in profile page --- src/components/settings_modal/tabs/profile_tab.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/settings_modal/tabs/profile_tab.vue b/src/components/settings_modal/tabs/profile_tab.vue index 2cf3e8bed5..699fdcf494 100644 --- a/src/components/settings_modal/tabs/profile_tab.vue +++ b/src/components/settings_modal/tabs/profile_tab.vue @@ -242,7 +242,7 @@
    • {{ $t('settings.hide_followers_count_description') }} @@ -260,7 +260,7 @@
    • {{ $t('settings.hide_follows_count_description') }} From f4b36a9ebf99cc69ab93c148e488401daf3713b7 Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Mon, 28 Feb 2022 18:15:21 +0200 Subject: [PATCH 0140/1033] fix errors in choicesetting --- src/components/settings_modal/helpers/choice_setting.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/components/settings_modal/helpers/choice_setting.js b/src/components/settings_modal/helpers/choice_setting.js index 07d0f76d32..4677d4c194 100644 --- a/src/components/settings_modal/helpers/choice_setting.js +++ b/src/components/settings_modal/helpers/choice_setting.js @@ -1,10 +1,12 @@ import { get, set } from 'lodash' import Select from 'src/components/select/select.vue' import ModifiedIndicator from './modified_indicator.vue' +import ServerSideIndicator from './server_side_indicator.vue' export default { components: { Select, - ModifiedIndicator + ModifiedIndicator, + ServerSideIndicator }, props: [ 'path', @@ -28,6 +30,9 @@ export default { defaultState () { return get(this.$parent, this.pathDefault) }, + isServerSide () { + return this.path.startsWith('serverSide_') + }, isChanged () { return !this.path.startsWith('serverSide_') && this.state !== this.defaultState }, From 39909c8a8590e866082da5d2528b4df2898f2bf5 Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Mon, 28 Feb 2022 18:17:13 +0200 Subject: [PATCH 0141/1033] pre-emptively wipe serverside settings on logout --- src/modules/serverSideConfig.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/modules/serverSideConfig.js b/src/modules/serverSideConfig.js index 2db6fc0654..4f0cd96571 100644 --- a/src/modules/serverSideConfig.js +++ b/src/modules/serverSideConfig.js @@ -55,6 +55,11 @@ const serverSideConfig = { wipeServerSideOption (state, { name }) { set(state, name, null) }, + wipeAllServerSideOptions (state) { + Object.keys(settingsMapGet).forEach(key => { + set(state, key, null) + }) + }, // Set the settings based on their path location setCurrentUser (state, user) { Object.entries(settingsMapGet).forEach(([name, path]) => { @@ -104,6 +109,9 @@ const serverSideConfig = { console.warn('Error setting server-side option:', e) commit('confirmServerSideOption', { name, value: oldValue }) }) + }, + logout ({ commit }) { + commit('wipeAllServerSideOptions') } } } From 77bb0b553062b91a69fbf92ce7540565f098951f Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Mon, 28 Feb 2022 18:23:32 +0200 Subject: [PATCH 0142/1033] lint --- src/components/attachment/attachment.vue | 19 +- src/components/gallery/gallery.vue | 4 +- .../helpers/boolean_setting.vue | 4 +- .../settings_modal/helpers/choice_setting.vue | 4 +- .../settings_modal/settings_modal.vue | 4 +- .../settings_modal/tabs/filtering_tab.vue | 16 +- .../settings_modal/tabs/general_tab.js | 2 +- .../settings_modal/tabs/general_tab.vue | 167 +++++++++++++----- .../settings_modal/tabs/notifications_tab.vue | 15 +- .../settings_modal/tabs/profile_tab.vue | 7 +- 10 files changed, 168 insertions(+), 74 deletions(-) diff --git a/src/components/attachment/attachment.vue b/src/components/attachment/attachment.vue index 5917375984..c4399f3066 100644 --- a/src/components/attachment/attachment.vue +++ b/src/components/attachment/attachment.vue @@ -81,56 +81,56 @@ @@ -160,7 +160,10 @@ :href="attachment.url" target="_blank" > - +

      {{ localDescription }}

      diff --git a/src/components/gallery/gallery.vue b/src/components/gallery/gallery.vue index f9cad8a9c1..f2e1b5ce51 100644 --- a/src/components/gallery/gallery.vue +++ b/src/components/gallery/gallery.vue @@ -26,8 +26,8 @@ :size="size" :editable="editable" :remove="removeAttachment" - :shiftUp="!(attachmentIndex === 0 && rowIndex === 0) && shiftUpAttachment" - :shiftDn="!(attachmentIndex === row.items.length - 1 && rowIndex === rows.length - 1) && shiftDnAttachment" + :shift-up="!(attachmentIndex === 0 && rowIndex === 0) && shiftUpAttachment" + :shift-dn="!(attachmentIndex === row.items.length - 1 && rowIndex === rows.length - 1) && shiftDnAttachment" :edit="editAttachment" :description="descriptions && descriptions[attachment.id]" :hide-description="size === 'small' || tooManyAttachments && hidingLong" diff --git a/src/components/settings_modal/helpers/boolean_setting.vue b/src/components/settings_modal/helpers/boolean_setting.vue index 3a7bd8053d..e0d825f20c 100644 --- a/src/components/settings_modal/helpers/boolean_setting.vue +++ b/src/components/settings_modal/helpers/boolean_setting.vue @@ -1,7 +1,7 @@ diff --git a/src/components/settings_modal/helpers/choice_setting.vue b/src/components/settings_modal/helpers/choice_setting.vue index 845886ca50..54f5d0a76b 100644 --- a/src/components/settings_modal/helpers/choice_setting.vue +++ b/src/components/settings_modal/helpers/choice_setting.vue @@ -1,7 +1,7 @@ diff --git a/src/components/settings_modal/settings_modal.vue b/src/components/settings_modal/settings_modal.vue index 0aad1abb51..1805c77fdd 100644 --- a/src/components/settings_modal/settings_modal.vue +++ b/src/components/settings_modal/settings_modal.vue @@ -109,8 +109,8 @@ - - {{ $t("settings.expert_mode")}} + + {{ $t("settings.expert_mode") }}
  • diff --git a/src/components/settings_modal/tabs/filtering_tab.vue b/src/components/settings_modal/tabs/filtering_tab.vue index 0352e88785..e60a8a857a 100644 --- a/src/components/settings_modal/tabs/filtering_tab.vue +++ b/src/components/settings_modal/tabs/filtering_tab.vue @@ -21,8 +21,8 @@
  • {{ $t('settings.hide_muted_threads') }} @@ -30,8 +30,8 @@
  • {{ $t('settings.hide_muted_posts') }} @@ -40,15 +40,18 @@
  • - + {{ $t('settings.hide_post_stats') }}
  • {{ $t('settings.replies_in_timeline') }} @@ -87,7 +90,10 @@ -
    +

    {{ $t('settings.user_profiles') }}

    • diff --git a/src/components/settings_modal/tabs/general_tab.js b/src/components/settings_modal/tabs/general_tab.js index 9e4e282f58..fe7deb6ee9 100644 --- a/src/components/settings_modal/tabs/general_tab.js +++ b/src/components/settings_modal/tabs/general_tab.js @@ -41,7 +41,7 @@ const GeneralTab = { ChoiceSetting, InterfaceLanguageSwitcher, ScopeSelector, - ServerSideIndicator, + ServerSideIndicator }, computed: { postFormats () { diff --git a/src/components/settings_modal/tabs/general_tab.vue b/src/components/settings_modal/tabs/general_tab.vue index 7944b03cf2..d4196c3def 100644 --- a/src/components/settings_modal/tabs/general_tab.vue +++ b/src/components/settings_modal/tabs/general_tab.vue @@ -27,7 +27,7 @@
    • - + {{ $t('settings.streaming') }}
      • - + {{ $t('settings.useStreamingApi') }}
        @@ -54,22 +57,34 @@
      • - + {{ $t('settings.virtual_scrolling') }}
      • - + {{ $t('settings.always_show_post_button') }}
      • - + {{ $t('settings.autohide_floating_post_button') }}
      • - + {{ $t('settings.hide_shoutbox') }}
      • @@ -84,18 +99,28 @@
      • - + {{ $t('settings.emoji_reactions_on_timeline') }}
      • - + {{ $t('settings.no_rich_text_description') }}
      • {{ $t('settings.attachments') }}

      • - + {{ $t('settings.use_contain_fit') }}
      • @@ -107,7 +132,8 @@
        • {{ $t('settings.preload_images') }} @@ -115,7 +141,8 @@
        • {{ $t('settings.use_one_click_nsfw') }} @@ -123,7 +150,10 @@
      • - + {{ $t('settings.loop_video') }}
        • {{ $t('settings.loop_video_silent_only') }} @@ -147,7 +178,10 @@
      • - + {{ $t('settings.play_videos_in_modal') }}
      • @@ -165,51 +199,74 @@ class="setting-list suboptions" >
      • - + {{ $t('settings.mention_link_show_tooltip') }}
      -
    • - - {{ $t('settings.use_at_icon') }} - -
    • -
    • - - {{ $t('settings.mention_link_show_avatar') }} - -
    • -
    • - - {{ $t('settings.mention_link_fade_domain') }} - -
    • -
    • - - {{ $t('settings.mention_link_bolden_you') }} - -
    • -

      {{ $t('settings.fun') }}

    • - + + {{ $t('settings.use_at_icon') }} + +
    • +
    • + + {{ $t('settings.mention_link_show_avatar') }} + +
    • +
    • + + {{ $t('settings.mention_link_fade_domain') }} + +
    • +
    • + + {{ $t('settings.mention_link_bolden_you') }} + +
    • +

      + {{ $t('settings.fun') }} +

      +
    • + {{ $t('settings.greentext') }}
    • - + {{ $t('settings.show_yous') }}
    -
    +

    {{ $t('settings.composing') }}

    • - + {{ $t('settings.scope_copy') }}
    • - + {{ $t('settings.subject_input_always_show') }}
    • @@ -255,22 +318,34 @@
    • - + {{ $t('settings.minimal_scopes_mode') }}
    • - + {{ $t('settings.always_show_post_button') }}
    • - + {{ $t('settings.autohide_floating_post_button') }}
    • - + {{ $t('settings.pad_emoji') }}
    • diff --git a/src/components/settings_modal/tabs/notifications_tab.vue b/src/components/settings_modal/tabs/notifications_tab.vue index 5e9ce91ec9..86be609587 100644 --- a/src/components/settings_modal/tabs/notifications_tab.vue +++ b/src/components/settings_modal/tabs/notifications_tab.vue @@ -46,16 +46,25 @@
    -
    +

    {{ $t('settings.notification_setting_privacy') }}

    • - + {{ $t('settings.enable_web_push_notifications') }}
    • - + {{ $t('settings.notification_setting_hide_notification_contents') }}
    • diff --git a/src/components/settings_modal/tabs/profile_tab.vue b/src/components/settings_modal/tabs/profile_tab.vue index 699fdcf494..e00f6e5b99 100644 --- a/src/components/settings_modal/tabs/profile_tab.vue +++ b/src/components/settings_modal/tabs/profile_tab.vue @@ -101,7 +101,8 @@

      {{ $t('settings.avatar_size_instruction') }}

      -
      + @@ -243,7 +244,7 @@ + > {{ $t('settings.hide_followers_count_description') }} @@ -261,7 +262,7 @@ + > {{ $t('settings.hide_follows_count_description') }} From 77b55a559be26e431f68188058c7900c2e16682c Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Mon, 28 Feb 2022 19:42:02 +0200 Subject: [PATCH 0143/1033] fix placeholder attachments opening new tab --- src/components/attachment/attachment.vue | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/attachment/attachment.vue b/src/components/attachment/attachment.vue index 5917375984..d1d43ac345 100644 --- a/src/components/attachment/attachment.vue +++ b/src/components/attachment/attachment.vue @@ -12,6 +12,7 @@ :href="attachment.url" :alt="attachment.description" :title="attachment.description" + @click.prevent > {{ nsfw ? "NSFW / " : "" }}{{ edit ? '' : placeholderName }} From fe0ed7e8f0941195547b924f99f6c0be707bf964 Mon Sep 17 00:00:00 2001 From: Alexander Tumin Date: Mon, 28 Feb 2022 23:07:20 +0300 Subject: [PATCH 0144/1033] Mute bot posts --- src/components/settings_modal/tabs/filtering_tab.vue | 5 +++++ src/components/status/status.js | 10 +++++++++- src/components/timeline/timeline_quick_settings.js | 7 +++++++ src/components/timeline/timeline_quick_settings.vue | 9 +++++++++ src/i18n/en.json | 1 + src/modules/config.js | 1 + src/modules/instance.js | 1 + 7 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/components/settings_modal/tabs/filtering_tab.vue b/src/components/settings_modal/tabs/filtering_tab.vue index 50ee20e096..87567befac 100644 --- a/src/components/settings_modal/tabs/filtering_tab.vue +++ b/src/components/settings_modal/tabs/filtering_tab.vue @@ -37,6 +37,11 @@
    +
  • + + {{ $t('settings.mute_bot_posts') }} + +
  • {{ $t('settings.hide_post_stats') }} diff --git a/src/components/status/status.js b/src/components/status/status.js index d8f94926e5..ba85114a68 100644 --- a/src/components/status/status.js +++ b/src/components/status/status.js @@ -166,6 +166,9 @@ const Status = { muteWordHits () { return muteWordHits(this.status, this.muteWords) }, + botStatus () { + return this.status.user.bot + }, mentionsLine () { if (!this.headTailLinks) return [] const writtenSet = new Set(this.headTailLinks.writtenMentions.map(_ => _.url)) @@ -191,7 +194,9 @@ const Status = { // Thread is muted status.thread_muted || // Wordfiltered - this.muteWordHits.length > 0 + this.muteWordHits.length > 0 || + // bot status + (this.muteBotStatuses && this.botStatus) return !this.unmuted && !this.shouldNotMute && reasonsToMute }, userIsMuted () { @@ -293,6 +298,9 @@ const Status = { hidePostStats () { return this.mergedConfig.hidePostStats }, + muteBotStatuses () { + return this.mergedConfig.muteBotStatuses + }, currentUser () { return this.$store.state.users.currentUser }, diff --git a/src/components/timeline/timeline_quick_settings.js b/src/components/timeline/timeline_quick_settings.js index 7b4931ce6a..92d5ac1464 100644 --- a/src/components/timeline/timeline_quick_settings.js +++ b/src/components/timeline/timeline_quick_settings.js @@ -53,6 +53,13 @@ const TimelineQuickSettings = { const value = !this.hideMutedPosts this.$store.dispatch('setOption', { name: 'hideFilteredStatuses', value }) } + }, + muteBotStatuses: { + get () { return this.mergedConfig.muteBotStatuses }, + set () { + const value = !this.muteBotStatuses + this.$store.dispatch('setOption', { name: 'muteBotStatuses', value }) + } } } } diff --git a/src/components/timeline/timeline_quick_settings.vue b/src/components/timeline/timeline_quick_settings.vue index 98996ebda2..4d67e06b6d 100644 --- a/src/components/timeline/timeline_quick_settings.vue +++ b/src/components/timeline/timeline_quick_settings.vue @@ -39,6 +39,15 @@ class="dropdown-divider" />
  • + @@ -161,7 +161,10 @@ :href="attachment.url" target="_blank" > - +

    {{ localDescription }}

    diff --git a/src/components/gallery/gallery.vue b/src/components/gallery/gallery.vue index f9cad8a9c1..f2e1b5ce51 100644 --- a/src/components/gallery/gallery.vue +++ b/src/components/gallery/gallery.vue @@ -26,8 +26,8 @@ :size="size" :editable="editable" :remove="removeAttachment" - :shiftUp="!(attachmentIndex === 0 && rowIndex === 0) && shiftUpAttachment" - :shiftDn="!(attachmentIndex === row.items.length - 1 && rowIndex === rows.length - 1) && shiftDnAttachment" + :shift-up="!(attachmentIndex === 0 && rowIndex === 0) && shiftUpAttachment" + :shift-dn="!(attachmentIndex === row.items.length - 1 && rowIndex === rows.length - 1) && shiftDnAttachment" :edit="editAttachment" :description="descriptions && descriptions[attachment.id]" :hide-description="size === 'small' || tooManyAttachments && hidingLong" From 0582f19e7c2c6f916b427d5ecfbbb571178ce841 Mon Sep 17 00:00:00 2001 From: Tusooa Zhu Date: Fri, 6 Aug 2021 20:18:27 -0400 Subject: [PATCH 0148/1033] Add tree-style thread display --- src/components/conversation/conversation.js | 60 ++++++++++++++++++- src/components/conversation/conversation.vue | 59 ++++++++++++------ .../settings_modal/tabs/general_tab.js | 5 ++ .../settings_modal/tabs/general_tab.vue | 9 +++ src/components/thread_tree/thread_tree.js | 52 ++++++++++++++++ src/components/thread_tree/thread_tree.vue | 55 +++++++++++++++++ src/modules/config.js | 4 +- src/modules/instance.js | 1 + 8 files changed, 224 insertions(+), 21 deletions(-) create mode 100644 src/components/thread_tree/thread_tree.js create mode 100644 src/components/thread_tree/thread_tree.vue diff --git a/src/components/conversation/conversation.js b/src/components/conversation/conversation.js index 069c0b4077..e663ba157e 100644 --- a/src/components/conversation/conversation.js +++ b/src/components/conversation/conversation.js @@ -1,5 +1,8 @@ import { reduce, filter, findIndex, clone, get } from 'lodash' import Status from '../status/status.vue' +import ThreadTree from '../thread_tree/thread_tree.vue' + +const debug = console.log const sortById = (a, b) => { const idA = a.type === 'retweet' ? a.retweeted_status.id : a.id @@ -53,6 +56,15 @@ const conversation = { } }, computed: { + displayStyle () { + return this.$store.state.config.conversationDisplay + }, + isTreeView () { + return this.displayStyle === 'tree' + }, + isLinearView () { + return this.displayStyle === 'linear' + }, hideStatus () { if (this.$refs.statusComponent && this.$refs.statusComponent[0]) { return this.virtualHidden && this.$refs.statusComponent[0].suspendable @@ -90,6 +102,49 @@ const conversation = { return sortAndFilterConversation(conversation, this.status) }, + threadTree () { + const reverseLookupTable = this.conversation.reduce((table, status, index) => { + table[status.id] = index + return table + }, {}) + + const threads = this.conversation.reduce((a, cur) => { + const id = cur.id + a.forest[id] = this.getReplies(id) + .map(s => s.id) + .sort((a, b) => reverseLookupTable[a] - reverseLookupTable[b]) + + a.topLevel = a.topLevel.filter(k => a.forest[id].contains(k)) + return a + }, { + forest: {}, + topLevel: this.conversation.map(s => s.id) + }) + + const walk = (forest, topLevel, depth = 0, processed = {}) => topLevel.map(id => { + if (processed[id]) { + return [] + } + + processed[id] = true + return [{ + status: this.conversation[reverseLookupTable[id]], + id, + depth + }, walk(forest, forest[child], depth + 1, processed)].reduce((a, b) => a.concat(b), []) + }).reduce((a, b) => a.concat(b), []) + + const linearized = walk(threads.forest, threads.topLevel) + + return linearized + }, + topLevel () { + const topLevel = this.conversation.reduce((tl, cur) => + tl.filter(k => this.getReplies(cur.id).map(v => v.id).indexOf(k.id) === -1), this.conversation) + debug("toplevel =", topLevel) + debug("toplevel =", topLevel) + return topLevel + }, replies () { let i = 1 // eslint-disable-next-line camelcase @@ -109,7 +164,7 @@ const conversation = { }, {}) }, isExpanded () { - return this.expanded || this.isPage + return !!(this.expanded || this.isPage) }, hiddenStyle () { const height = (this.status && this.status.virtualHeight) || '120px' @@ -117,7 +172,8 @@ const conversation = { } }, components: { - Status + Status, + ThreadTree }, watch: { statusId (newVal, oldVal) { diff --git a/src/components/conversation/conversation.vue b/src/components/conversation/conversation.vue index 3fb26d9239..cea5f88f08 100644 --- a/src/components/conversation/conversation.vue +++ b/src/components/conversation/conversation.vue @@ -18,24 +18,47 @@ {{ $t('timeline.collapse') }}
    - +
    + +
    +
    + +
    ({ + key: mode, + value: mode, + label: this.$t(`settings.conversation_display_${mode}`) + })), mentionLinkDisplayOptions: ['short', 'full_for_remote', 'full'].map(mode => ({ key: mode, value: mode, diff --git a/src/components/settings_modal/tabs/general_tab.vue b/src/components/settings_modal/tabs/general_tab.vue index eba3b2680d..8951c021dc 100644 --- a/src/components/settings_modal/tabs/general_tab.vue +++ b/src/components/settings_modal/tabs/general_tab.vue @@ -152,6 +152,15 @@ {{ $t('settings.show_yous') }} +
  • + + {{ $t('settings.conversation_display') }} + +
  • { + table[status.id] = index + return table + }, {}) + }, + currentReplies () { + debug('status:', this.status) + debug('getReplies:', this.getReplies(this.status.id)) + return this.getReplies(this.status.id).map(({ id }) => this.statusById(id)) + }, + }, + methods: { + statusById (id) { + return this.conversation[this.reverseLookupTable[id]] + }, + collapseThread () { + }, + showThread () { + }, + showAllSubthreads () { + } + } +} + +export default ThreadTree diff --git a/src/components/thread_tree/thread_tree.vue b/src/components/thread_tree/thread_tree.vue new file mode 100644 index 0000000000..8256eee6c3 --- /dev/null +++ b/src/components/thread_tree/thread_tree.vue @@ -0,0 +1,55 @@ + + + + + diff --git a/src/modules/config.js b/src/modules/config.js index 20979174a6..ec75dbfb59 100644 --- a/src/modules/config.js +++ b/src/modules/config.js @@ -12,6 +12,7 @@ const browserLocale = (window.navigator.language || 'en').split('-')[0] export const multiChoiceProperties = [ 'postContentType', 'subjectLineBehavior', + 'conversationDisplay', // tree | linear 'mentionLinkDisplay' // short | full_for_remote | full ] @@ -81,7 +82,8 @@ export const defaultState = { hidePostStats: undefined, // instance default hideUserStats: undefined, // instance default virtualScrolling: undefined, // instance default - sensitiveByDefault: undefined // instance default + sensitiveByDefault: undefined, // instance default + conversationDisplay: undefined // instance default } // caching the instance default properties diff --git a/src/modules/instance.js b/src/modules/instance.js index 1abd784f06..a160a5570f 100644 --- a/src/modules/instance.js +++ b/src/modules/instance.js @@ -53,6 +53,7 @@ const defaultState = { theme: 'pleroma-dark', virtualScrolling: true, sensitiveByDefault: false, + conversationDisplay: 'tree', // Nasty stuff customEmoji: [], From 0f2fd8a3523e9e2cd1ca6fe287eb7304895f2cba Mon Sep 17 00:00:00 2001 From: Tusooa Zhu Date: Sat, 7 Aug 2021 00:33:06 -0400 Subject: [PATCH 0149/1033] Implement thread folding/expanding --- src/components/conversation/conversation.js | 105 +++++++++++++++++-- src/components/conversation/conversation.vue | 7 ++ src/components/status/status.js | 22 +++- src/components/status/status.vue | 13 +++ src/components/thread_tree/thread_tree.js | 12 ++- src/components/thread_tree/thread_tree.vue | 35 ++++++- 6 files changed, 180 insertions(+), 14 deletions(-) diff --git a/src/components/conversation/conversation.js b/src/components/conversation/conversation.js index e663ba157e..0abb7abd23 100644 --- a/src/components/conversation/conversation.js +++ b/src/components/conversation/conversation.js @@ -38,7 +38,8 @@ const conversation = { data () { return { highlight: null, - expanded: false + expanded: false, + threadDisplayStatusObject: {} // id => 'showing' | 'hidden' } }, props: [ @@ -56,6 +57,9 @@ const conversation = { } }, computed: { + maxDepthToShowByDefault () { + return 4 + }, displayStyle () { return this.$store.state.config.conversationDisplay }, @@ -112,15 +116,14 @@ const conversation = { const id = cur.id a.forest[id] = this.getReplies(id) .map(s => s.id) - .sort((a, b) => reverseLookupTable[a] - reverseLookupTable[b]) - a.topLevel = a.topLevel.filter(k => a.forest[id].contains(k)) return a }, { forest: {}, - topLevel: this.conversation.map(s => s.id) }) + debug('threads = ', threads) + const walk = (forest, topLevel, depth = 0, processed = {}) => topLevel.map(id => { if (processed[id]) { return [] @@ -131,18 +134,63 @@ const conversation = { status: this.conversation[reverseLookupTable[id]], id, depth - }, walk(forest, forest[child], depth + 1, processed)].reduce((a, b) => a.concat(b), []) + }, walk(forest, forest[id], depth + 1, processed)].reduce((a, b) => a.concat(b), []) }).reduce((a, b) => a.concat(b), []) - const linearized = walk(threads.forest, threads.topLevel) + const linearized = walk(threads.forest, this.topLevel.map(k => k.id)) return linearized }, + replyIds () { + return this.conversation.map(k => k.id) + .reduce((res, id) => { + res[id] = (this.replies[id] || []).map(k => k.id) + return res + }, {}) + }, + totalReplyCount () { + debug('replyIds=', this.replyIds) + const sizes = {} + const subTreeSizeFor = (id) => { + if (sizes[id]) { + return sizes[id] + } + sizes[id] = 1 + this.replyIds[id].map(cid => subTreeSizeFor(cid)).reduce((a, b) => a + b, 0) + return sizes[id] + } + this.conversation.map(k => k.id).map(subTreeSizeFor) + debug('totalReplyCount=', sizes) + return Object.keys(sizes).reduce((res, id) => { + res[id] = sizes[id] - 1 // exclude itself + return res + }, {}) + }, + totalReplyDepth () { + const depths = {} + const subTreeDepthFor = (id) => { + if (depths[id]) { + return depths[id] + } + depths[id] = 1 + this.replyIds[id].map(cid => subTreeDepthFor(cid)).reduce((a, b) => a > b ? a : b, 0) + return depths[id] + } + this.conversation.map(k => k.id).map(subTreeDepthFor) + return Object.keys(depths).reduce((res, id) => { + res[id] = depths[id] - 1 // exclude itself + return res + }, {}) + }, + depths () { + debug('threadTree', this.threadTree) + return this.threadTree.reduce((a, k) => { + a[k.id] = k.depth + return a + }, {}) + }, topLevel () { const topLevel = this.conversation.reduce((tl, cur) => tl.filter(k => this.getReplies(cur.id).map(v => v.id).indexOf(k.id) === -1), this.conversation) debug("toplevel =", topLevel) - debug("toplevel =", topLevel) return topLevel }, replies () { @@ -169,6 +217,25 @@ const conversation = { hiddenStyle () { const height = (this.status && this.status.virtualHeight) || '120px' return this.virtualHidden ? { height } : {} + }, + threadDisplayStatus () { + return this.conversation.reduce((a, k) => { + const id = k.id + const depth = this.depths[id] + const status = (() => { + if (this.threadDisplayStatusObject[id]) { + return this.threadDisplayStatusObject[id] + } + if (depth <= this.maxDepthToShowByDefault) { + return 'showing' + } else { + return 'hidden' + } + })() + + a[id] = status + return a + }, {}) } }, components: { @@ -235,6 +302,30 @@ const conversation = { getConversationId (statusId) { const status = this.$store.state.statuses.allStatusesObject[statusId] return get(status, 'retweeted_status.statusnet_conversation_id', get(status, 'statusnet_conversation_id')) + }, + setThreadDisplay (id, nextStatus) { + this.threadDisplayStatusObject = { + ...this.threadDisplayStatusObject, + [id]: nextStatus + } + }, + toggleThreadDisplay (id) { + const depth = this.depths[id] + debug('depth = ', depth) + debug( + 'threadDisplayStatus = ', this.threadDisplayStatus, + 'threadDisplayStatusObject = ', this.threadDisplayStatusObject) + const curStatus = this.threadDisplayStatus[id] + const nextStatus = curStatus === 'showing' ? 'hidden' : 'showing' + debug('toggling', id, 'to', nextStatus) + this.setThreadDisplay(id, nextStatus) + }, + setThreadDisplayRecursively (id, nextStatus) { + this.setThreadDisplay(id, nextStatus) + this.getReplies(id).map(k => k.id).map(id => this.setThreadDisplayRecursively(id, nextStatus)) + }, + showThreadRecursively (id) { + this.setThreadDisplayRecursively(id, 'showing') } } } diff --git a/src/components/conversation/conversation.vue b/src/components/conversation/conversation.vue index cea5f88f08..783cc8941c 100644 --- a/src/components/conversation/conversation.vue +++ b/src/components/conversation/conversation.vue @@ -23,6 +23,7 @@ v-for="status in topLevel" :key="status.id" ref="statusComponent" + :depth="0" :status="status" :in-profile="inProfile" @@ -37,6 +38,12 @@ :get-highlight="getHighlight" :set-highlight="setHighlight" :toggle-expanded="toggleExpanded" + + :toggle-thread-display="toggleThreadDisplay" + :thread-display-status="threadDisplayStatus" + :show-thread-recursively="showThreadRecursively" + :total-reply-count="totalReplyCount" + :total-reply-depth="totalReplyDepth" />
  • diff --git a/src/components/status/status.js b/src/components/status/status.js index d8f94926e5..9d423631a0 100644 --- a/src/components/status/status.js +++ b/src/components/status/status.js @@ -35,7 +35,9 @@ import { faStar, faEyeSlash, faEye, - faThumbtack + faThumbtack, + faAngleDoubleUp, + faAngleDoubleDown } from '@fortawesome/free-solid-svg-icons' library.add( @@ -52,7 +54,9 @@ library.add( faEllipsisH, faEyeSlash, faEye, - faThumbtack + faThumbtack, + faAngleDoubleUp, + faAngleDoubleDown ) const Status = { @@ -89,7 +93,10 @@ const Status = { 'inlineExpanded', 'showPinned', 'inProfile', - 'profileUserId' + 'profileUserId', + + 'controlledThreadDisplayStatus', + 'controlledToggleThreadDisplay' ], data () { return { @@ -304,6 +311,12 @@ const Status = { }, isSuspendable () { return !this.replying && this.mediaPlaying.length === 0 + }, + inThreadForest () { + return !!this.controlledThreadDisplayStatus + }, + threadShowing () { + return this.controlledThreadDisplayStatus === 'showing' } }, methods: { @@ -353,6 +366,9 @@ const Status = { }, setHeadTailLinks (headTailLinks) { this.headTailLinks = headTailLinks + }, + toggleThreadDisplay () { + this.controlledToggleThreadDisplay() } }, watch: { diff --git a/src/components/status/status.vue b/src/components/status/status.vue index 3bb29db665..2ebf56385f 100644 --- a/src/components/status/status.vue +++ b/src/components/status/status.vue @@ -219,6 +219,19 @@ class="fa-scale-110" /> +
    this.statusById(id)) }, + threadShowing () { + return this.threadDisplayStatus[this.status.id] === 'showing' + } }, methods: { statusById (id) { diff --git a/src/components/thread_tree/thread_tree.vue b/src/components/thread_tree/thread_tree.vue index 8256eee6c3..9f59158511 100644 --- a/src/components/thread_tree/thread_tree.vue +++ b/src/components/thread_tree/thread_tree.vue @@ -13,18 +13,23 @@ :replies="getReplies(status.id)" :in-profile="inProfile" :profile-user-id="profileUserId" - class="conversation-status status-fadein panel-body" + class="conversation-status conversation-status-treeview status-fadein panel-body" + + :controlled-thread-display-status="threadDisplayStatus[status.id]" + :controlled-toggle-thread-display="() => toggleThreadDisplay(status.id)" + @goto="setHighlight" @toggleExpanded="toggleExpanded" />
    +
    + +
    From 414ee55957851a30b9455e47e1e6d258743953a3 Mon Sep 17 00:00:00 2001 From: Tusooa Zhu Date: Sat, 7 Aug 2021 01:05:26 -0400 Subject: [PATCH 0150/1033] Make show full thread message account for numbers --- src/components/thread_tree/thread_tree.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/thread_tree/thread_tree.vue b/src/components/thread_tree/thread_tree.vue index 9f59158511..bbdda6fbf1 100644 --- a/src/components/thread_tree/thread_tree.vue +++ b/src/components/thread_tree/thread_tree.vue @@ -60,7 +60,7 @@ class="button-unstyled -link thread-tree-show-replies-button" @click="showThreadRecursively(status.id)" > - {{ $t('status.thread_show_full', { numStatus: totalReplyCount[status.id], depth: totalReplyDepth[status.id] }) }} + {{ $tc('status.thread_show_full', totalReplyCount[status.id], { numStatus: totalReplyCount[status.id], depth: totalReplyDepth[status.id] }) }}
    From cd0f6a4f7820b27e3d776e598c842328ad64ab18 Mon Sep 17 00:00:00 2001 From: Tusooa Zhu Date: Sat, 7 Aug 2021 01:06:16 -0400 Subject: [PATCH 0151/1033] Add English translations for message threading --- src/i18n/en.json | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/i18n/en.json b/src/i18n/en.json index 8eb7fcc6ea..6be2d9aa08 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -465,6 +465,9 @@ "subject_line_email": "Like email: \"re: subject\"", "subject_line_mastodon": "Like mastodon: copy as is", "subject_line_noop": "Do not copy", + "conversation_display": "Conversation display style", + "conversation_display_tree": "Tree-style", + "conversation_display_linear": "Linear-style", "post_status_content_type": "Post status content type", "sensitive_by_default": "Mark posts as sensitive by default", "stop_gifs": "Pause animated images until you hover on them", @@ -747,7 +750,10 @@ "attachment_stop_flash": "Stop Flash player", "move_up": "Shift attachment left", "move_down": "Shift attachment right", - "open_gallery": "Open gallery" + "open_gallery": "Open gallery", + "thread_hide": "Hide this thread", + "thread_show": "Show this thread", + "thread_show_full": "Show everything under this thread ({numStatus} status in total, max depth {depth}) | Show everything under this thread ({numStatus} statuses in total, max depth {depth})" }, "user_card": { "approve": "Approve", From ace1f5067c90be2fa0b8da22d39b0e2c88f590fb Mon Sep 17 00:00:00 2001 From: Tusooa Zhu Date: Sat, 7 Aug 2021 10:28:45 -0400 Subject: [PATCH 0152/1033] Make status display controlled --- src/components/conversation/conversation.js | 37 +++++++++++- src/components/conversation/conversation.vue | 3 + src/components/status/status.js | 9 ++- src/components/status/status.vue | 6 ++ .../status_content/status_content.js | 59 ++++++++++++++++++- src/components/thread_tree/thread_tree.js | 11 +++- src/components/thread_tree/thread_tree.vue | 10 ++++ 7 files changed, 130 insertions(+), 5 deletions(-) diff --git a/src/components/conversation/conversation.js b/src/components/conversation/conversation.js index 0abb7abd23..6fc86b2c24 100644 --- a/src/components/conversation/conversation.js +++ b/src/components/conversation/conversation.js @@ -2,7 +2,8 @@ import { reduce, filter, findIndex, clone, get } from 'lodash' import Status from '../status/status.vue' import ThreadTree from '../thread_tree/thread_tree.vue' -const debug = console.log +// const debug = console.log +const debug = () => {} const sortById = (a, b) => { const idA = a.type === 'retweet' ? a.retweeted_status.id : a.id @@ -39,7 +40,8 @@ const conversation = { return { highlight: null, expanded: false, - threadDisplayStatusObject: {} // id => 'showing' | 'hidden' + threadDisplayStatusObject: {}, // id => 'showing' | 'hidden' + statusContentPropertiesObject: {} } }, props: [ @@ -236,6 +238,25 @@ const conversation = { a[id] = status return a }, {}) + }, + statusContentProperties () { + return this.conversation.reduce((a, k) => { + const id = k.id + const depth = this.depths[id] + const props = (() => { + if (this.statusContentPropertiesObject[id]) { + return this.statusContentPropertiesObject[id] + } + return { + showingTall: false, + expandingSubject: false, + showingLongSubject: false, + } + })() + + a[id] = props + return a + }, {}) } }, components: { @@ -326,6 +347,18 @@ const conversation = { }, showThreadRecursively (id) { this.setThreadDisplayRecursively(id, 'showing') + }, + setStatusContentProperty (id, name, value) { + this.statusContentPropertiesObject = { + ...this.statusContentPropertiesObject, + [id]: { + ...this.statusContentPropertiesObject[id], + [name]: value + } + } + }, + toggleStatusContentProperty (id, name) { + this.setStatusContentProperty(id, name, !this.statusContentProperties[id][name]) } } } diff --git a/src/components/conversation/conversation.vue b/src/components/conversation/conversation.vue index 783cc8941c..08cb72d042 100644 --- a/src/components/conversation/conversation.vue +++ b/src/components/conversation/conversation.vue @@ -44,6 +44,9 @@ :show-thread-recursively="showThreadRecursively" :total-reply-count="totalReplyCount" :total-reply-depth="totalReplyDepth" + :status-content-properties="statusContentProperties" + :set-status-content-property="setStatusContentProperty" + :toggle-status-content-property="toggleStatusContentProperty" />
    diff --git a/src/components/status/status.js b/src/components/status/status.js index 9d423631a0..d5ee7d4e8b 100644 --- a/src/components/status/status.js +++ b/src/components/status/status.js @@ -96,7 +96,14 @@ const Status = { 'profileUserId', 'controlledThreadDisplayStatus', - 'controlledToggleThreadDisplay' + 'controlledToggleThreadDisplay', + + 'controlledShowingTall', + 'controlledToggleShowingTall', + 'controlledExpandingSubject', + 'controlledToggleExpandingSubject', + 'controlledShowingLongSubject', + 'controlledToggleShowingLongSubject' ], data () { return { diff --git a/src/components/status/status.vue b/src/components/status/status.vue index 2ebf56385f..8fdebe44be 100644 --- a/src/components/status/status.vue +++ b/src/components/status/status.vue @@ -319,6 +319,12 @@ :no-heading="noHeading" :highlight="highlight" :focused="isFocused" + :controlled-showing-tall="controlledShowingTall" + :controlled-expanding-subject="controlledExpandingSubject" + :controlled-showing-long-subject="controlledShowingLongSubject" + :controlled-toggle-showing-tall="controlledToggleShowingTall" + :controlled-toggle-expanding-subject="controlledToggleExpandingSubject" + :controlled-toggle-showing-long-subject="controlledToggleShowingLongSubject" @mediaplay="addMediaPlaying($event)" @mediapause="removeMediaPlaying($event)" @parseReady="setHeadTailLinks" diff --git a/src/components/status_content/status_content.js b/src/components/status_content/status_content.js index dec8914a32..65ec85c4a0 100644 --- a/src/components/status_content/status_content.js +++ b/src/components/status_content/status_content.js @@ -23,6 +23,31 @@ library.add( faPollH ) +const camelCase = name => name.charAt(0).toUpperCase() + name.slice(1) + +const controlledOrUncontrolledGetters = list => list.reduce((res, name) => { + const camelized = camelCase(name) + const toggle = `controlledToggle${camelized}` + const controlledName = `controlled${camelized}` + const uncontrolledName = `uncontrolled${camelized}` + res[name] = function () { + return this[toggle] ? this[controlledName] : this[uncontrolledName] + } + return res +}, {}) + +const controlledOrUncontrolledToggle = (obj, name) => { + const camelized = camelCase(name) + const toggle = `controlledToggle${camelized}` + const controlledName = `controlled${camelized}` + const uncontrolledName = `uncontrolled${camelized}` + if (obj[toggle]) { + obj[toggle]() + } else { + obj[uncontrolledName] = !obj[uncontrolledName] + } +} + const StatusContent = { name: 'StatusContent', props: [ @@ -31,9 +56,22 @@ const StatusContent = { 'focused', 'noHeading', 'fullContent', - 'singleLine' + 'singleLine', + 'controlledShowingTall', + 'controlledExpandingSubject', + 'controlledToggleShowingTall', + 'controlledToggleExpandingSubject' ], + data () { + return { + uncontrolledShowingTall: this.fullContent || (this.inConversation && this.focused), + uncontrolledShowingLongSubject: false, + // not as computed because it sets the initial state which will be changed later + uncontrolledExpandingSubject: !this.$store.getters.mergedConfig.collapseMessageWithSubject + } + }, computed: { + ...controlledOrUncontrolledGetters(['showingTall', 'expandingSubject', 'showingLongSubject']), hideAttachments () { return (this.mergedConfig.hideAttachments && !this.inConversation) || (this.mergedConfig.hideAttachmentsInConv && this.inConversation) @@ -71,6 +109,25 @@ const StatusContent = { Gallery, LinkPreview, StatusBody + }, + methods: { + toggleShowingTall () { + controlledOrUncontrolledToggle(this, 'showingTall') + }, + toggleExpandingSubject () { + controlledOrUncontrolledToggle(this, 'expandingSubject') + }, + toggleShowMore () { + if (this.mightHideBecauseTall) { + this.toggleShowingTall() + } else if (this.mightHideBecauseSubject) { + this.toggleExpandingSubject() + } + }, + setMedia () { + const attachments = this.attachmentSize === 'hide' ? this.status.attachments : this.galleryAttachments + return () => this.$store.dispatch('setMedia', attachments) + } } } diff --git a/src/components/thread_tree/thread_tree.js b/src/components/thread_tree/thread_tree.js index 88b6010972..46245bdfc0 100644 --- a/src/components/thread_tree/thread_tree.js +++ b/src/components/thread_tree/thread_tree.js @@ -28,7 +28,10 @@ const ThreadTree = { threadDisplayStatus: Object, showThreadRecursively: Function, totalReplyCount: Object, - totalReplyDepth: Object + totalReplyDepth: Object, + statusContentProperties: Object, + setStatusContentProperty: Function, + toggleStatusContentProperty: Function }, computed: { reverseLookupTable () { @@ -44,6 +47,9 @@ const ThreadTree = { }, threadShowing () { return this.threadDisplayStatus[this.status.id] === 'showing' + }, + currentProp () { + return this.statusContentProperties[this.status.id] } }, methods: { @@ -55,6 +61,9 @@ const ThreadTree = { showThread () { }, showAllSubthreads () { + }, + toggleCurrentProp (name) { + this.toggleStatusContentProperty(this.status.id, name) } } } diff --git a/src/components/thread_tree/thread_tree.vue b/src/components/thread_tree/thread_tree.vue index bbdda6fbf1..d7077bfded 100644 --- a/src/components/thread_tree/thread_tree.vue +++ b/src/components/thread_tree/thread_tree.vue @@ -18,6 +18,13 @@ :controlled-thread-display-status="threadDisplayStatus[status.id]" :controlled-toggle-thread-display="() => toggleThreadDisplay(status.id)" + :controlled-showing-tall="currentProp.showingTall" + :controlled-expanding-subject="currentProp.expandingSubject" + :controlled-showing-long-subject="currentProp.showingLongSubject" + :controlled-toggle-showing-tall="() => toggleCurrentProp('ShowingTall')" + :controlled-toggle-expanding-subject="() => toggleCurrentProp('expandingSubject')" + :controlled-toggle-showing-long-subject="() => toggleCurrentProp('showingLongSubject')" + @goto="setHighlight" @toggleExpanded="toggleExpanded" /> @@ -50,6 +57,9 @@ :show-thread-recursively="showThreadRecursively" :total-reply-count="totalReplyCount" :total-reply-depth="totalReplyDepth" + :status-content-properties="statusContentProperties" + :set-status-content-property="setStatusContentProperty" + :toggle-status-content-property="toggleStatusContentProperty" />
    Date: Sat, 7 Aug 2021 11:59:10 -0400 Subject: [PATCH 0153/1033] Support diving into one status in a conversation --- src/components/conversation/conversation.js | 32 +++++++++++++++++++- src/components/conversation/conversation.vue | 30 +++++++++++++++++- src/components/status/status.js | 13 +++++--- src/components/status/status.vue | 14 ++++++++- src/components/thread_tree/thread_tree.js | 3 +- src/components/thread_tree/thread_tree.vue | 15 ++++++--- 6 files changed, 94 insertions(+), 13 deletions(-) diff --git a/src/components/conversation/conversation.js b/src/components/conversation/conversation.js index 6fc86b2c24..584f310ce3 100644 --- a/src/components/conversation/conversation.js +++ b/src/components/conversation/conversation.js @@ -2,6 +2,17 @@ import { reduce, filter, findIndex, clone, get } from 'lodash' import Status from '../status/status.vue' import ThreadTree from '../thread_tree/thread_tree.vue' +import { library } from '@fortawesome/fontawesome-svg-core' +import { + faAngleDoubleDown, + faAngleDoubleLeft +} from '@fortawesome/free-solid-svg-icons' + +library.add( + faAngleDoubleDown, + faAngleDoubleLeft +) + // const debug = console.log const debug = () => {} @@ -41,7 +52,8 @@ const conversation = { highlight: null, expanded: false, threadDisplayStatusObject: {}, // id => 'showing' | 'hidden' - statusContentPropertiesObject: {} + statusContentPropertiesObject: {}, + diveRoot: null } }, props: [ @@ -195,6 +207,18 @@ const conversation = { debug("toplevel =", topLevel) return topLevel }, + showingTopLevel () { + if (this.diveRoot) { + return [this.conversation.filter(k => this.diveRoot === k.id)[0]] + } + return this.topLevel + }, + diveDepth () { + return this.diveRoot ? this.depths[this.diveRoot] : 0 + }, + diveMode () { + return !!this.diveRoot + }, replies () { let i = 1 // eslint-disable-next-line camelcase @@ -359,6 +383,12 @@ const conversation = { }, toggleStatusContentProperty (id, name) { this.setStatusContentProperty(id, name, !this.statusContentProperties[id][name]) + }, + diveIntoStatus (id) { + this.diveRoot = id + }, + undive () { + this.diveRoot = null } } } diff --git a/src/components/conversation/conversation.vue b/src/components/conversation/conversation.vue index 08cb72d042..84e8d8b2ad 100644 --- a/src/components/conversation/conversation.vue +++ b/src/components/conversation/conversation.vue @@ -18,9 +18,22 @@ {{ $t('timeline.collapse') }}
    +
    + + + +
    @@ -65,6 +79,16 @@ :in-profile="inProfile" :profile-user-id="profileUserId" class="conversation-status status-fadein panel-body" + + :toggle-thread-display="toggleThreadDisplay" + :thread-display-status="threadDisplayStatus" + :show-thread-recursively="showThreadRecursively" + :total-reply-count="totalReplyCount" + :total-reply-depth="totalReplyDepth" + :status-content-properties="statusContentProperties" + :set-status-content-property="setStatusContentProperty" + :toggle-status-content-property="toggleStatusContentProperty" + @goto="setHighlight" @toggleExpanded="toggleExpanded" /> @@ -82,6 +106,10 @@ @import '../../_variables.scss'; .Conversation { + .conversation-undive-box { + padding: 1em; + } + .conversation-undive-box, .conversation-status { border-bottom-width: 1px; border-bottom-style: solid; diff --git a/src/components/status/status.js b/src/components/status/status.js index d5ee7d4e8b..f119f42e55 100644 --- a/src/components/status/status.js +++ b/src/components/status/status.js @@ -36,8 +36,9 @@ import { faEyeSlash, faEye, faThumbtack, - faAngleDoubleUp, - faAngleDoubleDown + faChevronUp, + faChevronDown, + faAngleDoubleRight } from '@fortawesome/free-solid-svg-icons' library.add( @@ -55,8 +56,9 @@ library.add( faEyeSlash, faEye, faThumbtack, - faAngleDoubleUp, - faAngleDoubleDown + faChevronUp, + faChevronDown, + faAngleDoubleRight ) const Status = { @@ -103,7 +105,8 @@ const Status = { 'controlledExpandingSubject', 'controlledToggleExpandingSubject', 'controlledShowingLongSubject', - 'controlledToggleShowingLongSubject' + 'controlledToggleShowingLongSubject', + 'dive' ], data () { return { diff --git a/src/components/status/status.vue b/src/components/status/status.vue index 8fdebe44be..c2df602187 100644 --- a/src/components/status/status.vue +++ b/src/components/status/status.vue @@ -229,7 +229,19 @@ + + diff --git a/src/components/thread_tree/thread_tree.js b/src/components/thread_tree/thread_tree.js index 46245bdfc0..3e8eedb143 100644 --- a/src/components/thread_tree/thread_tree.js +++ b/src/components/thread_tree/thread_tree.js @@ -31,7 +31,8 @@ const ThreadTree = { totalReplyDepth: Object, statusContentProperties: Object, setStatusContentProperty: Function, - toggleStatusContentProperty: Function + toggleStatusContentProperty: Function, + dive: Function }, computed: { reverseLookupTable () { diff --git a/src/components/thread_tree/thread_tree.vue b/src/components/thread_tree/thread_tree.vue index d7077bfded..adf7bcdf74 100644 --- a/src/components/thread_tree/thread_tree.vue +++ b/src/components/thread_tree/thread_tree.vue @@ -24,6 +24,7 @@ :controlled-toggle-showing-tall="() => toggleCurrentProp('ShowingTall')" :controlled-toggle-expanding-subject="() => toggleCurrentProp('expandingSubject')" :controlled-toggle-showing-long-subject="() => toggleCurrentProp('showingLongSubject')" + :dive="dive ? () => dive(status.id) : undefined" @goto="setHighlight" @toggleExpanded="toggleExpanded" @@ -60,18 +61,24 @@ :status-content-properties="statusContentProperties" :set-status-content-property="setStatusContentProperty" :toggle-status-content-property="toggleStatusContentProperty" + :dive="dive" />
    - + + + {{ $tc('status.thread_show_full', totalReplyCount[status.id], { numStatus: totalReplyCount[status.id], depth: totalReplyDepth[status.id] }) }} + +
    From 31c4300456192582786a7f5da420f7ce834a3e2b Mon Sep 17 00:00:00 2001 From: Tusooa Zhu Date: Sat, 7 Aug 2021 11:59:41 -0400 Subject: [PATCH 0154/1033] Add English translations for diving --- src/i18n/en.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/i18n/en.json b/src/i18n/en.json index 6be2d9aa08..7f92e95a32 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -753,7 +753,10 @@ "open_gallery": "Open gallery", "thread_hide": "Hide this thread", "thread_show": "Show this thread", - "thread_show_full": "Show everything under this thread ({numStatus} status in total, max depth {depth}) | Show everything under this thread ({numStatus} statuses in total, max depth {depth})" + "thread_show_full": "Show everything under this thread ({numStatus} status in total, max depth {depth}) | Show everything under this thread ({numStatus} statuses in total, max depth {depth})", + "thread_show_full_with_icon": "{icon} {text}", + "show_all_conversation": "{0} Show full conversation", + "show_only_conversation_under_this": "Only show replies to this status" }, "user_card": { "approve": "Approve", From d15d24c11c57ecfc49705af648b1e8f73caec51e Mon Sep 17 00:00:00 2001 From: Tusooa Zhu Date: Sat, 7 Aug 2021 14:11:34 -0400 Subject: [PATCH 0155/1033] Add dive functionality --- src/components/conversation/conversation.js | 69 +++++++++++++++++--- src/components/conversation/conversation.vue | 15 ++++- src/components/status/status.vue | 2 +- src/components/thread_tree/thread_tree.js | 3 +- src/components/thread_tree/thread_tree.vue | 5 +- 5 files changed, 80 insertions(+), 14 deletions(-) diff --git a/src/components/conversation/conversation.js b/src/components/conversation/conversation.js index 584f310ce3..b2af1d6cb4 100644 --- a/src/components/conversation/conversation.js +++ b/src/components/conversation/conversation.js @@ -5,12 +5,14 @@ import ThreadTree from '../thread_tree/thread_tree.vue' import { library } from '@fortawesome/fontawesome-svg-core' import { faAngleDoubleDown, - faAngleDoubleLeft + faAngleDoubleLeft, + faChevronLeft } from '@fortawesome/free-solid-svg-icons' library.add( faAngleDoubleDown, - faAngleDoubleLeft + faAngleDoubleLeft, + faChevronLeft ) // const debug = console.log @@ -53,7 +55,7 @@ const conversation = { expanded: false, threadDisplayStatusObject: {}, // id => 'showing' | 'hidden' statusContentPropertiesObject: {}, - diveRoot: null + diveHistory: [] } }, props: [ @@ -120,6 +122,14 @@ const conversation = { return sortAndFilterConversation(conversation, this.status) }, + conversationDive () { + }, + statusMap () { + return this.conversation.reduce((res, s) => { + res[s.id] = s + return res + }, {}) + }, threadTree () { const reverseLookupTable = this.conversation.reduce((table, status, index) => { table[status.id] = index @@ -208,16 +218,19 @@ const conversation = { return topLevel }, showingTopLevel () { - if (this.diveRoot) { - return [this.conversation.filter(k => this.diveRoot === k.id)[0]] + if (this.canDive && this.diveRoot) { + return [this.statusMap[this.diveRoot]] } return this.topLevel }, + diveRoot () { + return this.diveHistory[this.diveHistory.length - 1] + }, diveDepth () { - return this.diveRoot ? this.depths[this.diveRoot] : 0 + return this.canDive && this.diveRoot ? this.depths[this.diveRoot] : 0 }, diveMode () { - return !!this.diveRoot + return this.canDive && !!this.diveRoot }, replies () { let i = 1 @@ -252,7 +265,7 @@ const conversation = { if (this.threadDisplayStatusObject[id]) { return this.threadDisplayStatusObject[id] } - if (depth <= this.maxDepthToShowByDefault) { + if ((depth - this.diveDepth) <= this.maxDepthToShowByDefault) { return 'showing' } else { return 'hidden' @@ -281,6 +294,9 @@ const conversation = { a[id] = props return a }, {}) + }, + canDive () { + return this.isTreeView && this.isExpanded } }, components: { @@ -310,6 +326,25 @@ const conversation = { } }, methods: { + conversationFetched () { + if (!this.isExpanded) { + return + } + + if (!this._diven) { + if (!this.threadDisplayStatus[this.statusId]) { + return + } + this._diven = true + const parentOrSelf = this.parentOrSelf(this.originalStatusId) + console.log( + 'this.threadDisplayStatus ', this.threadDisplayStatus, + 'this.statusId', this.statusId) + if (this.threadDisplayStatus[this.statusId] === 'hidden') { + this.diveIntoStatus(parentOrSelf) + } + } + }, fetchConversation () { if (this.status) { this.$store.state.api.backendInteractor.fetchConversation({ id: this.statusId }) @@ -318,6 +353,7 @@ const conversation = { this.$store.dispatch('addNewStatuses', { statuses: descendants }) this.setHighlight(this.originalStatusId) }) + .then(this.conversationFetched) } else { this.$store.state.api.backendInteractor.fetchStatus({ id: this.statusId }) .then((status) => { @@ -385,10 +421,23 @@ const conversation = { this.setStatusContentProperty(id, name, !this.statusContentProperties[id][name]) }, diveIntoStatus (id) { - this.diveRoot = id + this.diveHistory = [...this.diveHistory, id] + }, + diveBack () { + this.diveHistory = [...this.diveHistory.slice(0, this.diveHistory.length - 1)] }, undive () { - this.diveRoot = null + this.diveHistory = [] + }, + statusById (id) { + return this.statusMap[id] + }, + parentOf (id) { + const { in_reply_to_status_id: parentId } = this.statusById(id) + return parentId + }, + parentOrSelf (id) { + return this.parentOf(id) || id } } } diff --git a/src/components/conversation/conversation.vue b/src/components/conversation/conversation.vue index 84e8d8b2ad..99bc7bccbb 100644 --- a/src/components/conversation/conversation.vue +++ b/src/components/conversation/conversation.vue @@ -31,6 +31,19 @@ +
    + + + +
    diff --git a/src/components/status/status.vue b/src/components/status/status.vue index c2df602187..47d35de84c 100644 --- a/src/components/status/status.vue +++ b/src/components/status/status.vue @@ -220,7 +220,7 @@ />
    -
    - +
    - - -
    -
    - + + +
    +
    - - -
    -
    - + + +
    +
    + -
    -
    - +
    +
    + + @goto="setHighlight" + @toggleExpanded="toggleExpanded" + /> +
    .conversation-status { + border-top-left-radius: $fallback--panelRadius; + border-top-left-radius: var(--panelRadius, $fallback--panelRadius); + } + + /* first element in conversation body */ + &.-expanded .conversation-body { + .conversation-undive-box:nth-child(1), + & > .conversation-status:nth-child(1), + & > .thread-body:nth-child(1) > .thread-tree:nth-child(1) > .conversation-status:nth-child(1), { + border-top: none; + } + } + + /* first unexpanded statuses in timeline */ + &:first-child:not(.-expanded) { + .conversation-body { + .conversation-status { + border-top: none; + } + } + } + + /* expanded conversation in timeline */ + &.status-fadein.-expanded .thread-body { + border-left-width: 4px; + border-left-style: solid; + border-left-color: $fallback--cRed; + border-left-color: var(--cRed, $fallback--cRed); + border-radius: 0 0 $fallback--panelRadius $fallback--panelRadius; + border-radius: 0 0 var(--panelRadius, $fallback--panelRadius) var(--panelRadius, $fallback--panelRadius); + border-bottom: 1px solid var(--border, $fallback--border); + } &.-expanded { .conversation-status:last-child { border-bottom: none; - border-radius: 0 0 $fallback--panelRadius $fallback--panelRadius; - border-radius: 0 0 var(--panelRadius, $fallback--panelRadius) var(--panelRadius, $fallback--panelRadius); } } } diff --git a/src/components/status/status.scss b/src/components/status/status.scss index 2028ade9e0..80bc392da2 100644 --- a/src/components/status/status.scss +++ b/src/components/status/status.scss @@ -1,7 +1,5 @@ @import '../../_variables.scss'; -$status-margin: 0.75em; - .Status { min-width: 0; white-space: normal; @@ -28,13 +26,6 @@ $status-margin: 0.75em; --icon: var(--selectedPostIcon, $fallback--icon); } - &.-conversation { - border-left-width: 4px; - border-left-style: solid; - border-left-color: $fallback--cRed; - border-left-color: var(--cRed, $fallback--cRed); - } - .gravestone { padding: $status-margin; color: $fallback--faint; diff --git a/src/components/thread_tree/thread_tree.vue b/src/components/thread_tree/thread_tree.vue index fa1e5f8620..aafad66ea7 100644 --- a/src/components/thread_tree/thread_tree.vue +++ b/src/components/thread_tree/thread_tree.vue @@ -109,14 +109,16 @@ From 8780246ce5566e60520354f5a3de92eacd059f61 Mon Sep 17 00:00:00 2001 From: Tusooa Zhu Date: Sun, 8 Aug 2021 12:55:04 -0400 Subject: [PATCH 0169/1033] Optimize thread border radius --- src/components/conversation/conversation.vue | 12 +++++++++--- src/components/thread_tree/thread_tree.vue | 3 +-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/components/conversation/conversation.vue b/src/components/conversation/conversation.vue index cd108f695f..11b5b3d817 100644 --- a/src/components/conversation/conversation.vue +++ b/src/components/conversation/conversation.vue @@ -130,10 +130,13 @@ .Conversation { .conversation-undive-box { padding: $status-margin; + border-bottom-width: 1px; + border-bottom-style: solid; + border-bottom-color: var(--border, $fallback--border); + border-radius: 0; } /* HACK: we want the border width to scale with the status *below it* */ - .conversation-undive-box, .conversation-status { border-top-width: 1px; border-top-style: solid; @@ -146,11 +149,14 @@ border-top-left-radius: var(--panelRadius, $fallback--panelRadius); } - /* first element in conversation body */ + /* first element in a reply tree, the border is supplied by reply tree instead + for radius to display properly + */ &.-expanded .conversation-body { .conversation-undive-box:nth-child(1), & > .conversation-status:nth-child(1), - & > .thread-body:nth-child(1) > .thread-tree:nth-child(1) > .conversation-status:nth-child(1), { + & > .thread-body:nth-child(1) > .thread-tree:nth-child(1) > .conversation-status:nth-child(1), + .thread-tree:nth-child(1) > .conversation-status:nth-child(1) { border-top: none; } } diff --git a/src/components/thread_tree/thread_tree.vue b/src/components/thread_tree/thread_tree.vue index aafad66ea7..79ba0cc55d 100644 --- a/src/components/thread_tree/thread_tree.vue +++ b/src/components/thread_tree/thread_tree.vue @@ -111,10 +111,9 @@ .thread-tree-replies { margin-left: $status-margin; border-left: 1px solid var(--border, $fallback--border); + border-top: 1px solid var(--border, $fallback--border); border-top-left-radius: $fallback--panelRadius; border-top-left-radius: var(--panelRadius, $fallback--panelRadius); - border-bottom-left-radius: $fallback--panelRadius; - border-bottom-left-radius: var(--panelRadius, $fallback--panelRadius); } .thread-tree-replies-hidden { From 0e4a7c3d05333d1e3c86b26b4d6b7cd296ff2582 Mon Sep 17 00:00:00 2001 From: Tusooa Zhu Date: Sun, 8 Aug 2021 13:29:49 -0400 Subject: [PATCH 0170/1033] Make dive/undive button clickable along the whole row --- src/components/conversation/conversation.vue | 4 ++++ src/components/thread_tree/thread_tree.vue | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/components/conversation/conversation.vue b/src/components/conversation/conversation.vue index 11b5b3d817..86a227ce96 100644 --- a/src/components/conversation/conversation.vue +++ b/src/components/conversation/conversation.vue @@ -134,6 +134,10 @@ border-bottom-style: solid; border-bottom-color: var(--border, $fallback--border); border-radius: 0; + /* Make the button stretch along the whole row */ + display: flex; + align-items: stretch; + flex-direction: column; } /* HACK: we want the border width to scale with the status *below it* */ diff --git a/src/components/thread_tree/thread_tree.vue b/src/components/thread_tree/thread_tree.vue index 79ba0cc55d..46d65101db 100644 --- a/src/components/thread_tree/thread_tree.vue +++ b/src/components/thread_tree/thread_tree.vue @@ -119,5 +119,9 @@ .thread-tree-replies-hidden { padding: $status-margin; border-top: 1px solid var(--border, $fallback--border); + /* Make the button stretch along the whole row */ + display: flex; + align-items: stretch; + flex-direction: column; } From 4adffb483579108c0bfe7593157e9bed3571903f Mon Sep 17 00:00:00 2001 From: Tusooa Zhu Date: Tue, 10 Aug 2021 21:28:13 -0400 Subject: [PATCH 0171/1033] Remove horizontal border and thicken vertical border in a thread tree --- src/components/conversation/conversation.vue | 32 +++----------------- src/components/thread_tree/thread_tree.vue | 7 ++--- 2 files changed, 7 insertions(+), 32 deletions(-) diff --git a/src/components/conversation/conversation.vue b/src/components/conversation/conversation.vue index 86a227ce96..c866b98302 100644 --- a/src/components/conversation/conversation.vue +++ b/src/components/conversation/conversation.vue @@ -142,36 +142,14 @@ /* HACK: we want the border width to scale with the status *below it* */ .conversation-status { - border-top-width: 1px; - border-top-style: solid; - border-top-color: var(--border, $fallback--border); + border-bottom-width: 1px; + border-bottom-style: solid; + border-bottom-color: var(--border, $fallback--border); border-radius: 0; } - &.-expanded .conversation-body .thread-tree:nth-child(1) > .conversation-status { - border-top-left-radius: $fallback--panelRadius; - border-top-left-radius: var(--panelRadius, $fallback--panelRadius); - } - - /* first element in a reply tree, the border is supplied by reply tree instead - for radius to display properly - */ - &.-expanded .conversation-body { - .conversation-undive-box:nth-child(1), - & > .conversation-status:nth-child(1), - & > .thread-body:nth-child(1) > .thread-tree:nth-child(1) > .conversation-status:nth-child(1), - .thread-tree:nth-child(1) > .conversation-status:nth-child(1) { - border-top: none; - } - } - - /* first unexpanded statuses in timeline */ - &:first-child:not(.-expanded) { - .conversation-body { - .conversation-status { - border-top: none; - } - } + &.-expanded .thread-tree .conversation-status { + border-bottom: none; } /* expanded conversation in timeline */ diff --git a/src/components/thread_tree/thread_tree.vue b/src/components/thread_tree/thread_tree.vue index 46d65101db..dce03f27a0 100644 --- a/src/components/thread_tree/thread_tree.vue +++ b/src/components/thread_tree/thread_tree.vue @@ -110,15 +110,12 @@ @import '../../_variables.scss'; .thread-tree-replies { margin-left: $status-margin; - border-left: 1px solid var(--border, $fallback--border); - border-top: 1px solid var(--border, $fallback--border); - border-top-left-radius: $fallback--panelRadius; - border-top-left-radius: var(--panelRadius, $fallback--panelRadius); + border-left: 2px solid var(--border, $fallback--border); } .thread-tree-replies-hidden { padding: $status-margin; - border-top: 1px solid var(--border, $fallback--border); + //border-top: 1px solid var(--border, $fallback--border); /* Make the button stretch along the whole row */ display: flex; align-items: stretch; From e560fbc9352f9f8754451f38c5e3ecef6da96686 Mon Sep 17 00:00:00 2001 From: Tusooa Zhu Date: Tue, 10 Aug 2021 23:58:27 -0400 Subject: [PATCH 0172/1033] Implement Misskey-style tree view Now the tree will be always rooted at the highlighted status, and all its ancestors shown linearly on the top. Enhancement: If an ancestor has more than one reply (i.e. it has a child that is not on current status's ancestor chain), we are given a link to root the thread at that status. --- src/components/conversation/conversation.js | 61 +++++----- src/components/conversation/conversation.vue | 118 +++++++++++++++---- 2 files changed, 124 insertions(+), 55 deletions(-) diff --git a/src/components/conversation/conversation.js b/src/components/conversation/conversation.js index bd8315b89f..817b9bda7d 100644 --- a/src/components/conversation/conversation.js +++ b/src/components/conversation/conversation.js @@ -55,7 +55,7 @@ const conversation = { expanded: false, threadDisplayStatusObject: {}, // id => 'showing' | 'hidden' statusContentPropertiesObject: {}, - diveHistory: [] + inlineDivePosition: null } }, props: [ @@ -231,7 +231,10 @@ const conversation = { return this.topLevel }, diveRoot () { - return this.diveHistory[this.diveHistory.length - 1] + (() => {})(this.conversation) + const statusId = this.inlineDivePosition || this.statusId + const isTopLevel = !this.parentOf(statusId) + return isTopLevel ? null : statusId }, diveDepth () { return this.canDive && this.diveRoot ? this.depths[this.diveRoot] : 0 @@ -332,7 +335,6 @@ const conversation = { this.fetchConversation() } else { // if we collapse it, we should reset the dive - this._diven = false this.undive() } }, @@ -348,19 +350,6 @@ const conversation = { if (!this.isExpanded) { return } - - if (!this._diven) { - if (!this.threadDisplayStatus[this.statusId]) { - return - } - this._diven = true - const parentOrSelf = this.parentOrSelf(this.originalStatusId) - // If current status is not visible - if (this.threadDisplayStatus[parentOrSelf] === 'hidden') { - this.diveIntoStatus(parentOrSelf, /* preventScroll */ true) - this.tryScrollTo(this.statusId) - } - } }, fetchConversation () { if (this.status) { @@ -449,26 +438,15 @@ const conversation = { return this.topLevel[0] ? this.topLevel[0].id : undefined }, diveIntoStatus (id, preventScroll) { - this.diveHistory = [...this.diveHistory, id] - if (!preventScroll) { - this.goToCurrent() - } + this.tryScrollTo(id) }, - diveBack () { - const oldHighlight = this.highlight - this.diveHistory = [...this.diveHistory.slice(0, this.diveHistory.length - 1)] - if (oldHighlight) { - this.tryScrollTo(this.leastVisibleAncestor(oldHighlight)) - } + diveToTopLevel () { + this.tryScrollTo(this.topLevel[0].id) }, + // only used when we are not on a page undive () { - const oldHighlight = this.highlight - this.diveHistory = [] - if (oldHighlight) { - this.tryScrollTo(this.leastVisibleAncestor(oldHighlight)) - } else { - this.goToCurrent() - } + this.inlineDivePosition = null + this.setHighlight(this.statusId) }, tryScrollTo (id) { if (!id) { @@ -477,8 +455,9 @@ const conversation = { if (this.isPage) { // set statusId this.$router.push({ name: 'conversation', params: { id } }) + } else { + this.inlineDivePosition = id } - this.setHighlight(id) }, goToCurrent () { @@ -493,10 +472,24 @@ const conversation = { return undefined } const { in_reply_to_status_id: parentId } = status + if (!this.statusMap[parentId]) { + return undefined + } return parentId }, parentOrSelf (id) { return this.parentOf(id) || id + }, + // Ancestors of some status, from top to bottom + ancestorsOf (id) { + const ancestors = [] + let cur = this.parentOf(id) + while (cur) { + ancestors.unshift(this.statusMap[cur]) + cur = this.parentOf(cur) + } + // console.log('ancestors = ', ancestors, 'conversation = ', this.conversation.map(k => k.id), 'statusContentProperties=', this.statusContentProperties) + return ancestors } } } diff --git a/src/components/conversation/conversation.vue b/src/components/conversation/conversation.vue index c866b98302..20ce54a66e 100644 --- a/src/components/conversation/conversation.vue +++ b/src/components/conversation/conversation.vue @@ -21,34 +21,88 @@
    -
    - - - -
    +
    +
    + +
    +
    + + + + {{ $tc('status.ancestor_follow', getReplies(status.id).length - 1, { numReplies: getReplies(status.id).length - 1 }) }} + + +
    +
    +
    +
    From d78c8e8ea4c1b5a9801552b519573037564a8f66 Mon Sep 17 00:00:00 2001 From: Tusooa Zhu Date: Tue, 10 Aug 2021 23:59:51 -0400 Subject: [PATCH 0173/1033] Add English translation for Misskey-style tree view --- src/i18n/en.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/i18n/en.json b/src/i18n/en.json index b8ddc3d27a..02dd7200c5 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -759,8 +759,9 @@ "thread_show_full_with_icon": "{icon} {text}", "thread_follow": "See the remaining part of this thread ({numStatus} status in total) | See the remaining part of this thread ({numStatus} statuses in total)", "thread_follow_with_icon": "{icon} {text}", + "ancestor_follow": "See {numReplies} other reply under this status | See {numReplies} other replies under this status", + "ancestor_follow_with_icon": "{icon} {text}", "show_all_conversation": "{0} Show full conversation", - "return_to_last_showing": "{0} Return to last position", "show_only_conversation_under_this": "Only show replies to this status" }, "user_card": { From f1db5e8f4bfc8d43eb74d0e3f784c0aa8b06bf3f Mon Sep 17 00:00:00 2001 From: Tusooa Zhu Date: Wed, 11 Aug 2021 00:12:16 -0400 Subject: [PATCH 0174/1033] Highlight ancestor of the current status when diving back to top --- src/components/conversation/conversation.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/components/conversation/conversation.js b/src/components/conversation/conversation.js index 817b9bda7d..e9bbca1803 100644 --- a/src/components/conversation/conversation.js +++ b/src/components/conversation/conversation.js @@ -441,7 +441,7 @@ const conversation = { this.tryScrollTo(id) }, diveToTopLevel () { - this.tryScrollTo(this.topLevel[0].id) + this.tryScrollTo(this.topLevelAncestorOrSelfId(this.diveRoot) || this.topLevel[0].id) }, // only used when we are not on a page undive () { @@ -490,6 +490,15 @@ const conversation = { } // console.log('ancestors = ', ancestors, 'conversation = ', this.conversation.map(k => k.id), 'statusContentProperties=', this.statusContentProperties) return ancestors + }, + topLevelAncestorOrSelfId (id) { + let cur = id + let parent = this.parentOf(id) + while (parent) { + cur = this.parentOf(cur) + parent = this.parentOf(parent) + } + return cur } } } From 10cd03c7186fa57e8cbdd22c4523c98e4ea53c47 Mon Sep 17 00:00:00 2001 From: Tusooa Zhu Date: Wed, 11 Aug 2021 00:17:17 -0400 Subject: [PATCH 0175/1033] Clean up --- src/components/conversation/conversation.js | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/components/conversation/conversation.js b/src/components/conversation/conversation.js index e9bbca1803..3cc5f88618 100644 --- a/src/components/conversation/conversation.js +++ b/src/components/conversation/conversation.js @@ -346,11 +346,6 @@ const conversation = { } }, methods: { - conversationFetched () { - if (!this.isExpanded) { - return - } - }, fetchConversation () { if (this.status) { this.$store.state.api.backendInteractor.fetchConversation({ id: this.statusId }) @@ -359,7 +354,6 @@ const conversation = { this.$store.dispatch('addNewStatuses', { statuses: descendants }) this.setHighlight(this.originalStatusId) }) - .then(this.conversationFetched) } else { this.$store.state.api.backendInteractor.fetchStatus({ id: this.statusId }) .then((status) => { @@ -488,7 +482,6 @@ const conversation = { ancestors.unshift(this.statusMap[cur]) cur = this.parentOf(cur) } - // console.log('ancestors = ', ancestors, 'conversation = ', this.conversation.map(k => k.id), 'statusContentProperties=', this.statusContentProperties) return ancestors }, topLevelAncestorOrSelfId (id) { From 26670e90035104fbd24e0884c00b17c6266ba354 Mon Sep 17 00:00:00 2001 From: Tusooa Zhu Date: Wed, 11 Aug 2021 00:22:47 -0400 Subject: [PATCH 0176/1033] Reset thread open state when collapsed --- src/components/conversation/conversation.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/components/conversation/conversation.js b/src/components/conversation/conversation.js index 3cc5f88618..4c42916183 100644 --- a/src/components/conversation/conversation.js +++ b/src/components/conversation/conversation.js @@ -334,8 +334,7 @@ const conversation = { if (value) { this.fetchConversation() } else { - // if we collapse it, we should reset the dive - this.undive() + this.resetDisplayState() } }, virtualHidden (value) { @@ -492,6 +491,10 @@ const conversation = { parent = this.parentOf(parent) } return cur + }, + resetDisplayState () { + this.undive() + this.threadDisplayStatusObject = {} } } } From 17863f54fef4203365aa2b7ce58da3bb9bb3cc8c Mon Sep 17 00:00:00 2001 From: Tusooa Zhu Date: Wed, 11 Aug 2021 00:30:27 -0400 Subject: [PATCH 0177/1033] Optimise thread ancestor display style --- src/components/conversation/conversation.vue | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/components/conversation/conversation.vue b/src/components/conversation/conversation.vue index 20ce54a66e..f0e118e56f 100644 --- a/src/components/conversation/conversation.vue +++ b/src/components/conversation/conversation.vue @@ -194,7 +194,12 @@ flex-direction: column; } - .thread-ancestor { + .thread-ancestors { + margin-left: $status-margin; + border-left: 2px solid var(--border, $fallback--border); + } + + .thread-ancestor .StatusContent { --link: var(--faintLink); --text: var(--faint); color: var(--text); From ba8598858b4a90d25b76a515dc6a9125d2809f9d Mon Sep 17 00:00:00 2001 From: Tusooa Zhu Date: Wed, 11 Aug 2021 00:49:38 -0400 Subject: [PATCH 0178/1033] Optimise thread ancestor borders --- src/components/conversation/conversation.vue | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/components/conversation/conversation.vue b/src/components/conversation/conversation.vue index f0e118e56f..9aea7b20bd 100644 --- a/src/components/conversation/conversation.vue +++ b/src/components/conversation/conversation.vue @@ -220,7 +220,6 @@ //border-left: 2px solid var(--border, $fallback--border); } - /* HACK: we want the border width to scale with the status *below it* */ .conversation-status { border-bottom-width: 1px; border-bottom-style: solid; @@ -229,10 +228,18 @@ } .thread-ancestor-has-other-replies .conversation-status, + .thread-ancestor:last-child .conversation-status, + .thread-ancestor:last-child .thread-ancestor-dive-box, &.-expanded .thread-tree .conversation-status { border-bottom: none; } + .thread-ancestors + .thread-tree > .conversation-status { + border-top-width: 1px; + border-top-style: solid; + border-top-color: var(--border, $fallback--border); + } + /* expanded conversation in timeline */ &.status-fadein.-expanded .thread-body { border-left-width: 4px; From 22bdcda9c0a9869f8a09507bb60215b8a5af709a Mon Sep 17 00:00:00 2001 From: Tusooa Zhu Date: Fri, 13 Aug 2021 18:53:31 -0400 Subject: [PATCH 0179/1033] Make other replies button stretch along the row --- src/components/conversation/conversation.vue | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/components/conversation/conversation.vue b/src/components/conversation/conversation.vue index 9aea7b20bd..6c8c6ef070 100644 --- a/src/components/conversation/conversation.vue +++ b/src/components/conversation/conversation.vue @@ -211,9 +211,11 @@ border-bottom-color: var(--border, $fallback--border); border-radius: 0; /* Make the button stretch along the whole row */ - display: flex; - align-items: stretch; - flex-direction: column; + &, &-inner { + display: flex; + align-items: stretch; + flex-direction: column; + } } .thread-ancestor-dive-box-inner { padding: $status-margin; From 244174a32b94c1373847f0ea20bb6127de5ef222 Mon Sep 17 00:00:00 2001 From: Tusooa Zhu Date: Sun, 5 Sep 2021 11:16:48 -0400 Subject: [PATCH 0180/1033] Improve "show full conversation" interaction Now we only show that button when there are other statuses out of sight (other toplevel statuses exist outside of the current thread tree). --- src/components/conversation/conversation.js | 8 ++++++++ src/components/conversation/conversation.vue | 12 +++++++++--- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/components/conversation/conversation.js b/src/components/conversation/conversation.js index 4c42916183..423930afb0 100644 --- a/src/components/conversation/conversation.js +++ b/src/components/conversation/conversation.js @@ -224,6 +224,9 @@ const conversation = { debug('toplevel =', topLevel) return topLevel }, + otherTopLevelCount () { + return this.topLevel.length - 1 + }, showingTopLevel () { if (this.canDive && this.diveRoot) { return [this.statusMap[this.diveRoot]] @@ -242,6 +245,11 @@ const conversation = { diveMode () { return this.canDive && !!this.diveRoot }, + shouldShowAllConversationButton () { + // The "show all conversation" button tells the user that there exist + // other toplevel statuses, so do not show it if there is only a single root + return this.diveMode && this.topLevel.length > 1 + }, replies () { let i = 1 // eslint-disable-next-line camelcase diff --git a/src/components/conversation/conversation.vue b/src/components/conversation/conversation.vue index 6c8c6ef070..f0eb88c124 100644 --- a/src/components/conversation/conversation.vue +++ b/src/components/conversation/conversation.vue @@ -20,16 +20,22 @@
    - + + + {{ $tc('status.show_all_conversation', otherTopLevelCount, { numStatus: otherTopLevelCount }) }} +
    Date: Sun, 5 Sep 2021 11:19:43 -0400 Subject: [PATCH 0181/1033] Add English translation for show all conversation button improvement --- src/i18n/en.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/i18n/en.json b/src/i18n/en.json index 02dd7200c5..ef96e0c50d 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -761,7 +761,8 @@ "thread_follow_with_icon": "{icon} {text}", "ancestor_follow": "See {numReplies} other reply under this status | See {numReplies} other replies under this status", "ancestor_follow_with_icon": "{icon} {text}", - "show_all_conversation": "{0} Show full conversation", + "show_all_conversation_with_icon": "{icon} {text}", + "show_all_conversation": "Show full conversation ({numStatus} other status) | Show full conversation ({numStatus} other statuses)", "show_only_conversation_under_this": "Only show replies to this status" }, "user_card": { From 863255d52fdcbbabe45c86c7e36ebafc0f7e1c53 Mon Sep 17 00:00:00 2001 From: Tusooa Zhu Date: Sun, 5 Sep 2021 16:35:47 -0400 Subject: [PATCH 0182/1033] Make position of other replies button a pref --- src/components/conversation/conversation.js | 9 +++++ src/components/conversation/conversation.vue | 7 ++-- .../settings_modal/tabs/general_tab.js | 5 +++ .../settings_modal/tabs/general_tab.vue | 40 +++++++++++++------ src/components/status/status.js | 1 + src/components/status/status.vue | 15 ++++++- src/modules/config.js | 2 + src/modules/instance.js | 1 + 8 files changed, 63 insertions(+), 17 deletions(-) diff --git a/src/components/conversation/conversation.js b/src/components/conversation/conversation.js index 423930afb0..d4972fbc74 100644 --- a/src/components/conversation/conversation.js +++ b/src/components/conversation/conversation.js @@ -92,6 +92,15 @@ const conversation = { isLinearView () { return this.displayStyle === 'linear' }, + otherRepliesButtonPosition () { + return this.$store.getters.mergedConfig.conversationOtherRepliesButton + }, + showOtherRepliesButtonBelowStatus () { + return this.otherRepliesButtonPosition === 'below' + }, + showOtherRepliesButtonInsideStatus () { + return this.otherRepliesButtonPosition === 'inside' + }, hideStatus () { if (this.$refs.statusComponent && this.$refs.statusComponent[0]) { return this.virtualHidden && this.$refs.statusComponent[0].suspendable diff --git a/src/components/conversation/conversation.vue b/src/components/conversation/conversation.vue index f0eb88c124..b3d97075d3 100644 --- a/src/components/conversation/conversation.vue +++ b/src/components/conversation/conversation.vue @@ -66,13 +66,14 @@ :profile-user-id="profileUserId" class="conversation-status status-fadein panel-body" - :simple="treeViewIsSimple" + :simple-tree="treeViewIsSimple" :toggle-thread-display="toggleThreadDisplay" :thread-display-status="threadDisplayStatus" :show-thread-recursively="showThreadRecursively" :total-reply-count="totalReplyCount" :total-reply-depth="totalReplyDepth" - :dive="(!treeViewIsSimple) ? () => diveIntoStatus(status.id) : null" + :show-other-replies-as-button="showOtherRepliesButtonInsideStatus" + :dive="() => diveIntoStatus(status.id)" :controlled-showing-tall="statusContentProperties[status.id].showingTall" :controlled-expanding-subject="statusContentProperties[status.id].expandingSubject" @@ -85,7 +86,7 @@ @toggleExpanded="toggleExpanded" />
    ({ + key: mode, + value: mode, + label: this.$t(`settings.conversation_other_replies_button_${mode}`) + })), mentionLinkDisplayOptions: ['short', 'full_for_remote', 'full'].map(mode => ({ key: mode, value: mode, diff --git a/src/components/settings_modal/tabs/general_tab.vue b/src/components/settings_modal/tabs/general_tab.vue index f97d92c352..d5ae781087 100644 --- a/src/components/settings_modal/tabs/general_tab.vue +++ b/src/components/settings_modal/tabs/general_tab.vue @@ -161,19 +161,33 @@ {{ $t('settings.conversation_display') }} -
  • - - -
  • +
      +
    • + + +
    • +
    • + + {{ $t('settings.conversation_other_replies_button') }} + +
    • +
  • - {{ $t('status.replies_list') }} + + + {{ $t('status.replies_list') }} + Date: Sun, 5 Sep 2021 16:36:27 -0400 Subject: [PATCH 0183/1033] Add English translation for position of other replies button pref --- src/i18n/en.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/i18n/en.json b/src/i18n/en.json index ef96e0c50d..7b37357af0 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -469,6 +469,9 @@ "conversation_display_tree": "Tree-style", "conversation_display_simple_tree": "Simplified tree-style", "conversation_display_linear": "Linear-style", + "conversation_other_replies_button": "Show the \"other replies\" button", + "conversation_other_replies_button_below": "Below statuses", + "conversation_other_replies_button_inside": "Inside statuses", "max_depth_in_thread": "Maximum number of levels in thread to display by default", "post_status_content_type": "Post status content type", "sensitive_by_default": "Mark posts as sensitive by default", From cebb4224ac0143f6969c7d3e907a7d25eb38b4c7 Mon Sep 17 00:00:00 2001 From: Tusooa Zhu Date: Wed, 8 Sep 2021 23:22:11 -0400 Subject: [PATCH 0184/1033] Do not display replies inside status as link if there are no other replies --- src/components/status/status.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/status/status.vue b/src/components/status/status.vue index bc0aeaf06c..31908815b9 100644 --- a/src/components/status/status.vue +++ b/src/components/status/status.vue @@ -347,7 +347,7 @@ class="replies" > Date: Wed, 8 Sep 2021 23:29:17 -0400 Subject: [PATCH 0186/1033] Add English translations for other replies count --- src/i18n/en.json | 1 + 1 file changed, 1 insertion(+) diff --git a/src/i18n/en.json b/src/i18n/en.json index 7b37357af0..b185dcab40 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -729,6 +729,7 @@ "reply_to": "Reply to", "mentions": "Mentions", "replies_list": "Replies:", + "replies_list_with_others": "Replies (+{numReplies} other): | Replies (+{numReplies} others):", "mute_conversation": "Mute conversation", "unmute_conversation": "Unmute conversation", "status_unavailable": "Status unavailable", From 0db5a5a581aa6560637dd85886dfd9d7934f40fa Mon Sep 17 00:00:00 2001 From: Tusooa Zhu Date: Thu, 9 Sep 2021 00:03:10 -0400 Subject: [PATCH 0187/1033] Fix controlled status display toggles --- src/components/status_body/status_body.js | 16 +++++++++------- src/components/status_content/status_content.js | 8 ++------ src/components/status_content/status_content.vue | 6 ++++++ 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/src/components/status_body/status_body.js b/src/components/status_body/status_body.js index 91c331359d..b8f6f9a0b6 100644 --- a/src/components/status_body/status_body.js +++ b/src/components/status_body/status_body.js @@ -26,14 +26,16 @@ const StatusContent = { 'focused', 'noHeading', 'fullContent', - 'singleLine' + 'singleLine', + 'showingTall', + 'expandingSubject', + 'showingLongSubject', + 'toggleShowingTall', + 'toggleExpandingSubject', + 'toggleShowingLongSubject' ], data () { return { - showingTall: this.fullContent || (this.inConversation && this.focused), - showingLongSubject: false, - // not as computed because it sets the initial state which will be changed later - expandingSubject: !this.$store.getters.mergedConfig.collapseMessageWithSubject, postLength: this.status.text.length, parseReadyDone: false } @@ -115,9 +117,9 @@ const StatusContent = { }, toggleShowMore () { if (this.mightHideBecauseTall) { - this.showingTall = !this.showingTall + this.toggleShowingTall() } else if (this.mightHideBecauseSubject) { - this.expandingSubject = !this.expandingSubject + this.toggleExpandingSubject() } }, generateTagLink (tag) { diff --git a/src/components/status_content/status_content.js b/src/components/status_content/status_content.js index 527a4cf543..cf72ccb845 100644 --- a/src/components/status_content/status_content.js +++ b/src/components/status_content/status_content.js @@ -116,12 +116,8 @@ const StatusContent = { toggleExpandingSubject () { controlledOrUncontrolledToggle(this, 'expandingSubject') }, - toggleShowMore () { - if (this.mightHideBecauseTall) { - this.toggleShowingTall() - } else if (this.mightHideBecauseSubject) { - this.toggleExpandingSubject() - } + toggleShowingLongSubject () { + controlledOrUncontrolledToggle(this, 'showingLongSubject') }, setMedia () { const attachments = this.attachmentSize === 'hide' ? this.status.attachments : this.galleryAttachments diff --git a/src/components/status_content/status_content.vue b/src/components/status_content/status_content.vue index 69635aad19..0a09cda48e 100644 --- a/src/components/status_content/status_content.vue +++ b/src/components/status_content/status_content.vue @@ -8,6 +8,12 @@ :status="status" :compact="compact" :single-line="singleLine" + :showing-tall="showingTall" + :expanding-subject="expandingSubject" + :showing-long-subject="showingLongSubject" + :toggle-showing-tall="toggleShowingTall" + :toggle-expanding-subject="toggleExpandingSubject" + :toggle-showing-long-subject="toggleShowingLongSubject" @parseReady="$emit('parseReady', $event)" >
    From 2a510205c3e18bc1c3ff253dc4521909857cd530 Mon Sep 17 00:00:00 2001 From: Tusooa Zhu Date: Wed, 15 Sep 2021 23:35:17 -0400 Subject: [PATCH 0188/1033] Fix virtual scrolling for tree threading Ref: tree-threading --- src/components/conversation/conversation.js | 15 ++++++++++----- src/components/conversation/conversation.vue | 2 +- src/components/thread_tree/thread_tree.js | 7 +++++++ 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/components/conversation/conversation.js b/src/components/conversation/conversation.js index d4972fbc74..1e97bbf0eb 100644 --- a/src/components/conversation/conversation.js +++ b/src/components/conversation/conversation.js @@ -101,13 +101,16 @@ const conversation = { showOtherRepliesButtonInsideStatus () { return this.otherRepliesButtonPosition === 'inside' }, - hideStatus () { + suspendable () { if (this.$refs.statusComponent && this.$refs.statusComponent[0]) { - return this.virtualHidden && this.$refs.statusComponent[0].suspendable + return this.$refs.statusComponent.every(s => s.suspendable) } else { - return this.virtualHidden + return true } }, + hideStatus () { + return this.virtualHidden && this.suspendable + }, status () { return this.$store.state.statuses.allStatusesObject[this.statusId] }, @@ -243,7 +246,6 @@ const conversation = { return this.topLevel }, diveRoot () { - (() => {})(this.conversation) const statusId = this.inlineDivePosition || this.statusId const isTopLevel = !this.parentOf(statusId) return isTopLevel ? null : statusId @@ -257,7 +259,10 @@ const conversation = { shouldShowAllConversationButton () { // The "show all conversation" button tells the user that there exist // other toplevel statuses, so do not show it if there is only a single root - return this.diveMode && this.topLevel.length > 1 + return this.isTreeView && this.isExpanded && this.diveMode && this.topLevel.length > 1 + }, + shouldShowAncestors () { + return this.isTreeView && this.isExpanded && this.ancestorsOf(this.diveRoot).length }, replies () { let i = 1 diff --git a/src/components/conversation/conversation.vue b/src/components/conversation/conversation.vue index b3d97075d3..0cd7453995 100644 --- a/src/components/conversation/conversation.vue +++ b/src/components/conversation/conversation.vue @@ -43,7 +43,7 @@ class="thread-body" >
    s.suspendable) + } + return selfSuspendable + }, reverseLookupTable () { return this.conversation.reduce((table, status, index) => { table[status.id] = index From cc5cff2038c067ceacd98f218bbcffa2a50069eb Mon Sep 17 00:00:00 2001 From: Tusooa Zhu Date: Fri, 10 Sep 2021 15:24:23 -0400 Subject: [PATCH 0189/1033] Clean up debug code for tree threading --- src/components/conversation/conversation.js | 15 --------------- src/components/thread_tree/thread_tree.js | 5 ----- 2 files changed, 20 deletions(-) diff --git a/src/components/conversation/conversation.js b/src/components/conversation/conversation.js index 1e97bbf0eb..7f9f24b574 100644 --- a/src/components/conversation/conversation.js +++ b/src/components/conversation/conversation.js @@ -15,9 +15,6 @@ library.add( faChevronLeft ) -// const debug = console.log -const debug = () => {} - const sortById = (a, b) => { const idA = a.type === 'retweet' ? a.retweeted_status.id : a.id const idB = b.type === 'retweet' ? b.retweeted_status.id : b.id @@ -165,8 +162,6 @@ const conversation = { forest: {} }) - debug('threads = ', threads) - const walk = (forest, topLevel, depth = 0, processed = {}) => topLevel.map(id => { if (processed[id]) { return [] @@ -192,7 +187,6 @@ const conversation = { }, {}) }, totalReplyCount () { - debug('replyIds=', this.replyIds) const sizes = {} const subTreeSizeFor = (id) => { if (sizes[id]) { @@ -202,7 +196,6 @@ const conversation = { return sizes[id] } this.conversation.map(k => k.id).map(subTreeSizeFor) - debug('totalReplyCount=', sizes) return Object.keys(sizes).reduce((res, id) => { res[id] = sizes[id] - 1 // exclude itself return res @@ -224,7 +217,6 @@ const conversation = { }, {}) }, depths () { - debug('threadTree', this.threadTree) return this.threadTree.reduce((a, k) => { a[k.id] = k.depth return a @@ -233,7 +225,6 @@ const conversation = { topLevel () { const topLevel = this.conversation.reduce((tl, cur) => tl.filter(k => this.getReplies(cur.id).map(v => v.id).indexOf(k.id) === -1), this.conversation) - debug('toplevel =', topLevel) return topLevel }, otherTopLevelCount () { @@ -409,14 +400,8 @@ const conversation = { } }, toggleThreadDisplay (id) { - const depth = this.depths[id] - debug('depth = ', depth) - debug( - 'threadDisplayStatus = ', this.threadDisplayStatus, - 'threadDisplayStatusObject = ', this.threadDisplayStatusObject) const curStatus = this.threadDisplayStatus[id] const nextStatus = curStatus === 'showing' ? 'hidden' : 'showing' - debug('toggling', id, 'to', nextStatus) this.setThreadDisplay(id, nextStatus) }, setThreadDisplayRecursively (id, nextStatus) { diff --git a/src/components/thread_tree/thread_tree.js b/src/components/thread_tree/thread_tree.js index fd21c5bc57..0e499b85be 100644 --- a/src/components/thread_tree/thread_tree.js +++ b/src/components/thread_tree/thread_tree.js @@ -11,9 +11,6 @@ library.add( faAngleDoubleRight ) -// const debug = console.log -const debug = () => {} - const ThreadTree = { components: { Status @@ -62,8 +59,6 @@ const ThreadTree = { }, {}) }, currentReplies () { - debug('status:', this.status) - debug('getReplies:', this.getReplies(this.status.id)) return this.getReplies(this.status.id).map(({ id }) => this.statusById(id)) }, threadShowing () { From 20880cdf0bd33d6c189549441ab0ee26b59abf6d Mon Sep 17 00:00:00 2001 From: Tusooa Zhu Date: Thu, 16 Sep 2021 00:29:14 -0400 Subject: [PATCH 0190/1033] Make replying and mediaPlaying controlled $refs is not a reliable way to deal with child components under tree threading as it is not reactive, but the children may change at any time. The only good way seems to be making these states aggregated on the conversation component. Ref: tree-threading --- src/components/conversation/conversation.js | 21 ++++++-- src/components/conversation/conversation.vue | 4 ++ src/components/status/status.js | 50 ++++++++++++++++++-- src/components/thread_tree/thread_tree.js | 3 ++ src/components/thread_tree/thread_tree.vue | 4 ++ 5 files changed, 72 insertions(+), 10 deletions(-) diff --git a/src/components/conversation/conversation.js b/src/components/conversation/conversation.js index 7f9f24b574..9aa7b18350 100644 --- a/src/components/conversation/conversation.js +++ b/src/components/conversation/conversation.js @@ -99,6 +99,10 @@ const conversation = { return this.otherRepliesButtonPosition === 'inside' }, suspendable () { + if (this.isTreeView) { + return Object.entries(this.statusContentProperties) + .every(([k, prop]) => !prop.replying && prop.mediaPlaying.length === 0) + } if (this.$refs.statusComponent && this.$refs.statusComponent[0]) { return this.$refs.statusComponent.every(s => s.suspendable) } else { @@ -303,14 +307,21 @@ const conversation = { return this.conversation.reduce((a, k) => { const id = k.id const props = (() => { - if (this.statusContentPropertiesObject[id]) { - return this.statusContentPropertiesObject[id] - } - return { + const def = { showingTall: false, expandingSubject: false, - showingLongSubject: false + showingLongSubject: false, + isReplying: false, + mediaPlaying: [] } + + if (this.statusContentPropertiesObject[id]) { + return { + ...def, + ...this.statusContentPropertiesObject[id] + } + } + return def })() a[id] = props diff --git a/src/components/conversation/conversation.vue b/src/components/conversation/conversation.vue index 0cd7453995..4d64cf08b5 100644 --- a/src/components/conversation/conversation.vue +++ b/src/components/conversation/conversation.vue @@ -78,9 +78,13 @@ :controlled-showing-tall="statusContentProperties[status.id].showingTall" :controlled-expanding-subject="statusContentProperties[status.id].expandingSubject" :controlled-showing-long-subject="statusContentProperties[status.id].showingLongSubject" + :controlled-replying="statusContentProperties[status.id].replying" + :controlled-media-playing="statusContentProperties[status.id].mediaPlaying" :controlled-toggle-showing-tall="() => toggleStatusContentProperty(status.id, 'showingTall')" :controlled-toggle-expanding-subject="() => toggleStatusContentProperty(status.id, 'expandingSubject')" :controlled-toggle-showing-long-subject="() => toggleStatusContentProperty(status.id, 'showingLongSubject')" + :controlled-toggle-replying="() => toggleStatusContentProperty(status.id, 'replying')" + :controlled-set-media-playing="(newVal) => toggleStatusContentProperty(status.id, 'mediaPlaying', newVal)" @goto="setHighlight" @toggleExpanded="toggleExpanded" diff --git a/src/components/status/status.js b/src/components/status/status.js index 700b97640e..73fad45fb8 100644 --- a/src/components/status/status.js +++ b/src/components/status/status.js @@ -61,6 +61,41 @@ library.add( faAngleDoubleRight ) +const camelCase = name => name.charAt(0).toUpperCase() + name.slice(1) + +const controlledOrUncontrolledGetters = list => list.reduce((res, name) => { + const camelized = camelCase(name) + const toggle = `controlledToggle${camelized}` + const controlledName = `controlled${camelized}` + const uncontrolledName = `uncontrolled${camelized}` + res[name] = function () { + return this[toggle] ? this[controlledName] : this[uncontrolledName] + } + return res +}, {}) + +const controlledOrUncontrolledToggle = (obj, name) => { + const camelized = camelCase(name) + const toggle = `controlledToggle${camelized}` + const uncontrolledName = `uncontrolled${camelized}` + if (obj[toggle]) { + obj[toggle]() + } else { + obj[uncontrolledName] = !obj[uncontrolledName] + } +} + +const controlledOrUncontrolledSet = (obj, name, val) => { + const camelized = camelCase(name) + const set = `controlledSet${camelized}` + const uncontrolledName = `uncontrolled${camelized}` + if (obj[set]) { + obj[set](val) + } else { + obj[uncontrolledName] = val + } +} + const Status = { name: 'Status', components: { @@ -108,20 +143,25 @@ const Status = { 'controlledToggleExpandingSubject', 'controlledShowingLongSubject', 'controlledToggleShowingLongSubject', + 'controlledReplying', + 'controlledToggleReplying', + 'controlledMediaPlaying', + 'controlledSetMediaPlaying', 'dive' ], data () { return { - replying: false, + uncontrolledReplying: false, unmuted: false, userExpanded: false, - mediaPlaying: [], + uncontrolledMediaPlaying: [], suspendable: true, error: null, headTailLinks: null } }, computed: { + ...controlledOrUncontrolledGetters(['replying', 'mediaPlaying']), muteWords () { return this.mergedConfig.muteWords }, @@ -351,7 +391,7 @@ const Status = { this.error = undefined }, toggleReplying () { - this.replying = !this.replying + controlledOrUncontrolledToggle(this, 'replying') }, gotoOriginal (id) { if (this.inConversation) { @@ -371,10 +411,10 @@ const Status = { return generateProfileLink(id, name, this.$store.state.instance.restrictedNicknames) }, addMediaPlaying (id) { - this.mediaPlaying.push(id) + controlledOrUncontrolledSet(this, 'mediaPlaying', this.mediaPlaying.concat(id)) }, removeMediaPlaying (id) { - this.mediaPlaying = this.mediaPlaying.filter(mediaId => mediaId !== id) + controlledOrUncontrolledSet(this, 'mediaPlaying', this.mediaPlaying.filter(mediaId => mediaId !== id)) }, setHeadTailLinks (headTailLinks) { this.headTailLinks = headTailLinks diff --git a/src/components/thread_tree/thread_tree.js b/src/components/thread_tree/thread_tree.js index 0e499b85be..71e6372541 100644 --- a/src/components/thread_tree/thread_tree.js +++ b/src/components/thread_tree/thread_tree.js @@ -80,6 +80,9 @@ const ThreadTree = { }, toggleCurrentProp (name) { this.toggleStatusContentProperty(this.status.id, name) + }, + setCurrentProp (name, newVal) { + this.setStatusContentProperty(this.status.id, name) } } } diff --git a/src/components/thread_tree/thread_tree.vue b/src/components/thread_tree/thread_tree.vue index dce03f27a0..cee223e818 100644 --- a/src/components/thread_tree/thread_tree.vue +++ b/src/components/thread_tree/thread_tree.vue @@ -22,9 +22,13 @@ :controlled-showing-tall="currentProp.showingTall" :controlled-expanding-subject="currentProp.expandingSubject" :controlled-showing-long-subject="currentProp.showingLongSubject" + :controlled-replying="currentProp.replying" + :controlled-media-playing="currentProp.mediaPlaying" :controlled-toggle-showing-tall="() => toggleCurrentProp('showingTall')" :controlled-toggle-expanding-subject="() => toggleCurrentProp('expandingSubject')" :controlled-toggle-showing-long-subject="() => toggleCurrentProp('showingLongSubject')" + :controlled-toggle-replying="() => toggleCurrentProp('replying')" + :controlled-set-media-playing="(newVal) => setCurrentProp('mediaPlaying', newVal)" :dive="dive ? () => dive(status.id) : undefined" @goto="setHighlight" From f8c5cbcd0d5d092c1264032a1be003f828dfc499 Mon Sep 17 00:00:00 2001 From: Tusooa Zhu Date: Thu, 16 Sep 2021 09:22:49 -0400 Subject: [PATCH 0191/1033] Fix timeline jump when scrolling Ref: tree-threading --- src/components/conversation/conversation.js | 19 ++++++++++++++++++- src/components/status/status.js | 3 --- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/components/conversation/conversation.js b/src/components/conversation/conversation.js index 9aa7b18350..b9ebe7ebe7 100644 --- a/src/components/conversation/conversation.js +++ b/src/components/conversation/conversation.js @@ -469,7 +469,24 @@ const conversation = { } else { this.inlineDivePosition = id } - this.setHighlight(id) + // Because the conversation can be unmounted when out of sight + // and mounted again when it comes into sight, + // the `mounted` or `created` function in `status` should not + // contain scrolling calls, as we do not want the page to jump + // when we scroll with an expanded conversation. + // + // Now the method is to rely solely on the `highlight` watcher + // in `status` components. + // In linear views, all statuses are rendered at all times, but + // in tree views, it is possible that a change in active status + // removes and adds status components (e.g. an originally child + // status becomes an ancestor status, and thus they will be + // different). + // Here, let the components be rendered first, in order to trigger + // the `highlight` watcher. + this.$nextTick(() => { + this.setHighlight(id) + }) }, goToCurrent () { this.tryScrollTo(this.diveRoot || this.topLevel[0].id) diff --git a/src/components/status/status.js b/src/components/status/status.js index 73fad45fb8..7bdcb66591 100644 --- a/src/components/status/status.js +++ b/src/components/status/status.js @@ -439,9 +439,6 @@ const Status = { } } }, - mounted () { - this.scrollIfHighlighted(this.highlight) - }, watch: { 'highlight': function (id) { this.scrollIfHighlighted(id) From 5768806d1ba65bf49e4313f4a7ace602ae456a89 Mon Sep 17 00:00:00 2001 From: Tusooa Zhu Date: Mon, 22 Nov 2021 11:20:22 -0500 Subject: [PATCH 0192/1033] Fix showingLongSubject not correctly propagated --- src/components/status_body/status_body.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/status_body/status_body.vue b/src/components/status_body/status_body.vue index a088e6bc85..24d842c2a7 100644 --- a/src/components/status_body/status_body.vue +++ b/src/components/status_body/status_body.vue @@ -17,14 +17,14 @@ From 9432fcec7ddfce7fd52ee2ba3f0ef531d61d9b46 Mon Sep 17 00:00:00 2001 From: Tusooa Zhu Date: Sun, 6 Mar 2022 13:50:15 -0500 Subject: [PATCH 0193/1033] Make 'Show full conversation' button have left border in embbeded mode --- src/components/conversation/conversation.vue | 38 ++++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/components/conversation/conversation.vue b/src/components/conversation/conversation.vue index 4d64cf08b5..73c613b94b 100644 --- a/src/components/conversation/conversation.vue +++ b/src/components/conversation/conversation.vue @@ -19,29 +19,29 @@
    -
    - - - - {{ $tc('status.show_all_conversation', otherTopLevelCount, { numStatus: otherTopLevelCount }) }} - - -
    +
    + + + + {{ $tc('status.show_all_conversation', otherTopLevelCount, { numStatus: otherTopLevelCount }) }} + + +
    Date: Sun, 6 Mar 2022 13:57:48 -0500 Subject: [PATCH 0194/1033] Split conversation display style into two different settings linear => linear (now default) simple_tree => tree / conversationTreeAdvanced=false tree => tree / conversationTreeAdvanced=true --- src/components/conversation/conversation.js | 4 ++-- src/components/settings_modal/tabs/general_tab.js | 2 +- src/components/settings_modal/tabs/general_tab.vue | 5 +++++ src/modules/config.js | 1 + src/modules/instance.js | 3 ++- 5 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/components/conversation/conversation.js b/src/components/conversation/conversation.js index b9ebe7ebe7..46228e37b4 100644 --- a/src/components/conversation/conversation.js +++ b/src/components/conversation/conversation.js @@ -81,10 +81,10 @@ const conversation = { return this.$store.getters.mergedConfig.conversationDisplay }, isTreeView () { - return this.displayStyle === 'tree' || this.displayStyle === 'simple_tree' + return !this.isLinearView }, treeViewIsSimple () { - return this.displayStyle === 'simple_tree' + return !this.$store.getters.mergedConfig.conversationTreeAdvanced }, isLinearView () { return this.displayStyle === 'linear' diff --git a/src/components/settings_modal/tabs/general_tab.js b/src/components/settings_modal/tabs/general_tab.js index a963d2047a..8ae0021ce6 100644 --- a/src/components/settings_modal/tabs/general_tab.js +++ b/src/components/settings_modal/tabs/general_tab.js @@ -20,7 +20,7 @@ const GeneralTab = { value: mode, label: this.$t(`settings.subject_line_${mode === 'masto' ? 'mastodon' : mode}`) })), - conversationDisplayOptions: ['tree', 'simple_tree', 'linear'].map(mode => ({ + conversationDisplayOptions: ['tree', 'linear'].map(mode => ({ key: mode, value: mode, label: this.$t(`settings.conversation_display_${mode}`) diff --git a/src/components/settings_modal/tabs/general_tab.vue b/src/components/settings_modal/tabs/general_tab.vue index d5ae781087..28b39d7b2a 100644 --- a/src/components/settings_modal/tabs/general_tab.vue +++ b/src/components/settings_modal/tabs/general_tab.vue @@ -165,6 +165,11 @@ v-if="conversationDisplay !== 'linear'" class="setting-list suboptions" > +
  • + + {{ $t('settings.tree_advanced') }} + +
  • +
  • + + {{ $t('settings.tree_fade_ancestors') }} + +
  • From 7a17eb7fec4e8f7dbe0a288a22498b800886ac01 Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Mon, 21 Mar 2022 22:00:25 +0200 Subject: [PATCH 0291/1033] fix selects --- src/components/select/select.js | 7 ++----- src/components/select/select.vue | 5 ++--- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/components/select/select.js b/src/components/select/select.js index 49535d0799..ec571a14f9 100644 --- a/src/components/select/select.js +++ b/src/components/select/select.js @@ -8,12 +8,9 @@ library.add( ) export default { - model: { - prop: 'value', - event: 'change' - }, + emits: ['update:modelValue'], props: [ - 'value', + 'modelValue', 'disabled', 'unstyled', 'kind' diff --git a/src/components/select/select.vue b/src/components/select/select.vue index 56e651e378..08c88979bc 100644 --- a/src/components/select/select.vue +++ b/src/components/select/select.vue @@ -1,4 +1,3 @@ - -