From 97fdee5c9dc90ac4beec51b569be32b3286b3d3f Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Tue, 30 Jun 2026 04:02:13 +0300 Subject: [PATCH 1/7] lint and sw fixes --- src/components/error_modal/error_modal.js | 2 +- src/components/global_error/global_error.js | 10 +++++++--- src/components/user_card/user_card.js | 2 +- src/components/user_panel/user_panel.js | 4 ++-- src/components/user_panel/user_panel.vue | 2 +- src/stores/interface.js | 2 +- src/sw.js | 1 + 7 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/components/error_modal/error_modal.js b/src/components/error_modal/error_modal.js index aaa9f99ec..560de3a53 100644 --- a/src/components/error_modal/error_modal.js +++ b/src/components/error_modal/error_modal.js @@ -30,7 +30,7 @@ const ErrorModal = { type: Error, }, }, - emits: ['clear', 'recover'] + emits: ['clear', 'recover'], } export default ErrorModal diff --git a/src/components/global_error/global_error.js b/src/components/global_error/global_error.js index 0f826f4c4..cd4593521 100644 --- a/src/components/global_error/global_error.js +++ b/src/components/global_error/global_error.js @@ -1,9 +1,9 @@ +import { mapActions, mapState } from 'pinia' + import ErrorModal from 'src/components/error_modal/error_modal.vue' import { useInterfaceStore } from 'src/stores/interface.js' -import { mapState, mapActions } from 'pinia' - const GlobalError = { components: { ErrorModal, @@ -24,7 +24,11 @@ const GlobalError = { details() { if (this.globalError == null) return null if (this.globalError.error != null) { - return this.globalError.error.toString() + '\n\n' + this.globalError.error.stack + return ( + this.globalError.error.toString() + + '\n\n' + + this.globalError.error.stack + ) } else { return this.globalError.details } diff --git a/src/components/user_card/user_card.js b/src/components/user_card/user_card.js index f3e2b8f85..267be8bfd 100644 --- a/src/components/user_card/user_card.js +++ b/src/components/user_card/user_card.js @@ -11,11 +11,11 @@ import Checkbox from 'src/components/checkbox/checkbox.vue' import ColorInput from 'src/components/color_input/color_input.vue' import EmojiInput from 'src/components/emoji_input/emoji_input.vue' import suggestor from 'src/components/emoji_input/suggestor.js' +import FollowButton from 'src/components/follow_button/follow_button.vue' import ProgressButton from 'src/components/progress_button/progress_button.vue' import Select from 'src/components/select/select.vue' import UserAvatar from 'src/components/user_avatar/user_avatar.vue' import UserLink from 'src/components/user_link/user_link.vue' -import FollowButton from 'src/components/follow_button/follow_button.vue' import { useEmojiStore } from 'src/stores/emoji.js' import { useInstanceStore } from 'src/stores/instance.js' diff --git a/src/components/user_panel/user_panel.js b/src/components/user_panel/user_panel.js index dd1da869e..08270a1c6 100644 --- a/src/components/user_panel/user_panel.js +++ b/src/components/user_panel/user_panel.js @@ -1,9 +1,8 @@ -import { defineAsyncComponent } from 'vue' import { mapState } from 'vuex' +import AuthForm from 'src/components/auth_form/auth_form.js' import PostStatusForm from 'src/components/post_status_form/post_status_form.vue' import UserCard from 'src/components/user_card/user_card.vue' -import AuthForm from 'src/components/auth_form/auth_form.js' const UserPanel = { computed: { @@ -15,6 +14,7 @@ const UserPanel = { components: { PostStatusForm, UserCard, + AuthForm, }, } diff --git a/src/components/user_panel/user_panel.vue b/src/components/user_panel/user_panel.vue index 3f6922c31..b0479321c 100644 --- a/src/components/user_panel/user_panel.vue +++ b/src/components/user_panel/user_panel.vue @@ -11,7 +11,7 @@ /> - diff --git a/src/stores/interface.js b/src/stores/interface.js index e76a23cc2..6e82dc5f9 100644 --- a/src/stores/interface.js +++ b/src/stores/interface.js @@ -199,7 +199,7 @@ export const useInterfaceStore = defineStore('interface', { console.log(this.globalError) }, clearGlobalError() { - this.globalError = null; + this.globalError = null }, pushGlobalNotice({ messageKey, diff --git a/src/sw.js b/src/sw.js index 1e7abd3de..b7629b5f2 100644 --- a/src/sw.js +++ b/src/sw.js @@ -1,5 +1,6 @@ /* eslint-env serviceworker */ +// biome-ignore: side effect import of assets list import 'virtual:pleroma-fe/service_worker_env' import { createI18n } from 'vue-i18n' From 31f4ad343ab06ba610043b2ba3d24deb64cf4176 Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Tue, 30 Jun 2026 05:42:09 +0300 Subject: [PATCH 2/7] refactored the way status suspensibility works --- src/components/attachment/attachment.js | 1 + src/components/conversation/conversation.js | 79 +++---------- src/components/conversation/conversation.vue | 22 +--- src/components/gallery/gallery.js | 21 ++++ src/components/gallery/gallery.vue | 2 + .../post_status_form/post_status_form.js | 8 +- src/components/search/search.vue | 1 - src/components/status/status.js | 46 +++----- src/components/status/status.vue | 16 +-- src/components/status_body/status_body.js | 83 ++++++++------ src/components/status_body/status_body.scss | 24 ++-- src/components/status_body/status_body.vue | 15 ++- .../status_content/status_content.js | 108 ++++++------------ .../status_content/status_content.vue | 12 +- src/components/thread_tree/thread_tree.js | 7 +- src/components/thread_tree/thread_tree.vue | 20 +--- 16 files changed, 182 insertions(+), 283 deletions(-) diff --git a/src/components/attachment/attachment.js b/src/components/attachment/attachment.js index d5bce12a7..87d659921 100644 --- a/src/components/attachment/attachment.js +++ b/src/components/attachment/attachment.js @@ -52,6 +52,7 @@ const Attachment = { 'shiftDn', 'edit', ], + emits: ['play', 'pause'], data() { return { localDescription: this.description || this.attachment.description, diff --git a/src/components/conversation/conversation.js b/src/components/conversation/conversation.js index 54bcbd373..696167831 100644 --- a/src/components/conversation/conversation.js +++ b/src/components/conversation/conversation.js @@ -55,16 +55,6 @@ const sortAndFilterConversation = (conversation, statusoid) => { } const conversation = { - data() { - return { - highlight: null, - expanded: false, - threadDisplayStatusObject: {}, // id => 'showing' | 'hidden' - statusContentPropertiesObject: {}, - inlineDivePosition: null, - loadStatusError: null, - } - }, props: [ 'statusId', 'collapsable', @@ -74,6 +64,16 @@ const conversation = { 'profileUserId', 'virtualHidden', ], + data() { + return { + highlight: null, + expanded: false, + threadDisplayStatusObject: {}, // id => 'showing' | 'hidden' + inlineDivePosition: null, + loadStatusError: null, + unsuspendibleIds: new Set(), + } + }, created() { if (this.isPage) { this.fetchConversation() @@ -118,16 +118,7 @@ const conversation = { return this.otherRepliesButtonPosition === 'inside' }, suspendable() { - if (this.isTreeView) { - return Object.entries(this.statusContentProperties).every( - ([, prop]) => !prop.replying && prop.mediaPlaying.length === 0, - ) - } - if (this.$refs.statusComponent && this.$refs.statusComponent[0]) { - return this.$refs.statusComponent.every((s) => s.suspendable) - } else { - return true - } + return this.unsuspendibleIds.size > 0 }, hideStatus() { return this.virtualHidden && this.suspendable @@ -364,31 +355,6 @@ const conversation = { return a }, {}) }, - statusContentProperties() { - return this.conversation.reduce((a, k) => { - const id = k.id - const props = (() => { - const def = { - showingTall: false, - expandingSubject: false, - showingLongSubject: false, - isReplying: false, - mediaPlaying: [], - } - - if (this.statusContentPropertiesObject[id]) { - return { - ...def, - ...this.statusContentPropertiesObject[id], - } - } - return def - })() - - a[id] = props - return a - }, {}) - }, canDive() { return this.isTreeView && this.isExpanded }, @@ -514,22 +480,6 @@ 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], - ) - }, leastVisibleAncestor(id) { let cur = id let parent = this.parentOf(cur) @@ -629,6 +579,13 @@ const conversation = { this.undive() this.threadDisplayStatusObject = {} }, + onStatusSuspendStateChange({ id, suspend }) { + if (!suspend) { + this.unsuspendibleIds.add(id) + } else { + this.unsuspendibleIds.delete(id) + } + }, }, } diff --git a/src/components/conversation/conversation.vue b/src/components/conversation/conversation.vue index 8d4734083..98bd8956c 100644 --- a/src/components/conversation/conversation.vue +++ b/src/components/conversation/conversation.vue @@ -107,19 +107,8 @@ :show-other-replies-as-button="showOtherRepliesButtonInsideStatus" :dive="() => diveIntoStatus(status.id)" - :controlled-showing-tall="statusContentProperties[status.id].showingTall" - :controlled-toggle-showing-tall="() => toggleStatusContentProperty(status.id, 'showingTall')" - :controlled-expanding-subject="statusContentProperties[status.id].expandingSubject" - :controlled-toggle-expanding-subject="() => toggleStatusContentProperty(status.id, 'expandingSubject')" - :controlled-showing-long-subject="statusContentProperties[status.id].showingLongSubject" - :controlled-toggle-showing-long-subject="() => toggleStatusContentProperty(status.id, 'showingLongSubject')" - :controlled-replying="statusContentProperties[status.id].replying" - :controlled-toggle-replying="() => toggleStatusContentProperty(status.id, 'replying')" - :controlled-media-playing="statusContentProperties[status.id].mediaPlaying" - :controlled-set-media-playing="(newVal) => toggleStatusContentProperty(status.id, 'mediaPlaying', newVal)" - @goto="setHighlight" - @toggle-expanded="toggleExpanded" + @suspendable-state-change="onStatusSuspendStateChange" />
-
-
diff --git a/src/components/gallery/gallery.js b/src/components/gallery/gallery.js index 252a32bf6..58ab3db0b 100644 --- a/src/components/gallery/gallery.js +++ b/src/components/gallery/gallery.js @@ -27,8 +27,10 @@ const Gallery = { return { sizes: {}, hidingLong: true, + playingMedia: new Set(), } }, + emits: ['play', 'pause'], components: { Attachment }, computed: { rows() { @@ -115,11 +117,21 @@ const Gallery = { return this.attachmentsDimensionalScore > 1 } }, + hasPlayingMedia() { + return this.playingMedia.size > 0 + }, }, methods: { onNaturalSizeLoad({ id, width, height }) { set(this.sizes, id, { width, height }) }, + onMediaStateChange(playing, id) { + if (playing) { + this.playingMedia.add(id) + } else { + this.playingMedia.delete(id) + } + }, rowStyle(row) { if (row.audio) { return { 'padding-bottom': '25%' } // fixed reduced height for audio @@ -146,6 +158,15 @@ const Gallery = { useMediaViewerStore().setMedia(this.attachments) }, }, + watch: { + hasPlayingMedia(newValue) { + if (newValue) { + this.$emit('play') + } else { + this.$emit('pause') + } + } + } } export default Gallery diff --git a/src/components/gallery/gallery.vue b/src/components/gallery/gallery.vue index 11637f3c2..a32d4feb7 100644 --- a/src/components/gallery/gallery.vue +++ b/src/components/gallery/gallery.vue @@ -34,6 +34,8 @@ :style="itemStyle(attachment.id, row.items)" @set-media="onMedia" @natural-size-load="onNaturalSizeLoad" + @play="() => onMediaStateChange(true, attachment.id)" + @pause="() => onMediaStateChange(false, attachment.id)" /> diff --git a/src/components/post_status_form/post_status_form.js b/src/components/post_status_form/post_status_form.js index 6cb99a3b6..bb4051628 100644 --- a/src/components/post_status_form/post_status_form.js +++ b/src/components/post_status_form/post_status_form.js @@ -133,7 +133,7 @@ const PostStatusForm = { 'resize', 'mediaplay', 'mediapause', - 'can-close', + 'close-accepted', 'update', ], components: { @@ -963,19 +963,19 @@ const PostStatusForm = { }, requestClose() { if (!this.saveable) { - this.$emit('can-close') + this.$emit('close-accepted') } else { this.$refs.draftCloser.requestClose() } }, saveAndCloseDraft() { this.saveDraft().then(() => { - this.$emit('can-close') + this.$emit('close-accepted') }) }, discardAndCloseDraft() { this.abandonDraft().then(() => { - this.$emit('can-close') + this.$emit('close-accepted') }) }, addBeforeUnloadListener() { diff --git a/src/components/search/search.vue b/src/components/search/search.vue index 4302f93f9..16418d389 100644 --- a/src/components/search/search.vue +++ b/src/components/search/search.vue @@ -63,7 +63,6 @@ :compact="false" class="search-result" :statusoid="status" - :no-heading="false" /> diff --git a/src/components/thread_tree/thread_tree.js b/src/components/thread_tree/thread_tree.js index bbb81b059..14e79e188 100644 --- a/src/components/thread_tree/thread_tree.js +++ b/src/components/thread_tree/thread_tree.js @@ -26,28 +26,14 @@ const ThreadTree = { toggleExpanded: Function, simple: Boolean, - // to control display of the whole thread forest - toggleThreadDisplay: Function, + canDive: Boolean, threadDisplayStatus: Object, showThreadRecursively: Function, totalReplyCount: Object, totalReplyDepth: Object, - dive: Function, }, - emits: ['suspendableStateChange'], + emits: ['suspendableStateChange', 'dive'], computed: { - suspendable() { - const selfSuspendable = this.$refs.statusComponent - ? this.$refs.statusComponent.suspendable - : true - if (this.$refs.childComponent) { - return ( - selfSuspendable && - this.$refs.childComponent.every((s) => s.suspendable) - ) - } - return selfSuspendable - }, reverseLookupTable() { return this.conversation.reduce( (table, status, index) => { @@ -72,21 +58,6 @@ const ThreadTree = { statusById(id) { return this.conversation[this.reverseLookupTable[id]] }, - collapseThread() { - /* no-op */ - }, - showThread() { - /* no-op */ - }, - showAllSubthreads() { - /* no-op */ - }, - toggleCurrentProp(name) { - this.toggleStatusContentProperty(this.status.id, name) - }, - setCurrentProp(name) { - 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 f04315877..ee0aa75fb 100644 --- a/src/components/thread_tree/thread_tree.vue +++ b/src/components/thread_tree/thread_tree.vue @@ -3,30 +3,29 @@
@@ -70,7 +69,7 @@ tag="button" keypath="status.thread_follow_with_icon" class="button-unstyled -link thread-tree-show-replies-button" - @click.prevent="dive(status.id)" + @click.prevent="$emit('dive', status.id)" >