Merge remote-tracking branch 'origin/develop' into shigusegubu-vue3
This commit is contained in:
commit
232c5528b5
16 changed files with 90 additions and 57 deletions
1
changelog.d/emoji-picker-button-accessible.fix
Normal file
1
changelog.d/emoji-picker-button-accessible.fix
Normal file
|
@ -0,0 +1 @@
|
|||
Add alt text to emoji picker buttons
|
1
changelog.d/mention-twice.fix
Normal file
1
changelog.d/mention-twice.fix
Normal file
|
@ -0,0 +1 @@
|
|||
Fix a bug where mentioning a user twice will not fill the mention into the textarea
|
1
changelog.d/mentionsline-shouldbreak.fix
Normal file
1
changelog.d/mentionsline-shouldbreak.fix
Normal file
|
@ -0,0 +1 @@
|
|||
Make MentionsLine aware of line breaking by non-br elements
|
1
changelog.d/nonascii-tags.fix
Normal file
1
changelog.d/nonascii-tags.fix
Normal file
|
@ -0,0 +1 @@
|
|||
Fix parsing non-ascii tags
|
1
changelog.d/oauth2-token-linger.fix
Normal file
1
changelog.d/oauth2-token-linger.fix
Normal file
|
@ -0,0 +1 @@
|
|||
Fix OAuth2 token lingering after revocation
|
1
changelog.d/reload-user-pinned.fix
Normal file
1
changelog.d/reload-user-pinned.fix
Normal file
|
@ -0,0 +1 @@
|
|||
Fix pinned statuses gone when reloading user timeline
|
|
@ -28,6 +28,7 @@
|
|||
active: activeGroupView === group.id
|
||||
}"
|
||||
:title="group.text"
|
||||
role="button"
|
||||
@click.prevent="highlight(group.id)"
|
||||
>
|
||||
<span
|
||||
|
@ -116,6 +117,7 @@
|
|||
:key="group.id + emoji.displayText"
|
||||
:title="maybeLocalizedEmojiName(emoji)"
|
||||
class="emoji-item"
|
||||
role="button"
|
||||
@click.stop.prevent="onEmoji(emoji)"
|
||||
>
|
||||
<span
|
||||
|
@ -126,6 +128,7 @@
|
|||
v-else
|
||||
class="emoji-picker-emoji -custom"
|
||||
loading="lazy"
|
||||
:alt="maybeLocalizedEmojiName(emoji)"
|
||||
:src="emoji.imageUrl"
|
||||
:data-emoji-name="group.id + emoji.displayText"
|
||||
/>
|
||||
|
|
|
@ -129,44 +129,32 @@
|
|||
<div
|
||||
v-if="quotable"
|
||||
role="radiogroup"
|
||||
class="reply-or-quote-selector"
|
||||
class="btn-group reply-or-quote-selector"
|
||||
>
|
||||
<div
|
||||
class="reply-or-quote-option"
|
||||
<button
|
||||
:id="`reply-or-quote-option-${randomSeed}-reply`"
|
||||
class="btn button-default reply-or-quote-option"
|
||||
:class="{ toggled: !newStatus.quoting }"
|
||||
tabindex="0"
|
||||
role="radio"
|
||||
:aria-labelledby="`reply-or-quote-option-${randomSeed}-reply`"
|
||||
:aria-checked="!newStatus.quoting"
|
||||
@click="newStatus.quoting = false"
|
||||
>
|
||||
<input
|
||||
type="radio"
|
||||
:checked="!newStatus.quoting"
|
||||
>
|
||||
<label class="reply-or-quote-option-text">
|
||||
<span :id="`reply-or-quote-option-${randomSeed}-reply`">
|
||||
{{ $t('post_status.reply_option') }}
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
<div
|
||||
class="reply-or-quote-option"
|
||||
{{ $t('post_status.reply_option') }}
|
||||
</button>
|
||||
<button
|
||||
:id="`reply-or-quote-option-${randomSeed}-quote`"
|
||||
class="btn button-default reply-or-quote-option"
|
||||
:class="{ toggled: newStatus.quoting }"
|
||||
tabindex="0"
|
||||
role="radio"
|
||||
:aria-labelledby="`reply-or-quote-option-${randomSeed}-quote`"
|
||||
:aria-checked="newStatus.quoting"
|
||||
@click="newStatus.quoting = true"
|
||||
>
|
||||
<input
|
||||
type="radio"
|
||||
:checked="newStatus.quoting"
|
||||
>
|
||||
<label class="reply-or-quote-option-text">
|
||||
<span :id="`reply-or-quote-option-${randomSeed}-quote`">
|
||||
{{ $t('post_status.quote_option') }}
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
{{ $t('post_status.quote_option') }}
|
||||
</button>
|
||||
</div>
|
||||
<EmojiInput
|
||||
v-if="!disableSubject && (newStatus.spoilerText || alwaysShowSubject)"
|
||||
|
@ -463,17 +451,7 @@
|
|||
}
|
||||
|
||||
.reply-or-quote-selector {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.reply-or-quote-option {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.reply-or-quote-option-text::before {
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
.text-format {
|
||||
|
|
|
@ -44,6 +44,10 @@ const PostStatusModal = {
|
|||
methods: {
|
||||
closeModal () {
|
||||
this.$store.dispatch('closePostStatusModal')
|
||||
},
|
||||
resetAndClose () {
|
||||
this.$store.dispatch('resetPostStatusModal')
|
||||
this.$store.dispatch('closePostStatusModal')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
<PostStatusForm
|
||||
class="panel-body"
|
||||
v-bind="params"
|
||||
@posted="closeModal"
|
||||
@posted="resetAndClose"
|
||||
/>
|
||||
</div>
|
||||
</Modal>
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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('喵喵喵')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
Loading…
Add table
Reference in a new issue