diff --git a/changelog.d/emoji-picker-button-accessible.fix b/changelog.d/emoji-picker-button-accessible.fix new file mode 100644 index 000000000..12898a1ac --- /dev/null +++ b/changelog.d/emoji-picker-button-accessible.fix @@ -0,0 +1 @@ +Add alt text to emoji picker buttons diff --git a/changelog.d/mention-twice.fix b/changelog.d/mention-twice.fix new file mode 100644 index 000000000..0e4b71dfd --- /dev/null +++ b/changelog.d/mention-twice.fix @@ -0,0 +1 @@ +Fix a bug where mentioning a user twice will not fill the mention into the textarea diff --git a/changelog.d/mentionsline-shouldbreak.fix b/changelog.d/mentionsline-shouldbreak.fix new file mode 100644 index 000000000..33ee8d2c9 --- /dev/null +++ b/changelog.d/mentionsline-shouldbreak.fix @@ -0,0 +1 @@ +Make MentionsLine aware of line breaking by non-br elements diff --git a/changelog.d/nonascii-tags.fix b/changelog.d/nonascii-tags.fix new file mode 100644 index 000000000..e4c6dc82d --- /dev/null +++ b/changelog.d/nonascii-tags.fix @@ -0,0 +1 @@ +Fix parsing non-ascii tags diff --git a/changelog.d/oauth2-token-linger.fix b/changelog.d/oauth2-token-linger.fix new file mode 100644 index 000000000..da4e46316 --- /dev/null +++ b/changelog.d/oauth2-token-linger.fix @@ -0,0 +1 @@ +Fix OAuth2 token lingering after revocation diff --git a/changelog.d/reload-user-pinned.fix b/changelog.d/reload-user-pinned.fix new file mode 100644 index 000000000..db241c205 --- /dev/null +++ b/changelog.d/reload-user-pinned.fix @@ -0,0 +1 @@ +Fix pinned statuses gone when reloading user timeline diff --git a/src/components/emoji_picker/emoji_picker.vue b/src/components/emoji_picker/emoji_picker.vue index 227d7718b..b8d333097 100644 --- a/src/components/emoji_picker/emoji_picker.vue +++ b/src/components/emoji_picker/emoji_picker.vue @@ -28,6 +28,7 @@ active: activeGroupView === group.id }" :title="group.text" + role="button" @click.prevent="highlight(group.id)" > diff --git a/src/components/post_status_form/post_status_form.vue b/src/components/post_status_form/post_status_form.vue index 0d7938854..9b108a5aa 100644 --- a/src/components/post_status_form/post_status_form.vue +++ b/src/components/post_status_form/post_status_form.vue @@ -129,44 +129,32 @@
- -
+
+ {{ $t('post_status.quote_option') }} +
diff --git a/src/components/rich_content/rich_content.jsx b/src/components/rich_content/rich_content.jsx index b16ab242e..ff14a58ac 100644 --- a/src/components/rich_content/rich_content.jsx +++ b/src/components/rich_content/rich_content.jsx @@ -8,6 +8,27 @@ import HashtagLink from 'src/components/hashtag_link/hashtag_link.vue' import './rich_content.scss' +const MAYBE_LINE_BREAKING_ELEMENTS = [ + 'blockquote', + 'br', + 'hr', + 'ul', + 'ol', + 'li', + 'p', + 'table', + 'tbody', + 'td', + 'th', + 'thead', + 'tr', + 'h1', + 'h2', + 'h3', + 'h4', + 'h5' +] + /** * RichContent, The Über-powered component for rendering Post HTML. * @@ -166,25 +187,22 @@ export default { !(children && typeof children[0] === 'string' && children[0].match(/^\s/)) ? lastSpacing : '' - switch (Tag) { - case 'br': + if (MAYBE_LINE_BREAKING_ELEMENTS.includes(Tag)) { + // all the elements that can cause a line change + currentMentions = null + } else if (Tag === 'img') { // replace images with StillImage + return ['', [mentionsLinePadding, renderImage(opener)], ''] + } else if (Tag === 'a' && this.handleLinks) { // replace mentions with MentionLink + if (fullAttrs.class && fullAttrs.class.includes('mention')) { + // Handling mentions here + return renderMention(attrs, children) + } else { currentMentions = null - break - case 'img': // replace images with StillImage - return ['', [mentionsLinePadding, renderImage(opener)], ''] - case 'a': // replace mentions with MentionLink - if (!this.handleLinks) break - if (fullAttrs.class && fullAttrs.class.includes('mention')) { - // Handling mentions here - return renderMention(attrs, children) - } else { - currentMentions = null - break - } - case 'span': - if (this.handleLinks && fullAttrs.class && fullAttrs.class.includes('h-card')) { - return ['', children.map(processItem), ''] - } + } + } else if (Tag === 'span') { + if (this.handleLinks && fullAttrs.class && fullAttrs.class.includes('h-card')) { + return ['', children.map(processItem), ''] + } } if (children !== undefined) { diff --git a/src/components/timeline/timeline.js b/src/components/timeline/timeline.js index b74146109..1050b87a6 100644 --- a/src/components/timeline/timeline.js +++ b/src/components/timeline/timeline.js @@ -160,6 +160,9 @@ const Timeline = { if (this.timeline.flushMarker !== 0) { this.$store.commit('clearTimeline', { timeline: this.timelineName, excludeUserId: true }) this.$store.commit('queueFlush', { timeline: this.timelineName, id: 0 }) + if (this.timelineName === 'user') { + this.$store.dispatch('fetchPinnedStatuses', this.userId) + } this.fetchOlderStatuses() } else { this.blockClicksTemporarily() diff --git a/src/modules/postStatus.js b/src/modules/postStatus.js index 638c1fb20..d3bea1378 100644 --- a/src/modules/postStatus.js +++ b/src/modules/postStatus.js @@ -10,6 +10,9 @@ const postStatus = { }, closePostStatusModal (state) { state.modalActivated = false + }, + resetPostStatusModal (state) { + state.params = null } }, actions: { @@ -18,6 +21,9 @@ const postStatus = { }, closePostStatusModal ({ commit }) { commit('closePostStatusModal') + }, + resetPostStatusModal ({ commit }) { + commit('resetPostStatusModal') } } } diff --git a/src/modules/users.js b/src/modules/users.js index e976d8753..50b4cb84d 100644 --- a/src/modules/users.js +++ b/src/modules/users.js @@ -651,6 +651,12 @@ const users = { const response = data.error // Authentication failed commit('endLogin') + + // remove authentication token on client/authentication errors + if ([400, 401, 403, 422].includes(response.status)) { + commit('clearToken') + } + if (response.status === 401) { reject(new Error('Wrong username or password')) } else { diff --git a/src/services/matcher/matcher.service.js b/src/services/matcher/matcher.service.js index b6c4e9099..54f02d312 100644 --- a/src/services/matcher/matcher.service.js +++ b/src/services/matcher/matcher.service.js @@ -14,8 +14,11 @@ export const mentionMatchesUrl = (attention, url) => { * @param {string} url */ export const extractTagFromUrl = (url) => { - const regex = /tag[s]*\/(\w+)$/g - const result = regex.exec(url) + const decoded = decodeURI(url) + // https://git.pleroma.social/pleroma/elixir-libraries/linkify/-/blob/master/lib/linkify/parser.ex + // https://www.pcre.org/original/doc/html/pcrepattern.html + const regex = /tag[s]*\/([\p{L}\p{N}_]*[\p{Alphabetic}_·\u{200c}][\p{L}\p{N}_·\p{M}\u{200c}]*)$/ug + const result = regex.exec(decoded) if (!result) { return false } diff --git a/test/unit/specs/services/matcher/matcher.spec.js b/test/unit/specs/services/matcher/matcher.spec.js index 7a2494f07..c6e9719d3 100644 --- a/test/unit/specs/services/matcher/matcher.spec.js +++ b/test/unit/specs/services/matcher/matcher.spec.js @@ -78,5 +78,11 @@ describe('MatcherService', () => { expect(MatcherService.extractTagFromUrl(url)).to.eql(false) }) + + it('should return tag name from non-ascii tags', () => { + const url = encodeURI('https://website.com/tag/喵喵喵') + + expect(MatcherService.extractTagFromUrl(url)).to.eql('喵喵喵') + }) }) })