diff --git a/CHANGELOG.md b/CHANGELOG.md index 1eb5a9cb4..d3b899d25 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,50 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). +## 2.11 +### Added +- Initial MFM rendering support +- 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) +- Displaying other user's backgrounds (if supported by BE) +- Add quoting by URL and in replies +- Settings synchronization +- User highlight synchronization +- User administration + post scope/sensitivity admin change support + +### Changed +- Migrated to Vite 8 and optimized our imports, more stuff is loaded on-demand, reducing the initial load time and transfer size +- Overall improved spacing 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 + +### Fixed +- Fix HTML attribute parsing for escaped quotes +- Fix emojis breaking user bio/description editing +- 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 +- Fixed status action mute hiding itself on click +- Fix reply form crash when quote-reply settings are unavailable + + ## 2.10.1 ### Fixed - fixed being unable to set actor type from profile page diff --git a/changelog.d/api-refactor.skip b/changelog.d/api-refactor.skip deleted file mode 100644 index e69de29bb..000000000 diff --git a/changelog.d/attrs-parsing.fix b/changelog.d/attrs-parsing.fix deleted file mode 100644 index e36e59a86..000000000 --- a/changelog.d/attrs-parsing.fix +++ /dev/null @@ -1 +0,0 @@ -Fix HTML attribute parsing for escaped quotes \ No newline at end of file diff --git a/changelog.d/ci-pr-uploads-removal.skip b/changelog.d/ci-pr-uploads-removal.skip deleted file mode 100644 index e69de29bb..000000000 diff --git a/changelog.d/fast.change b/changelog.d/fast.change deleted file mode 100644 index 1f0a89092..000000000 --- a/changelog.d/fast.change +++ /dev/null @@ -1 +0,0 @@ -Migrated to Vite 8 and optimized our imports, more stuff is loaded on-demand, reducing the initial load time and transfer size diff --git a/changelog.d/fix-emojis-breaking-bio.fix b/changelog.d/fix-emojis-breaking-bio.fix deleted file mode 100644 index 62a607d8a..000000000 --- a/changelog.d/fix-emojis-breaking-bio.fix +++ /dev/null @@ -1 +0,0 @@ -Fix emojis breaking user bio/description editing diff --git a/changelog.d/instance-store-migration.skip b/changelog.d/instance-store-migration.skip deleted file mode 100644 index e69de29bb..000000000 diff --git a/changelog.d/mfm.add b/changelog.d/mfm.add deleted file mode 100644 index b5d320955..000000000 --- a/changelog.d/mfm.add +++ /dev/null @@ -1 +0,0 @@ -Initial MFM rendering support diff --git a/changelog.d/minor.add b/changelog.d/minor.add deleted file mode 100644 index 5f4934173..000000000 --- a/changelog.d/minor.add +++ /dev/null @@ -1,6 +0,0 @@ -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 deleted file mode 100644 index 979d36955..000000000 --- a/changelog.d/minor.change +++ /dev/null @@ -1,7 +0,0 @@ -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 deleted file mode 100644 index 420836364..000000000 --- a/changelog.d/minor.fix +++ /dev/null @@ -1,12 +0,0 @@ -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/more-fixes.skip b/changelog.d/more-fixes.skip deleted file mode 100644 index e69de29bb..000000000 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/profilebg.add b/changelog.d/profilebg.add deleted file mode 100644 index a2c79074a..000000000 --- a/changelog.d/profilebg.add +++ /dev/null @@ -1 +0,0 @@ -displaying other user's backgrounds (if supported by BE) 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/changelog.d/reply-quote-config.fix b/changelog.d/reply-quote-config.fix deleted file mode 100644 index b6ac4e5e9..000000000 --- a/changelog.d/reply-quote-config.fix +++ /dev/null @@ -1 +0,0 @@ -Fix reply form crash when quote-reply settings are unavailable diff --git a/changelog.d/sync-config.add b/changelog.d/sync-config.add deleted file mode 100644 index 76a5a1cca..000000000 --- a/changelog.d/sync-config.add +++ /dev/null @@ -1,2 +0,0 @@ -settings synchronization -user highlight synchronization diff --git a/changelog.d/user-management.add b/changelog.d/user-management.add deleted file mode 100644 index ccd217f19..000000000 --- a/changelog.d/user-management.add +++ /dev/null @@ -1 +0,0 @@ -User administration + post scope/sensitivity admin change support diff --git a/changelog.d/woodpecker-pr-pipeline.skip b/changelog.d/woodpecker-pr-pipeline.skip deleted file mode 100644 index e69de29bb..000000000 diff --git a/package.json b/package.json index f594d7a99..1d94ac22f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pleroma_fe", - "version": "2.10.1", + "version": "2.11.0", "description": "Pleroma frontend, the default frontend of Pleroma social network server", "author": "Pleroma contributors ", "private": false, diff --git a/src/api/chats.js b/src/api/chats.js index 114038e52..5d766dec4 100644 --- a/src/api/chats.js +++ b/src/api/chats.js @@ -1,6 +1,9 @@ import { paramsString, promisedRequest } from './helpers.js' -import { parseChat } from 'src/services/entity_normalizer/entity_normalizer.service.js' +import { + parseChat, + parseChatMessage, +} from 'src/services/entity_normalizer/entity_normalizer.service.js' const PLEROMA_CHATS_URL = '/api/v1/pleroma/chats' const PLEROMA_CHAT_URL = (id) => `/api/v1/pleroma/chats/by-account-id/${id}` @@ -15,7 +18,7 @@ export const chats = ({ credentials }) => url: PLEROMA_CHATS_URL, credentials, }).then(({ data }) => ({ - chatList: data.map(parseChat).filter((c) => c), + data: data.map(parseChat).filter((c) => c), })) export const getOrCreateChat = ({ accountId, credentials }) => @@ -23,7 +26,7 @@ export const getOrCreateChat = ({ accountId, credentials }) => url: PLEROMA_CHAT_URL(accountId), method: 'POST', credentials, - }) + }).then(({ data }) => ({ data: parseChat(data) })) export const chatMessages = ({ id, @@ -36,7 +39,9 @@ export const chatMessages = ({ url: PLEROMA_CHAT_MESSAGES_URL(id, { maxId, sinceId, limit }), method: 'GET', credentials, - }) + }).then(({ data }) => ({ + data: data.map(parseChatMessage).filter((c) => c), + })) } export const sendChatMessage = ({ @@ -66,7 +71,9 @@ export const sendChatMessage = ({ payload, credentials, headers, - }) + }).then(({ data }) => ({ + data: parseChatMessage(data), + })) } export const readChat = ({ id, lastReadId, credentials }) => diff --git a/src/boot/routes.js b/src/boot/routes.js index d50baab04..0dfb1e744 100644 --- a/src/boot/routes.js +++ b/src/boot/routes.js @@ -293,7 +293,7 @@ export default (store) => { name: 'chat', path: '/users/:username/chats/:recipient_id', component: defineAsyncComponent( - () => import('src/components/chat/chat.vue'), + () => import('src/components/chat_view/chat_view.vue'), ), meta: { dontScroll: false }, beforeEnter: validateAuthenticatedRoute, diff --git a/src/components/chat_list/chat_list.js b/src/components/chat_list/chat_list.js index 597fcc709..446ccb70a 100644 --- a/src/components/chat_list/chat_list.js +++ b/src/components/chat_list/chat_list.js @@ -1,9 +1,12 @@ -import { mapGetters, mapState } from 'vuex' +import { mapState as mapPiniaState } from 'pinia' +import { mapState } from 'vuex' import ChatListItem from 'src/components/chat_list_item/chat_list_item.vue' import ChatNew from 'src/components/chat_new/chat_new.vue' import List from 'src/components/list/list.vue' +import { useChatsStore } from 'src/stores/chats.js' + const ChatList = { components: { ChatListItem, @@ -14,7 +17,7 @@ const ChatList = { ...mapState({ currentUser: (state) => state.users.currentUser, }), - ...mapGetters(['sortedChatList']), + ...mapPiniaState(useChatsStore, ['sortedChatList']), }, data() { return { @@ -22,12 +25,12 @@ const ChatList = { } }, created() { - this.$store.dispatch('fetchChats', { latest: true }) + useChatsStore().fetchChats() }, methods: { cancelNewChat() { this.isNew = false - this.$store.dispatch('fetchChats', { latest: true }) + useChatsStore().fetchChats() }, newChat() { this.isNew = true diff --git a/src/components/chat_message/chat_message.js b/src/components/chat_message/chat_message.js index 2066a8194..580cb183f 100644 --- a/src/components/chat_message/chat_message.js +++ b/src/components/chat_message/chat_message.js @@ -1,3 +1,4 @@ +import { find } from 'lodash' import { mapState as mapPiniaState } from 'pinia' import { mapState } from 'vuex' @@ -6,6 +7,8 @@ import ChatMessageDate from 'src/components/chat_message_date/chat_message_date. import Gallery from 'src/components/gallery/gallery.vue' import LinkPreview from 'src/components/link-preview/link-preview.vue' import Popover from 'src/components/popover/popover.vue' +import StatusActionButtons from 'src/components/status_action_buttons/status_action_buttons.vue' +import StatusBody from 'src/components/status_body/status_body.vue' import StatusContent from 'src/components/status_content/status_content.vue' import UserAvatar from 'src/components/user_avatar/user_avatar.vue' import UserPopover from 'src/components/user_popover/user_popover.vue' @@ -15,24 +18,31 @@ import { useInterfaceStore } from 'src/stores/interface' import { useMergedConfigStore } from 'src/stores/merged_config.js' import { library } from '@fortawesome/fontawesome-svg-core' -import { faEllipsisH, faTimes } from '@fortawesome/free-solid-svg-icons' +import { + faCircleNotch, + faEllipsisH, + faTimes, +} from '@fortawesome/free-solid-svg-icons' -library.add(faTimes, faEllipsisH) +library.add(faTimes, faEllipsisH, faCircleNotch) const ChatMessage = { name: 'ChatMessage', props: [ - 'author', 'edited', 'noHeading', - 'chatViewItem', + 'previousItem', + 'chatItem', + 'previousItem', 'hoveredMessageChain', ], - emits: ['hover'], + emits: ['hover', 'replyRequested'], components: { Popover, Attachment, StatusContent, + StatusBody, + StatusActionButtons, UserAvatar, Gallery, LinkPreview, @@ -42,27 +52,48 @@ const ChatMessage = { computed: { // Returns HH:MM (hours and minutes) in local time. createdAt() { - const time = this.chatViewItem.data.created_at + const time = this.chatItem.data.created_at return time.toLocaleTimeString('en', { hour: '2-digit', minute: '2-digit', hour12: false, }) }, + isStatus() { + // ChatMessage only has account_id while Status has full user data + return !!this.message.user + }, + author() { + const accountId = this.message.account_id || this.message.user.id + + return this.$store.getters.findUser(accountId) + }, isCurrentUser() { - return this.message.account_id === this.currentUser.id + return this.author.id === this.currentUser.id }, message() { - return this.chatViewItem.data + return this.isMessage ? this.chatItem.data : null }, isMessage() { - return this.chatViewItem.type === 'message' + return this.chatItem.type === 'message' + }, + isCustomReply() { + if (!this.previousItem) return false + if (!this.chatItem.data.in_reply_to_status_id) return false + return ( + this.previousItem.data.id !== this.chatItem.data.in_reply_to_status_id + ) + }, + customReplyTo() { + return this.$store.state.statuses.allStatusesObject[ + this.chatItem.data.in_reply_to_status_id + ] }, messageForStatusContent() { return { summary: '', emojis: this.message.emojis, - raw_html: this.message.content || '', + raw_html: this.message.content || this.message.raw_html || '', text: this.message.content || '', attachments: this.message.attachments, } @@ -96,15 +127,32 @@ const ChatMessage = { onHover(bool) { this.$emit('hover', { isHovered: bool, - messageChainId: this.chatViewItem.messageChainId, + messageChainId: this.chatItem.messageChainId, }) }, + visibilityIcon(visibility) { + switch (visibility) { + case 'private': + return 'lock' + case 'unlisted': + return 'lock-open' + case 'direct': + return 'envelope' + case 'local': + return 'igloo' + default: + return 'globe' + } + }, + visibilityLocalized() { + return this.$i18n.t('general.scope_in_timeline.' + this.status.visibility) + }, async deleteMessage() { const confirmed = window.confirm(this.$t('chats.delete_confirm')) if (confirmed) { - await this.$store.dispatch('deleteChatMessage', { - messageId: this.chatViewItem.data.id, - chatId: this.chatViewItem.data.chat_id, + await this.$emit('delete', { + messageId: this.chatItem.data.id, + chatId: this.chatItem.data.chat_id, }) } this.hovered = false diff --git a/src/components/chat_message/chat_message.scss b/src/components/chat_message/chat_message.scss index c058f8172..34382c42d 100644 --- a/src/components/chat_message/chat_message.scss +++ b/src/components/chat_message/chat_message.scss @@ -11,29 +11,59 @@ } } - .chat-message-menu { + .chat-message-toolbar { transition: opacity 0.1s; opacity: 0; position: absolute; top: -0.8em; + right: 0.4rem; + z-index: 10; - button { + .quick-action-buttons { + justify-items: end; + grid-template-columns: auto auto auto; + } + + .simple-button { padding-top: 0.2em; padding-bottom: 0.2em; } + + &.-visible { + opacity: 1; + } } .menu-icon { cursor: pointer; } + .reply-to-header { + white-space: nowrap; + width: 100%; + display: flex; + align-items: baseline; + gap: 0.5em; + + .reply-label { + display: inline-block; + line-height: 1; + } + + .reply-body { + line-height: 1; + display: inline-block; + overflow-x: hidden; + text-overflow: ellipsis; + } + } + .popover { width: 12em; } .chat-message { display: flex; - padding-bottom: 0.5em; .status-body:hover { --_still-image-img-visibility: visible; @@ -67,7 +97,6 @@ font-size: 0.8em; margin: -1em 0 -0.5em; font-style: italic; - opacity: 0.8; } .without-attachment { @@ -104,7 +133,7 @@ width: 100%; } - .outgoing { + .-outgoing { display: flex; flex-flow: row wrap; place-content: end flex-end; @@ -113,14 +142,8 @@ align-items: flex-end; } - .chat-message-menu { - right: 0.4rem; - } - } - - .incoming { - .chat-message-menu { - left: 0.4rem; + .reply-to-header { + justify-content: end; } } @@ -139,8 +162,8 @@ .chat-message-date-separator { text-align: center; - margin: 1.4em 0; font-size: 0.9em; + line-height: 2; user-select: none; color: var(--textFaint); } diff --git a/src/components/chat_message/chat_message.vue b/src/components/chat_message/chat_message.vue index 22e2e8eb8..91ad9a4eb 100644 --- a/src/components/chat_message/chat_message.vue +++ b/src/components/chat_message/chat_message.vue @@ -8,14 +8,14 @@ >
+ + + + {{ $t('status.reply_to') }} + + + +
+ +
@@ -80,6 +109,27 @@ + + + + + + {{ createdAt }} @@ -93,7 +143,7 @@ v-else class="chat-message-date-separator" > - +
diff --git a/src/components/chat_message_date/chat_message_date.vue b/src/components/chat_message_date/chat_message_date.vue index f0cadb6e7..6c1be505b 100644 --- a/src/components/chat_message_date/chat_message_date.vue +++ b/src/components/chat_message_date/chat_message_date.vue @@ -5,12 +5,17 @@ + +