diff --git a/changelog.d/mute-dropdown.fix b/changelog.d/mute-dropdown.fix deleted file mode 100644 index 33f12a571..000000000 --- a/changelog.d/mute-dropdown.fix +++ /dev/null @@ -1 +0,0 @@ -Fixed status action mute hiding itself on click diff --git a/changelog.d/quote-by-url.add b/changelog.d/quote-by-url.add deleted file mode 100644 index ef401f93c..000000000 --- a/changelog.d/quote-by-url.add +++ /dev/null @@ -1 +0,0 @@ -Add quoting by URL and in replies diff --git a/src/components/chat/chat.vue b/src/components/chat/chat.vue index cedbdce69..dfd197e56 100644 --- a/src/components/chat/chat.vue +++ b/src/components/chat/chat.vue @@ -73,7 +73,6 @@ :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 45786614e..ffc299af6 100644 --- a/src/components/draft/draft.js +++ b/src/components/draft/draft.js @@ -45,12 +45,7 @@ const Draft = { } }, safeToSave() { - return ( - this.draft.status || - this.draft.files?.length || - this.draft.hasPoll || - this.draft.hasQuote - ) + return this.draft.status || this.draft.files?.length || this.draft.hasPoll }, 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 1452be422..0a7ec760a 100644 --- a/src/components/edit_status_form/edit_status_form.vue +++ b/src/components/edit_status_form/edit_status_form.vue @@ -4,7 +4,6 @@ v-bind="params" :post-handler="doEditStatus" :disable-polls="true" - :disable-quotes="true" :disable-visibility-selector="true" /> diff --git a/src/components/mrf_transparency_panel/mrf_transparency_panel.js b/src/components/mrf_transparency_panel/mrf_transparency_panel.js index d77a0a839..b387bcf4c 100644 --- a/src/components/mrf_transparency_panel/mrf_transparency_panel.js +++ b/src/components/mrf_transparency_panel/mrf_transparency_panel.js @@ -24,6 +24,7 @@ const MRFTransparencyPanel = { mrfPolicies: (state) => get(state, 'federationPolicy.mrf_policies', []), quarantineInstances: (state) => + console.log(state) || toInstanceReasonObject( get(state, 'federationPolicy.quarantined_instances', []), get( diff --git a/src/components/post_status_form/post_status_form.js b/src/components/post_status_form/post_status_form.js index d08a8b9c2..7ebbeeaeb 100644 --- a/src/components/post_status_form/post_status_form.js +++ b/src/components/post_status_form/post_status_form.js @@ -15,7 +15,6 @@ 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' @@ -38,7 +37,6 @@ import { faChevronRight, faCircleNotch, faPollH, - faQuoteRight, faSmileBeam, faTimes, faUpload, @@ -48,7 +46,6 @@ library.add( faSmileBeam, faPollH, faUpload, - faQuoteRight, faBan, faTimes, faCircleNotch, @@ -110,7 +107,6 @@ const PostStatusForm = { 'disableNotice', 'disableLockWarning', 'disablePolls', - 'disableQuotes', 'disableSensitivityCheckbox', 'disableSubmit', 'disablePreview', @@ -142,7 +138,6 @@ const PostStatusForm = { MediaUpload, EmojiInput, PollForm, - QuoteForm, ScopeSelector, Checkbox, Select, @@ -152,9 +147,6 @@ const PostStatusForm = { DraftCloser, Popover, }, - created() { - this.initQuote() - }, mounted() { this.updateIdempotencyKey() this.resize(this.$refs.textarea) @@ -213,8 +205,6 @@ const PostStatusForm = { files: [], poll: {}, hasPoll: false, - hasQuote: false, - quote: {}, mediaDescriptions: {}, visibility: scope, contentType, @@ -232,8 +222,6 @@ const PostStatusForm = { files: this.statusFiles || [], poll: this.statusPoll || {}, hasPoll: false, - hasQuote: false, - quote: {}, mediaDescriptions: this.statusMediaDescriptions || {}, visibility: this.statusScope || scope, contentType: statusContentType, @@ -360,28 +348,12 @@ const PostStatusForm = { isEdit() { return typeof this.statusId !== 'undefined' && this.statusId.trim() !== '' }, - quotingAvailable() { + quotable() { if (!useInstanceCapabilitiesStore().quotingAvailable) { return false } - 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 - ) { + if (!this.replyTo) { return false } @@ -403,25 +375,12 @@ 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 useMergedConfigStore().mergedConfig.autoSaveDraft }, @@ -439,8 +398,7 @@ const PostStatusForm = { (this.newStatus.status || this.newStatus.spoilerText || this.newStatus.files?.length || - this.newStatus.hasPoll || - this.newStatus.hasQuote) && + this.newStatus.hasPoll) && this.saveable ) }, @@ -451,8 +409,7 @@ const PostStatusForm = { this.newStatus.status || this.newStatus.spoilerText || this.newStatus.files?.length || - this.newStatus.hasPoll || - this.newStatus.hasQuote + this.newStatus.hasPoll ) ) }, @@ -502,13 +459,11 @@ 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() @@ -548,7 +503,9 @@ const PostStatusForm = { return } - const poll = newStatus.hasPoll ? pollFormToMasto(newStatus.poll) : {} + const poll = this.newStatus.hasPoll + ? pollFormToMasto(this.newStatus.poll) + : {} if (this.pollContentError) { this.error = this.pollContentError return @@ -564,6 +521,10 @@ const PostStatusForm = { return } + const replyOrQuoteAttr = newStatus.quoting + ? 'quoteId' + : 'inReplyToStatusId' + const postingOptions = { status: newStatus.status, spoilerText: newStatus.spoilerText || null, @@ -571,8 +532,7 @@ const PostStatusForm = { sensitive: newStatus.nsfw, media: newStatus.files, store: this.$store, - inReplyToStatusId: this.inReplyStatusId, - quoteId: this.quoteId, + [replyOrQuoteAttr]: this.replyTo, contentType: newStatus.contentType, poll, idempotencyKey: this.idempotencyKey, @@ -601,7 +561,9 @@ const PostStatusForm = { } const newStatus = this.newStatus this.previewLoading = true - + const replyOrQuoteAttr = newStatus.quoting + ? 'quoteId' + : 'inReplyToStatusId' statusPoster .postStatus({ status: newStatus.status, @@ -610,8 +572,7 @@ const PostStatusForm = { sensitive: newStatus.nsfw, media: [], store: this.$store, - inReplyToStatusId: this.inReplyStatusId, - quoteId: this.quoteId, + [replyOrQuoteAttr]: this.replyTo, contentType: newStatus.contentType, poll: {}, preview: true, @@ -855,32 +816,6 @@ 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() { useSyncConfigStore().setSimplePrefAndSave({ path: 'hideScopeNotice', diff --git a/src/components/post_status_form/post_status_form.scss b/src/components/post_status_form/post_status_form.scss index 684a92267..c7fdb0806 100644 --- a/src/components/post_status_form/post_status_form.scss +++ b/src/components/post_status_form/post_status_form.scss @@ -136,17 +136,11 @@ .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 5fdde4784..fe37394f5 100644 --- a/src/components/post_status_form/post_status_form.vue +++ b/src/components/post_status_form/post_status_form.vue @@ -115,26 +115,24 @@ {{ $t('post_status.reply_option') }} {{ $t('post_status.quote_option') }} @@ -272,13 +270,6 @@ :visible="pollFormVisible" :params="newStatus.poll" /> - - - - import('../status/status.vue')), - }, - name: 'Quote', - props: { - visible: { - type: Boolean, - }, - loading: { - type: Boolean, - }, - statusId: { - type: String, - }, - statusUrl: { - type: String, - }, - statusVisible: { - type: Boolean, - }, - initiallyExpanded: { - type: Boolean, - }, - }, - data() { - return { - displayQuote: this.initiallyExpanded, - fetchAttempted: false, - fetching: false, - error: null, - } - }, - created() { - this.maybeFetchStatus() - }, - watch: { - statusId() { - this.maybeFetchStatus() - }, - }, - computed: { - quotedStatus() { - return this.statusId - ? this.$store.state.statuses.allStatusesObject[this.statusId] - : undefined - }, - shouldDisplayQuote() { - return this.displayQuote && this.quotedStatus - }, - hasVisibleQuote() { - return ( - this.statusUrl && - this.statusVisible && - (this.showSpinner || this.quotedStatus) - ) - }, - hasInvisibleQuote() { - return this.statusUrl && !this.statusVisible - }, - showSpinner() { - return this.loading || this.fetching - }, - }, - methods: { - toggleDisplayQuote() { - this.displayQuote = !this.displayQuote - this.maybeFetchStatus() - }, - maybeFetchStatus() { - if (this.statusId && this.displayQuote && !this.quotedStatus) { - this.fetchStatus() - } - }, - fetchStatus() { - this.fetchAttempted = true - this.fetching = true - this.$emit('loading', true) - this.$store - .dispatch('fetchStatus', this.statusId) - .then(() => { - this.displayQuote = true - }) - .catch((error) => { - this.error = error - this.$emit('error', error) - }) - .finally(() => { - this.fetching = false - this.$emit('loading', false) - }) - }, - }, -} diff --git a/src/components/quote/quote.vue b/src/components/quote/quote.vue deleted file mode 100644 index f518db7ab..000000000 --- a/src/components/quote/quote.vue +++ /dev/null @@ -1,82 +0,0 @@ - - - - {{ shouldDisplayQuote ? $t('status.hide_quote') : $t('status.display_quote') }} - - - - - - - - - - - - - {{ statusUrl }} - - - {{ statusUrl }} - - - - - - - - - - diff --git a/src/components/quote/quote_form.js b/src/components/quote/quote_form.js deleted file mode 100644 index 401211724..000000000 --- a/src/components/quote/quote_form.js +++ /dev/null @@ -1,118 +0,0 @@ -import { debounce } from 'lodash' - -import Checkbox from '../checkbox/checkbox.vue' -import Quote from './quote.vue' - -import { useInstanceStore } from 'src/stores/instance.js' - -export default { - components: { - Quote, - Checkbox, - }, - name: 'QuoteForm', - props: { - visible: { - type: Boolean, - }, - reply: { - type: Boolean, - }, - params: { - type: Object, - required: true, - }, - }, - data() { - return { - text: this.params.url, - loading: false, - error: false, - debounceSetQuote: debounce((value) => { - this.fetchStatus(value) - }, 1000), - } - }, - created() { - if (this.params.url && !this.params.id) { - this.fetchStatus(this.params.url) - } else if (this.params.id) { - this.text = - window.location.protocol + - '//' + - this.instanceHost + - '/notice/' + - this.params.id - this.params.url = this.text - } - }, - computed: { - instanceHost() { - return new URL(useInstanceStore().server).host - }, - noticeRegex() { - return new RegExp( - `^([^/:]*:?//|)(${window.location.host}|${this.instanceHost})/notice/(.*)$`, - ) - }, - quoteVisible() { - return (!!this.params.id || this.loading) && !this.error - }, - }, - watch: { - text(value) { - this.debounceSetQuote(value) - }, - visible(value) { - if (value && this.params.url) { - this.fetchStatus(this.params.url) - } - }, - }, - methods: { - clear() { - this.text = this.params.url - this.loading = false - this.error = false - }, - setLoading(value) { - this.loading = value - }, - handleError(error) { - this.params.id = null - this.error = !!error - }, - fetchStatus(value) { - this.params.url = value - this.error = false - - const notice = this.noticeRegex.exec(value) - if (notice && notice.length === 4) { - this.params.id = notice[3] - } else if (value) { - this.loading = true - this.$store - .dispatch('search', { - q: value, - resolve: true, - offset: 0, - limit: 1, - type: 'statuses', - }) - .then((data) => { - if (data && data.statuses && data.statuses.length === 1) { - this.params.id = data.statuses[0].id - } else { - this.handleError(true) - } - }) - .catch(this.handleError) - .finally(() => { - this.loading = false - }) - } else { - this.params.id = null - } - }, - }, -} diff --git a/src/components/quote/quote_form.vue b/src/components/quote/quote_form.vue deleted file mode 100644 index b0b277a2b..000000000 --- a/src/components/quote/quote_form.vue +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - - - - diff --git a/src/components/status/status.js b/src/components/status/status.js index 7b4a31561..b24146d9d 100644 --- a/src/components/status/status.js +++ b/src/components/status/status.js @@ -12,7 +12,6 @@ import { import AvatarList from '../avatar_list/avatar_list.vue' import EmojiReactions from '../emoji_reactions/emoji_reactions.vue' import PostStatusForm from '../post_status_form/post_status_form.vue' -import Quote from '../quote/quote.vue' import StatusContent from '../status_content/status_content.vue' import StatusPopover from '../status_popover/status_popover.vue' import Timeago from '../timeago/timeago.vue' @@ -130,7 +129,6 @@ const Status = { MentionsLine, UserPopover, UserLink, - Quote, StatusActionButtons, }, props: [ @@ -176,6 +174,7 @@ const Status = { suspendable: true, error: null, headTailLinks: null, + displayQuote: !this.inQuote, } }, computed: { @@ -499,17 +498,19 @@ const Status = { editingAvailable() { return useInstanceCapabilitiesStore().editingAvailable }, - quoteId() { + hasVisibleQuote() { + return this.status.quote_url && this.status.quote_visible + }, + hasInvisibleQuote() { + return this.status.quote_url && !this.status.quote_visible + }, + quotedStatus() { return this.status.quote_id + ? this.$store.state.statuses.allStatusesObject[this.status.quote_id] + : undefined }, - quoteUrl() { - return this.status.quote_url - }, - quoteVisible() { - return this.status.quote_visible - }, - quoteExpanded() { - return !this.inQuote + shouldDisplayQuote() { + return this.quotedStatus && this.displayQuote }, scrobblePresent() { if (this.mergedConfig.hideScrobbles) return false @@ -629,6 +630,17 @@ const Status = { } } }, + toggleDisplayQuote() { + if (this.shouldDisplayQuote) { + this.displayQuote = false + } else if (!this.quotedStatus) { + this.$store.dispatch('fetchStatus', this.status.quote_id).then(() => { + this.displayQuote = true + }) + } else { + this.displayQuote = true + } + }, }, watch: { highlight: function (id) { diff --git a/src/components/status/status.scss b/src/components/status/status.scss index 2a40f0dde..897730a07 100644 --- a/src/components/status/status.scss +++ b/src/components/status/status.scss @@ -388,4 +388,22 @@ } } } + + .quoted-status { + margin-top: 0.5em; + border: 1px solid var(--border); + border-radius: var(--roundness); + + &.-unavailable-prompt { + padding: 0.5em; + } + } + + .display-quoted-status-button { + margin: 0.5em; + + &-icon { + color: inherit; + } + } } diff --git a/src/components/status/status.vue b/src/components/status/status.vue index 015a7017c..9351d53c8 100644 --- a/src/components/status/status.vue +++ b/src/components/status/status.vue @@ -420,12 +420,47 @@ @parse-ready="setHeadTailLinks" /> - + + + {{ shouldDisplayQuote ? $t('status.hide_quote') : $t('status.display_quote') }} + + + + + + + + + + {{ status.quote_url }} + + + + + loggedIn, - toggleable: false, + toggleable: true, dropdown: true, - action({ status, dispatch, emit }) { - /* prevent hiding */ - }, + // action ({ status, dispatch, emit }) { + // } }, { // ========= diff --git a/src/components/status_action_buttons/status_action_buttons.scss b/src/components/status_action_buttons/status_action_buttons.scss index 3bbcdeefb..23b86e5bd 100644 --- a/src/components/status_action_buttons/status_action_buttons.scss +++ b/src/components/status_action_buttons/status_action_buttons.scss @@ -6,7 +6,7 @@ grid-template-columns: repeat(auto-fill, minmax(10%, 3em)); grid-auto-flow: row dense; grid-auto-rows: 1fr; - grid-gap: 1.25em 0; + grid-gap: 1.25em 1em; margin-top: var(--status-margin); } diff --git a/src/i18n/en.json b/src/i18n/en.json index 7851c297c..0165af240 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -284,7 +284,6 @@ "new_status": "Post new status", "reply_option": "Reply to this status", "quote_option": "Quote this status", - "quote_url": "Link to quoted post", "account_not_locked_warning": "Your account is not {0}. Anyone can follow you to view your follower-only posts.", "account_not_locked_warning_link": "locked", "attachments_sensitive": "Mark attachments as sensitive", @@ -1766,7 +1765,6 @@ "favorite": "Favorite", "unfavorite": "Unfavorite", "add_reaction": "Add Reaction", - "add_quote": "Add quote", "user_settings": "User Settings", "accept_follow_request": "Accept follow request", "reject_follow_request": "Reject follow request", diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js index 2e2ca5a5c..48f8b9e8a 100644 --- a/src/services/api/api.service.js +++ b/src/services/api/api.service.js @@ -693,7 +693,7 @@ const fetchStatus = ({ id, credentials }) => { if (data.ok) { return data } - throw new Error('Error fetching timeline', { cause: data }) + throw new Error('Error fetching timeline', 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', { cause: data }) + throw new Error('Error fetching source', 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 8fb98bc9b..bcc27e8cb 100644 --- a/src/services/entity_normalizer/entity_normalizer.service.js +++ b/src/services/entity_normalizer/entity_normalizer.service.js @@ -384,7 +384,7 @@ export const parseStatus = (data) => { } output.summary_raw_html = escapeHtml(data.spoiler_text) - output.external_url = data.uri || data.url + output.external_url = data.url output.poll = data.poll if (output.poll) { output.poll.options = (output.poll.options || []).map((field) => ({
- - - - - {{ statusUrl }} - - - {{ statusUrl }} - - - - -
+ + + + + {{ status.quote_url }} + + + + +