diff --git a/build/check-versions.mjs b/build/check-versions.mjs index 8c5968a30..c22004b00 100644 --- a/build/check-versions.mjs +++ b/build/check-versions.mjs @@ -36,7 +36,6 @@ export default function () { const warning = warnings[i] console.warn(' ' + warning) } - console.warn() process.exit(1) } } diff --git a/changelog.d/minor.add b/changelog.d/minor.add new file mode 100644 index 000000000..5f4934173 --- /dev/null +++ b/changelog.d/minor.add @@ -0,0 +1,6 @@ +button to remove all drafts +option to remove forced aspect ratio for user profiles (requested) +showing user tags (mrf policies for user + custom if present) +version information now is also in about page +mention autosuggest now sorts by recent activity +non-square emoji support (toggleable by user) diff --git a/changelog.d/minor.change b/changelog.d/minor.change new file mode 100644 index 000000000..979d36955 --- /dev/null +++ b/changelog.d/minor.change @@ -0,0 +1,7 @@ +overall improved spacings in status action buttons and post form +logout confirm button is now dangerous +reply/quote now is a radio group and wraps, fixes overflow on languages where labels are too wide +personal note input is now bigger +moved "edit pinned" to the bottom for status action buttons. +dots status action button drops down instead of up to avoid hiding the action buttons +improved attachment description (alt text) input and display diff --git a/changelog.d/minor.fix b/changelog.d/minor.fix new file mode 100644 index 000000000..420836364 --- /dev/null +++ b/changelog.d/minor.fix @@ -0,0 +1,12 @@ +navbar wide logo cropping search input +danger buttons being too bright +user background upload failure no longer breaks new uploads + displays an error +importing theme from old theme editor +removed duplicate federationpolicy entry in admin tab +repeater name overflowing content +reply popover is now shown if replied-to status is muted +second language input not having header +post form's bottom left buttons not showing their toggled state +some font overrides not working +popovers opening outside of window's boundaries +occasional blank page when showing new posts diff --git a/changelog.d/sync-config.add b/changelog.d/sync-config.add new file mode 100644 index 000000000..76a5a1cca --- /dev/null +++ b/changelog.d/sync-config.add @@ -0,0 +1,2 @@ +settings synchronization +user highlight synchronization diff --git a/src/App.js b/src/App.js index 487090565..9fb4d32e5 100644 --- a/src/App.js +++ b/src/App.js @@ -67,6 +67,11 @@ export default { data: () => ({ mobileActivePanel: 'timeline', }), + provide() { + return { + allowNonSquareEmoji: useMergedConfigStore().mergedConfig.nonSquareEmoji, + } + }, watch: { themeApplied() { this.removeSplash() diff --git a/src/App.scss b/src/App.scss index b36e702d5..56fef9d11 100644 --- a/src/App.scss +++ b/src/App.scss @@ -50,7 +50,7 @@ body { // have a cursor/pointer to operate them @media (any-pointer: fine) { * { - scrollbar-color: var(--fg) transparent; + scrollbar-color: var(--icon) transparent; &::-webkit-scrollbar { background: transparent; @@ -130,7 +130,7 @@ body { } // Body should have background to scrollbar otherwise it will use white (body color?) html { - scrollbar-color: var(--fg) var(--wallpaper); + scrollbar-color: var(--icon) var(--wallpaper); background: var(--wallpaper); } } @@ -787,6 +787,19 @@ option { padding: 0 0.25em; border-radius: var(--roundness); border: 1px solid var(--border); + + &.-dismissible { + display: flex; + padding-left: 0.5em; + margin: 0; + align-items: baseline; + line-height: 2; + + span { + display: block; + flex: 1 0 auto; + } + } } .faint { @@ -802,9 +815,11 @@ option { align-items: baseline; line-height: 1.5; + p, span { display: block; flex: 1 1 auto; + margin: 0; } .dismiss { diff --git a/src/App.vue b/src/App.vue index f432d8bc4..c1a7199d7 100644 --- a/src/App.vue +++ b/src/App.vue @@ -28,10 +28,10 @@ > diff --git a/src/boot/after_store.js b/src/boot/after_store.js index d16852bf8..a3d8701e5 100644 --- a/src/boot/after_store.js +++ b/src/boot/after_store.js @@ -152,8 +152,10 @@ const getStaticConfig = async () => { throw res } } catch (error) { - console.warn('Failed to load static/config.json, continuing without it.') - console.warn(error) + console.warn( + 'Failed to load static/config.json, continuing without it.', + error, + ) return {} } } @@ -175,14 +177,16 @@ const setSettings = async ({ apiConfig, staticConfig, store }) => { if (source === 'name') return if (INSTANCE_IDENTIY_EXTERNAL.has(source)) return useInstanceStore().set({ - value: config[source], + value: + config[source] ?? INSTANCE_IDENTITY_DEFAULT_DEFINITIONS[source].default, path: `instanceIdentity.${source}`, }) }) Object.keys(INSTANCE_DEFAULT_CONFIG_DEFINITIONS).forEach((source) => useInstanceStore().set({ - value: config[source], + value: + config[source] ?? INSTANCE_DEFAULT_CONFIG_DEFINITIONS[source].default, path: `prefsStorage.${source}`, }), ) @@ -440,8 +444,7 @@ const getNodeInfo = async ({ store }) => { throw res } } catch (e) { - console.warn('Could not load nodeinfo') - console.warn(e) + console.warn('Could not load nodeinfo', e) } } diff --git a/src/components/about/about.js b/src/components/about/about.js index 404843e8b..e6a1067fe 100644 --- a/src/components/about/about.js +++ b/src/components/about/about.js @@ -1,3 +1,5 @@ +import { mapState } from 'pinia' + import FeaturesPanel from '../features_panel/features_panel.vue' import InstanceSpecificPanel from '../instance_specific_panel/instance_specific_panel.vue' import MRFTransparencyPanel from '../mrf_transparency_panel/mrf_transparency_panel.vue' @@ -7,6 +9,9 @@ import TermsOfServicePanel from '../terms_of_service_panel/terms_of_service_pane import { useInstanceStore } from 'src/stores/instance.js' import { useMergedConfigStore } from 'src/stores/merged_config.js' +const pleromaFeCommitUrl = + 'https://git.pleroma.social/pleroma/pleroma-fe/commit/' + const About = { components: { InstanceSpecificPanel, @@ -19,6 +24,14 @@ const About = { showFeaturesPanel() { return useInstanceStore().instanceIdentity.showFeaturesPanel }, + frontendVersionLink() { + return pleromaFeCommitUrl + this.frontendVersion + }, + ...mapState(useInstanceStore, [ + 'backendVersion', + 'backendRepository', + 'frontendVersion', + ]), showInstanceSpecificPanel() { return ( useInstanceStore().instanceIdentity.showInstanceSpecificPanel && diff --git a/src/components/about/about.vue b/src/components/about/about.vue index 8a551485f..f7bc0d00d 100644 --- a/src/components/about/about.vue +++ b/src/components/about/about.vue @@ -1,11 +1,47 @@ + diff --git a/src/components/attachment/attachment.js b/src/components/attachment/attachment.js index fbe77a687..d29d22f4a 100644 --- a/src/components/attachment/attachment.js +++ b/src/components/attachment/attachment.js @@ -2,6 +2,7 @@ import { mapState } from 'pinia' import nsfwImage from '../../assets/nsfw.png' import Flash from '../flash/flash.vue' +import Popover from '../popover/popover.vue' import StillImage from '../still-image/still-image.vue' import VideoAttachment from '../video_attachment/video_attachment.vue' @@ -65,13 +66,13 @@ const Attachment = { modalOpen: false, showHidden: false, flashLoaded: false, - showDescription: false, } }, components: { Flash, StillImage, VideoAttachment, + Popover, }, computed: { classNames() { @@ -180,9 +181,6 @@ const Attachment = { setFlashLoaded(event) { this.flashLoaded = event }, - toggleDescription() { - this.showDescription = !this.showDescription - }, toggleHidden(event) { if ( this.mergedConfig.useOneClickNsfw && diff --git a/src/components/attachment/attachment.scss b/src/components/attachment/attachment.scss index 97515eb32..3c3ba7751 100644 --- a/src/components/attachment/attachment.scss +++ b/src/components/attachment/attachment.scss @@ -134,7 +134,7 @@ width: 2em; height: 2em; margin-left: 0.5em; - font-size: 1.25em; + font-size: 1em; } } @@ -265,3 +265,27 @@ } } } + +.description-popover { + padding: 1em; + width: 50ch; + max-width: 90vw; + overflow: hidden; + box-sizing: border-box; + + summary { + display: inline-block; + margin-bottom: 0.5em; + font-weight: bold; + pointer-events: none; + } + + span { + display: block; + overflow-y: auto; + max-height: 10.5em; + text-wrap: pretty; + line-height: 1.5; + white-space: pre-wrap; + } +} diff --git a/src/components/attachment/attachment.vue b/src/components/attachment/attachment.vue index 0db86ff8a..1a1b84628 100644 --- a/src/components/attachment/attachment.vue +++ b/src/components/attachment/attachment.vue @@ -30,21 +30,16 @@
- -

- {{ localDescription }} -

+ />
- + + +
- -

- {{ localDescription }} -

+ />
diff --git a/src/components/basic_user_card/basic_user_card.js b/src/components/basic_user_card/basic_user_card.js index 0e45b140a..722d459f3 100644 --- a/src/components/basic_user_card/basic_user_card.js +++ b/src/components/basic_user_card/basic_user_card.js @@ -4,6 +4,7 @@ import UserLink from '../user_link/user_link.vue' import UserPopover from '../user_popover/user_popover.vue' import { useInstanceStore } from 'src/stores/instance.js' +import { useMergedConfigStore } from 'src/stores/merged_config.js' import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator' @@ -24,6 +25,11 @@ const BasicUserCard = { ) }, }, + computed: { + allowNonSquareEmoji() { + return useMergedConfigStore().mergedConfig.nonSquareEmoji + }, + }, } export default BasicUserCard diff --git a/src/components/basic_user_card/basic_user_card.vue b/src/components/basic_user_card/basic_user_card.vue index 29a60cd1e..572b07abb 100644 --- a/src/components/basic_user_card/basic_user_card.vue +++ b/src/components/basic_user_card/basic_user_card.vue @@ -27,6 +27,7 @@ class="basic-user-card-user-name-value" :html="user.name" :emoji="user.emoji" + :allow-non-square-emoji="allowNonSquareEmoji" />
diff --git a/src/components/button.style.js b/src/components/button.style.js index 3fb308b89..1644accc4 100644 --- a/src/components/button.style.js +++ b/src/components/button.style.js @@ -54,7 +54,7 @@ export default { { variant: 'danger', directives: { - background: '--cRed', + background: '$blend(--cRed 0.25 --inheritedBackground)', }, }, { diff --git a/src/components/chat_title/chat_title.js b/src/components/chat_title/chat_title.js index 3447f5163..54a31a6fe 100644 --- a/src/components/chat_title/chat_title.js +++ b/src/components/chat_title/chat_title.js @@ -3,6 +3,8 @@ import { defineAsyncComponent } from 'vue' import RichContent from 'src/components/rich_content/rich_content.jsx' import UserAvatar from '../user_avatar/user_avatar.vue' +import { useMergedConfigStore } from 'src/stores/merged_config.js' + export default { name: 'ChatTitle', components: { @@ -20,5 +22,8 @@ export default { htmlTitle() { return this.user ? this.user.name_html : '' }, + allowNonSquareEmoji() { + return useMergedConfigStore().mergedConfig.nonSquareEmoji + }, }, } diff --git a/src/components/chat_title/chat_title.vue b/src/components/chat_title/chat_title.vue index 00521260f..313e66ce3 100644 --- a/src/components/chat_title/chat_title.vue +++ b/src/components/chat_title/chat_title.vue @@ -19,6 +19,7 @@ :title="'@'+(user && user.screen_name_ui)" :html="htmlTitle" :emoji="user.emoji || []" + :allow-non-square-emoji="allowNonSquareEmoji" :is-local="user.is_local" />
diff --git a/src/components/checkbox/checkbox.vue b/src/components/checkbox/checkbox.vue index cbe3dd80f..4a3ea49bc 100644 --- a/src/components/checkbox/checkbox.vue +++ b/src/components/checkbox/checkbox.vue @@ -61,12 +61,14 @@ export default { diff --git a/src/components/color_input/color_input.vue b/src/components/color_input/color_input.vue index 6f236d35f..07aed6b81 100644 --- a/src/components/color_input/color_input.vue +++ b/src/components/color_input/color_input.vue @@ -88,6 +88,7 @@ export default { label: { required: false, type: String, + default: '', }, // use unstyled, uh, style unstyled: { diff --git a/src/components/confirm_modal/confirm_modal.js b/src/components/confirm_modal/confirm_modal.js index cd83194be..affad7dcb 100644 --- a/src/components/confirm_modal/confirm_modal.js +++ b/src/components/confirm_modal/confirm_modal.js @@ -21,6 +21,9 @@ const ConfirmModal = { confirmText: { type: String, }, + confirmDanger: { + type: Boolean, + }, }, emits: ['cancelled', 'accepted'], computed: {}, diff --git a/src/components/confirm_modal/confirm_modal.vue b/src/components/confirm_modal/confirm_modal.vue index 992792ede..7e1a7ff68 100644 --- a/src/components/confirm_modal/confirm_modal.vue +++ b/src/components/confirm_modal/confirm_modal.vue @@ -14,6 +14,7 @@ - - - + this.hideConfirmDialog()) + }, + hideConfirmDialog() { + this.showingConfirmDialog = false + }, + }, } export default Drafts diff --git a/src/components/drafts/drafts.vue b/src/components/drafts/drafts.vue index 1cce255da..2e3f3432c 100644 --- a/src/components/drafts/drafts.vue +++ b/src/components/drafts/drafts.vue @@ -13,36 +13,66 @@ > {{ $t('drafts.no_drafts') }} - - - + + + + {{ $t('drafts.abandon_all_confirm') }} + + diff --git a/src/components/emoji_input/emoji_input.js b/src/components/emoji_input/emoji_input.js index 0146a3de8..0cce2494d 100644 --- a/src/components/emoji_input/emoji_input.js +++ b/src/components/emoji_input/emoji_input.js @@ -333,7 +333,6 @@ const EmojiInput = { if (!this.pickerShown) { this.scrollIntoView() this.$refs.picker.showPicker() - this.$refs.picker.startEmojiLoad() } else { this.$refs.picker.hidePicker() } @@ -590,7 +589,7 @@ const EmojiInput = { setCaret({ target: { selectionStart } }) { this.caret = selectionStart this.$nextTick(() => { - this.$refs.suggestorPopover.updateStyles() + this.$refs.suggestorPopover?.updateStyles() }) }, autoCompleteItemLabel(suggestion) { diff --git a/src/components/emoji_input/emoji_input.vue b/src/components/emoji_input/emoji_input.vue index a1cba33bc..526f646ab 100644 --- a/src/components/emoji_input/emoji_input.vue +++ b/src/components/emoji_input/emoji_input.vue @@ -2,7 +2,7 @@
{ const diff = (bScore - aScore) * 10 // Then sort alphabetically + const activity = a.last_status_at < b.last_status_at ? 100 : -100 const nameAlphabetically = a.name > b.name ? 1 : -1 const screenNameAlphabetically = a.screen_name > b.screen_name ? 1 : -1 - return diff + nameAlphabetically + screenNameAlphabetically + return diff + nameAlphabetically + screenNameAlphabetically + activity }) .map((user) => ({ user, diff --git a/src/components/emoji_picker/emoji_picker.js b/src/components/emoji_picker/emoji_picker.js index 1d19987ac..36b669622 100644 --- a/src/components/emoji_picker/emoji_picker.js +++ b/src/components/emoji_picker/emoji_picker.js @@ -129,6 +129,7 @@ const EmojiPicker = { hideCustomEmojiInPicker: false, // Lazy-load only after the first time `showing` becomes true. contentLoaded: false, + popoverShown: false, groupRefs: {}, emojiRefs: {}, filteredEmojiGroups: [], @@ -176,6 +177,13 @@ const EmojiPicker = { const fullEmojiSize = emojiSizeReal + 2 * 0.2 * fontSizeMultiplier * 14 this.emojiSize = fullEmojiSize }, + togglePicker() { + if (this.popoverShown) { + this.hidePicker() + } else { + this.showPicker() + } + }, showPicker() { this.$refs.popover.showPopover() this.$nextTick(() => { @@ -194,10 +202,10 @@ const EmojiPicker = { } }, onPopoverShown() { - this.$emit('show') + this.popoverShown = true }, onPopoverClosed() { - this.$emit('close') + this.popoverShown = false }, onStickerUploaded(e) { this.$emit('sticker-uploaded', e) diff --git a/src/components/emoji_picker/emoji_picker.vue b/src/components/emoji_picker/emoji_picker.vue index dae5ff871..67f40c945 100644 --- a/src/components/emoji_picker/emoji_picker.vue +++ b/src/components/emoji_picker/emoji_picker.vue @@ -4,6 +4,7 @@ trigger="click" popover-class="emoji-picker popover-default" :hide-trigger="true" + placement="bottom" @show="onPopoverShown" @close="onPopoverClosed" > diff --git a/src/components/emoji_reactions/emoji_reactions.js b/src/components/emoji_reactions/emoji_reactions.js index e1a28a8f1..e22336138 100644 --- a/src/components/emoji_reactions/emoji_reactions.js +++ b/src/components/emoji_reactions/emoji_reactions.js @@ -3,6 +3,7 @@ import UserAvatar from '../user_avatar/user_avatar.vue' import UserListPopover from '../user_list_popover/user_list_popover.vue' import { useInstanceStore } from 'src/stores/instance.js' +import { useMergedConfigStore } from 'src/stores/merged_config.js' import { library } from '@fortawesome/fontawesome-svg-core' import { faCheck, faMinus, faPlus } from '@fortawesome/free-solid-svg-icons' @@ -48,6 +49,9 @@ const EmojiReactions = { statusId: this.status.id, }) }, + allowNonSquareEmoji() { + return useMergedConfigStore().mergedConfig.nonSquareEmoji + }, }, methods: { toggleShowAll() { diff --git a/src/components/emoji_reactions/emoji_reactions.scss b/src/components/emoji_reactions/emoji_reactions.scss index 8ea45e1b4..88ff1cee6 100644 --- a/src/components/emoji_reactions/emoji_reactions.scss +++ b/src/components/emoji_reactions/emoji_reactions.scss @@ -49,6 +49,12 @@ justify-content: center; align-items: center; + &.-wide { + width: auto; + min-width: var(--emoji-size); + max-width: calc(var(--emoji-size) * 3); + } + --_still_image-label-scale: 0.3; } @@ -62,6 +68,12 @@ font-size: calc(var(--emoji-size) * 0.8); margin: 0; + &.-wide { + width: auto; + min-width: var(--emoji-size); + max-width: calc(var(--emoji-size) * 3); + } + img { object-fit: contain; } diff --git a/src/components/emoji_reactions/emoji_reactions.vue b/src/components/emoji_reactions/emoji_reactions.vue index e2361885a..16c69fa40 100644 --- a/src/components/emoji_reactions/emoji_reactions.vue +++ b/src/components/emoji_reactions/emoji_reactions.vue @@ -17,11 +17,13 @@ > {{ ' ' }}