From ccd4d342b1d987c8ee4b2e98fd211b600f7618d8 Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Sun, 15 Mar 2026 19:26:36 +0200 Subject: [PATCH 1/5] fix socket --- src/App.js | 2 +- src/App.vue | 4 ++-- src/modules/api.js | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/App.js b/src/App.js index 0714ced1d..a0bf0aaa4 100644 --- a/src/App.js +++ b/src/App.js @@ -147,7 +147,7 @@ export default { } } }, - shout() { + shoutJoined() { return useShoutStore().joined }, isChats() { diff --git a/src/App.vue b/src/App.vue index e5e088bc3..f432d8bc4 100644 --- a/src/App.vue +++ b/src/App.vue @@ -60,8 +60,8 @@ /> - Date: Sun, 15 Mar 2026 19:47:11 +0200 Subject: [PATCH 2/5] cleanup + fixes for instance tab --- src/components/color_input/color_input.vue | 2 +- src/components/settings_modal/admin_tabs/instance_tab.vue | 3 ++- src/components/settings_modal/helpers/attachment_setting.js | 2 +- src/components/settings_modal/helpers/color_setting.vue | 1 + .../settings_modal/helpers/pwa_manifest_icons_setting.js | 4 ++-- .../settings_modal/helpers/pwa_manifest_icons_setting.vue | 4 ++-- 6 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/components/color_input/color_input.vue b/src/components/color_input/color_input.vue index a6fc2047b..6f236d35f 100644 --- a/src/components/color_input/color_input.vue +++ b/src/components/color_input/color_input.vue @@ -86,7 +86,7 @@ export default { }, // Readable label label: { - required: true, + required: false, type: String, }, // use unstyled, uh, style diff --git a/src/components/settings_modal/admin_tabs/instance_tab.vue b/src/components/settings_modal/admin_tabs/instance_tab.vue index 585fe303c..144958fa4 100644 --- a/src/components/settings_modal/admin_tabs/instance_tab.vue +++ b/src/components/settings_modal/admin_tabs/instance_tab.vue @@ -51,6 +51,7 @@
  • @@ -99,7 +100,7 @@ override-backend-description override-backend-description-label override-available-options - :options="limitLocalContentOptions" + :options="[...limitLocalContentOptions]" path=":pleroma.:instance.:limit_to_local_content" /> diff --git a/src/components/settings_modal/helpers/attachment_setting.js b/src/components/settings_modal/helpers/attachment_setting.js index 7ba910950..cbcd4abf8 100644 --- a/src/components/settings_modal/helpers/attachment_setting.js +++ b/src/components/settings_modal/helpers/attachment_setting.js @@ -29,7 +29,7 @@ export default { // The "server" part is primarily for local dev, but could be useful for alt-domain or multiuser usage. const url = path.includes('://') ? path : useInstanceStore().server + path return { - mimetype: fileTypeExt(url), + type: fileTypeExt(url), url, } }, diff --git a/src/components/settings_modal/helpers/color_setting.vue b/src/components/settings_modal/helpers/color_setting.vue index 6813bb2a2..c996dc02f 100644 --- a/src/components/settings_modal/helpers/color_setting.vue +++ b/src/components/settings_modal/helpers/color_setting.vue @@ -20,6 +20,7 @@ {{ ' ' }} From 90abdc2b9a6c4598d221684617d7fa05c300c82f Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Fri, 20 Mar 2026 14:00:29 +0200 Subject: [PATCH 3/5] fix mute dropdown closing itself --- changelog.d/mute-dropdown.fix | 1 + .../status_action_buttons/buttons_definitions.js | 7 ++++--- 2 files changed, 5 insertions(+), 3 deletions(-) create mode 100644 changelog.d/mute-dropdown.fix diff --git a/changelog.d/mute-dropdown.fix b/changelog.d/mute-dropdown.fix new file mode 100644 index 000000000..33f12a571 --- /dev/null +++ b/changelog.d/mute-dropdown.fix @@ -0,0 +1 @@ +Fixed status action mute hiding itself on click diff --git a/src/components/status_action_buttons/buttons_definitions.js b/src/components/status_action_buttons/buttons_definitions.js index 20db7aa45..bf03a9ab9 100644 --- a/src/components/status_action_buttons/buttons_definitions.js +++ b/src/components/status_action_buttons/buttons_definitions.js @@ -106,10 +106,11 @@ export const BUTTONS = [ icon: 'eye-slash', label: 'status.mute_ellipsis', if: ({ loggedIn }) => loggedIn, - toggleable: true, + toggleable: false, dropdown: true, - // action ({ status, dispatch, emit }) { - // } + action({ status, dispatch, emit }) { + /* prevent hiding */ + }, }, { // ========= From 7aefda42110c703ad039a3858fa3e352a5d6db9c Mon Sep 17 00:00:00 2001 From: Alexander Tumin Date: Mon, 28 Jul 2025 11:39:50 +0300 Subject: [PATCH 4/5] Add quoting by url / in replies --- changelog.d/quote-by-url.add | 1 + src/components/chat/chat.vue | 1 + src/components/draft/draft.js | 7 +- .../edit_status_form/edit_status_form.vue | 1 + .../post_status_form/post_status_form.js | 99 ++++++++++++--- .../post_status_form/post_status_form.scss | 6 + .../post_status_form/post_status_form.vue | 31 ++++- src/components/quote/quote.js | 101 +++++++++++++++ src/components/quote/quote.vue | 82 ++++++++++++ src/components/quote/quote_form.js | 118 ++++++++++++++++++ src/components/quote/quote_form.vue | 55 ++++++++ src/components/status/status.js | 34 ++--- src/components/status/status.scss | 18 --- src/components/status/status.vue | 47 +------ .../status_action_buttons.scss | 2 +- src/i18n/en.json | 2 + src/services/api/api.service.js | 4 +- .../entity_normalizer.service.js | 2 +- 18 files changed, 501 insertions(+), 110 deletions(-) create mode 100644 changelog.d/quote-by-url.add create mode 100644 src/components/quote/quote.js create mode 100644 src/components/quote/quote.vue create mode 100644 src/components/quote/quote_form.js create mode 100644 src/components/quote/quote_form.vue diff --git a/changelog.d/quote-by-url.add b/changelog.d/quote-by-url.add new file mode 100644 index 000000000..ef401f93c --- /dev/null +++ b/changelog.d/quote-by-url.add @@ -0,0 +1 @@ +Add quoting by URL and in replies diff --git a/src/components/chat/chat.vue b/src/components/chat/chat.vue index dfd197e56..cedbdce69 100644 --- a/src/components/chat/chat.vue +++ b/src/components/chat/chat.vue @@ -73,6 +73,7 @@ :disable-notice="true" :disable-lock-warning="true" :disable-polls="true" + :disable-quotes="true" :disable-sensitivity-checkbox="true" :disable-submit="errorLoadingChat || !currentChat" :disable-preview="true" diff --git a/src/components/draft/draft.js b/src/components/draft/draft.js index 971a75b10..4f0d8cbee 100644 --- a/src/components/draft/draft.js +++ b/src/components/draft/draft.js @@ -43,7 +43,12 @@ const Draft = { } }, safeToSave() { - return this.draft.status || this.draft.files?.length || this.draft.hasPoll + return ( + this.draft.status || + this.draft.files?.length || + this.draft.hasPoll || + this.draft.hasQuote + ) }, postStatusFormProps() { return { diff --git a/src/components/edit_status_form/edit_status_form.vue b/src/components/edit_status_form/edit_status_form.vue index 0a7ec760a..1452be422 100644 --- a/src/components/edit_status_form/edit_status_form.vue +++ b/src/components/edit_status_form/edit_status_form.vue @@ -4,6 +4,7 @@ v-bind="params" :post-handler="doEditStatus" :disable-polls="true" + :disable-quotes="true" :disable-visibility-selector="true" /> diff --git a/src/components/post_status_form/post_status_form.js b/src/components/post_status_form/post_status_form.js index 507d12f6c..049183575 100644 --- a/src/components/post_status_form/post_status_form.js +++ b/src/components/post_status_form/post_status_form.js @@ -15,6 +15,7 @@ import EmojiInput from '../emoji_input/emoji_input.vue' import suggestor from '../emoji_input/suggestor.js' import MediaUpload from '../media_upload/media_upload.vue' import PollForm from '../poll/poll_form.vue' +import QuoteForm from '../quote/quote_form.vue' import ScopeSelector from '../scope_selector/scope_selector.vue' import Select from '../select/select.vue' import StatusContent from '../status_content/status_content.vue' @@ -35,6 +36,7 @@ import { faChevronRight, faCircleNotch, faPollH, + faQuoteRight, faSmileBeam, faTimes, faUpload, @@ -44,6 +46,7 @@ library.add( faSmileBeam, faPollH, faUpload, + faQuoteRight, faBan, faTimes, faCircleNotch, @@ -105,6 +108,7 @@ const PostStatusForm = { 'disableNotice', 'disableLockWarning', 'disablePolls', + 'disableQuotes', 'disableSensitivityCheckbox', 'disableSubmit', 'disablePreview', @@ -136,6 +140,7 @@ const PostStatusForm = { MediaUpload, EmojiInput, PollForm, + QuoteForm, ScopeSelector, Checkbox, Select, @@ -145,6 +150,9 @@ const PostStatusForm = { DraftCloser, Popover, }, + created() { + this.initQuote() + }, mounted() { this.updateIdempotencyKey() this.resize(this.$refs.textarea) @@ -203,6 +211,8 @@ const PostStatusForm = { files: [], poll: {}, hasPoll: false, + hasQuote: false, + quote: {}, mediaDescriptions: {}, visibility: scope, contentType, @@ -220,6 +230,8 @@ const PostStatusForm = { files: this.statusFiles || [], poll: this.statusPoll || {}, hasPoll: false, + hasQuote: false, + quote: {}, mediaDescriptions: this.statusMediaDescriptions || {}, visibility: this.statusScope || scope, contentType: statusContentType, @@ -345,12 +357,28 @@ const PostStatusForm = { isEdit() { return typeof this.statusId !== 'undefined' && this.statusId.trim() !== '' }, - quotable() { + quotingAvailable() { if (!useInstanceCapabilitiesStore().quotingAvailable) { return false } - if (!this.replyTo) { + return this.disableQuotes !== true + }, + isReply() { + return this.newStatus.type === 'reply' + }, + quotable() { + return this.quotingAvailable && this.replyTo + }, + quoteThreadToggled() { + return this.newStatus.hasQuote && this.newStatus.quote.thread + }, + defaultQuotable() { + if ( + !this.quotingAvailable || + !this.isReply || + !this.$store.getters.mergedConfig.quoteReply + ) { return false } @@ -372,12 +400,25 @@ const PostStatusForm = { return false }, + inReplyStatusId() { + return !this.newStatus.hasQuote || + !this.newStatus.quote.thread || + !this.newStatus.quote.id + ? this.replyTo + : undefined + }, + quoteId() { + return this.newStatus.hasQuote ? this.newStatus.quote.id : undefined + }, debouncedMaybeAutoSaveDraft() { return debounce(this.maybeAutoSaveDraft, 3000) }, pollFormVisible() { return this.newStatus.hasPoll }, + quoteFormVisible() { + return this.newStatus.hasQuote && !this.newStatus.quote.thread + }, shouldAutoSaveDraft() { return this.$store.getters.mergedConfig.autoSaveDraft }, @@ -395,7 +436,8 @@ const PostStatusForm = { (this.newStatus.status || this.newStatus.spoilerText || this.newStatus.files?.length || - this.newStatus.hasPoll) && + this.newStatus.hasPoll || + this.newStatus.hasQuote) && this.saveable ) }, @@ -406,7 +448,8 @@ const PostStatusForm = { this.newStatus.status || this.newStatus.spoilerText || this.newStatus.files?.length || - this.newStatus.hasPoll + this.newStatus.hasPoll || + this.newStatus.hasQuote ) ) }, @@ -456,11 +499,13 @@ const PostStatusForm = { contentType: newStatus.contentType, poll: {}, hasPoll: false, + hasQuote: false, + quote: {}, mediaDescriptions: {}, - quoting: false, } this.$refs.mediaUpload && this.$refs.mediaUpload.clearFile() this.clearPollForm() + this.clearQuoteForm() if (this.preserveFocus) { this.$nextTick(() => { this.$refs.textarea.focus() @@ -500,9 +545,7 @@ const PostStatusForm = { return } - const poll = this.newStatus.hasPoll - ? pollFormToMasto(this.newStatus.poll) - : {} + const poll = newStatus.hasPoll ? pollFormToMasto(newStatus.poll) : {} if (this.pollContentError) { this.error = this.pollContentError return @@ -518,10 +561,6 @@ const PostStatusForm = { return } - const replyOrQuoteAttr = newStatus.quoting - ? 'quoteId' - : 'inReplyToStatusId' - const postingOptions = { status: newStatus.status, spoilerText: newStatus.spoilerText || null, @@ -529,7 +568,8 @@ const PostStatusForm = { sensitive: newStatus.nsfw, media: newStatus.files, store: this.$store, - [replyOrQuoteAttr]: this.replyTo, + inReplyToStatusId: this.inReplyStatusId, + quoteId: this.quoteId, contentType: newStatus.contentType, poll, idempotencyKey: this.idempotencyKey, @@ -558,9 +598,7 @@ const PostStatusForm = { } const newStatus = this.newStatus this.previewLoading = true - const replyOrQuoteAttr = newStatus.quoting - ? 'quoteId' - : 'inReplyToStatusId' + statusPoster .postStatus({ status: newStatus.status, @@ -569,7 +607,8 @@ const PostStatusForm = { sensitive: newStatus.nsfw, media: [], store: this.$store, - [replyOrQuoteAttr]: this.replyTo, + inReplyToStatusId: this.inReplyStatusId, + quoteId: this.quoteId, contentType: newStatus.contentType, poll: {}, preview: true, @@ -813,6 +852,32 @@ const PostStatusForm = { this.$refs.pollForm.clear() } }, + initQuote() { + const quote = this.newStatus.quote + + if (Object.keys(quote).length > 0) { + return + } + + const quotable = this.defaultQuotable + + quote.id = quotable ? this.replyTo : '' + quote.url = '' + quote.thread = quotable + }, + setQuoteThread(v) { + this.newStatus.hasQuote = v + this.newStatus.quote.thread = v + this.newStatus.quote.id = v ? this.replyTo : '' + }, + clearQuoteForm() { + if (this.$refs.quoteForm) { + this.$refs.quoteForm.clear() + } + }, + toggleQuoteForm() { + this.newStatus.hasQuote = !this.newStatus.hasQuote + }, dismissScopeNotice() { this.$store.dispatch('setOption', { name: 'hideScopeNotice', diff --git a/src/components/post_status_form/post_status_form.scss b/src/components/post_status_form/post_status_form.scss index 641dc6dac..976a23f0a 100644 --- a/src/components/post_status_form/post_status_form.scss +++ b/src/components/post_status_form/post_status_form.scss @@ -137,11 +137,17 @@ .poll-icon { order: 3; + justify-content: center; + } + + .quote-icon { + order: 4; justify-content: right; } .media-upload-icon, .poll-icon, + .quote-icon, .emoji-icon { font-size: 1.85em; line-height: 1.1; diff --git a/src/components/post_status_form/post_status_form.vue b/src/components/post_status_form/post_status_form.vue index f661a980d..0eedea360 100644 --- a/src/components/post_status_form/post_status_form.vue +++ b/src/components/post_status_form/post_status_form.vue @@ -111,24 +111,26 @@ @@ -266,6 +268,13 @@ :visible="pollFormVisible" :params="newStatus.poll" /> + +
    - - -

    - - - -

    +
    { if (data.ok) { return data } - throw new Error('Error fetching timeline', data) + throw new Error('Error fetching timeline', { cause: data }) }) .then((data) => data.json()) .then((data) => parseStatus(data)) @@ -706,7 +706,7 @@ const fetchStatusSource = ({ id, credentials }) => { if (data.ok) { return data } - throw new Error('Error fetching source', data) + throw new Error('Error fetching source', { cause: data }) }) .then((data) => data.json()) .then((data) => parseSource(data)) diff --git a/src/services/entity_normalizer/entity_normalizer.service.js b/src/services/entity_normalizer/entity_normalizer.service.js index 62d7fa855..909a014ce 100644 --- a/src/services/entity_normalizer/entity_normalizer.service.js +++ b/src/services/entity_normalizer/entity_normalizer.service.js @@ -383,7 +383,7 @@ export const parseStatus = (data) => { } output.summary_raw_html = escapeHtml(data.spoiler_text) - output.external_url = data.url + output.external_url = data.uri || data.url output.poll = data.poll if (output.poll) { output.poll.options = (output.poll.options || []).map((field) => ({ From 9610811558ec68431040da9eec2476c104f6966e Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Thu, 23 Apr 2026 21:55:07 +0300 Subject: [PATCH 5/5] cleanup console.log --- src/components/mrf_transparency_panel/mrf_transparency_panel.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/mrf_transparency_panel/mrf_transparency_panel.js b/src/components/mrf_transparency_panel/mrf_transparency_panel.js index b387bcf4c..d77a0a839 100644 --- a/src/components/mrf_transparency_panel/mrf_transparency_panel.js +++ b/src/components/mrf_transparency_panel/mrf_transparency_panel.js @@ -24,7 +24,6 @@ const MRFTransparencyPanel = { mrfPolicies: (state) => get(state, 'federationPolicy.mrf_policies', []), quarantineInstances: (state) => - console.log(state) || toInstanceReasonObject( get(state, 'federationPolicy.quarantined_instances', []), get(