Merge branch 'small-fixes-and-improvements' into shigusegubu-themes3
This commit is contained in:
commit
d08896c73b
31 changed files with 228 additions and 65 deletions
1
changelog.d/reply-quote-config.fix
Normal file
1
changelog.d/reply-quote-config.fix
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
Fix reply form crash when quote-reply settings are unavailable
|
||||||
|
|
@ -175,14 +175,16 @@ const setSettings = async ({ apiConfig, staticConfig, store }) => {
|
||||||
if (source === 'name') return
|
if (source === 'name') return
|
||||||
if (INSTANCE_IDENTIY_EXTERNAL.has(source)) return
|
if (INSTANCE_IDENTIY_EXTERNAL.has(source)) return
|
||||||
useInstanceStore().set({
|
useInstanceStore().set({
|
||||||
value: config[source] ?? INSTANCE_IDENTITY_DEFAULT_DEFINITIONS[source].default,
|
value:
|
||||||
|
config[source] ?? INSTANCE_IDENTITY_DEFAULT_DEFINITIONS[source].default,
|
||||||
path: `instanceIdentity.${source}`,
|
path: `instanceIdentity.${source}`,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
Object.keys(INSTANCE_DEFAULT_CONFIG_DEFINITIONS).forEach((source) =>
|
Object.keys(INSTANCE_DEFAULT_CONFIG_DEFINITIONS).forEach((source) =>
|
||||||
useInstanceStore().set({
|
useInstanceStore().set({
|
||||||
value: config[source] ?? INSTANCE_DEFAULT_CONFIG_DEFINITIONS[source].default,
|
value:
|
||||||
|
config[source] ?? INSTANCE_DEFAULT_CONFIG_DEFINITIONS[source].default,
|
||||||
path: `prefsStorage.${source}`,
|
path: `prefsStorage.${source}`,
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,11 @@ const About = {
|
||||||
frontendVersionLink() {
|
frontendVersionLink() {
|
||||||
return pleromaFeCommitUrl + this.frontendVersion
|
return pleromaFeCommitUrl + this.frontendVersion
|
||||||
},
|
},
|
||||||
...mapState(useInstanceStore, ['backendVersion', 'backendRepository', 'frontendVersion']),
|
...mapState(useInstanceStore, [
|
||||||
|
'backendVersion',
|
||||||
|
'backendRepository',
|
||||||
|
'frontendVersion',
|
||||||
|
]),
|
||||||
showInstanceSpecificPanel() {
|
showInstanceSpecificPanel() {
|
||||||
return (
|
return (
|
||||||
useInstanceStore().instanceIdentity.showInstanceSpecificPanel &&
|
useInstanceStore().instanceIdentity.showInstanceSpecificPanel &&
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,9 @@
|
||||||
<features-panel v-if="showFeaturesPanel" />
|
<features-panel v-if="showFeaturesPanel" />
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
<div class="title">{{ $t('settings.version.title') }}</div>
|
<div class="title">
|
||||||
|
{{ $t('settings.version.title') }}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<dl>
|
<dl>
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ const BasicUserCard = {
|
||||||
allowNonSquareEmoji() {
|
allowNonSquareEmoji() {
|
||||||
return useMergedConfigStore().mergedConfig.nonSquareEmoji
|
return useMergedConfigStore().mergedConfig.nonSquareEmoji
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export default BasicUserCard
|
export default BasicUserCard
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@ import { defineAsyncComponent } from 'vue'
|
||||||
import RichContent from 'src/components/rich_content/rich_content.jsx'
|
import RichContent from 'src/components/rich_content/rich_content.jsx'
|
||||||
import UserAvatar from '../user_avatar/user_avatar.vue'
|
import UserAvatar from '../user_avatar/user_avatar.vue'
|
||||||
|
|
||||||
|
import { useMergedConfigStore } from 'src/stores/merged_config.js'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'ChatTitle',
|
name: 'ChatTitle',
|
||||||
components: {
|
components: {
|
||||||
|
|
|
||||||
|
|
@ -88,6 +88,7 @@ export default {
|
||||||
label: {
|
label: {
|
||||||
required: false,
|
required: false,
|
||||||
type: String,
|
type: String,
|
||||||
|
default: '',
|
||||||
},
|
},
|
||||||
// use unstyled, uh, style
|
// use unstyled, uh, style
|
||||||
unstyled: {
|
unstyled: {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
|
import ConfirmModal from 'src/components/confirm_modal/confirm_modal.vue'
|
||||||
import Draft from 'src/components/draft/draft.vue'
|
import Draft from 'src/components/draft/draft.vue'
|
||||||
import List from 'src/components/list/list.vue'
|
import List from 'src/components/list/list.vue'
|
||||||
import ConfirmModal from 'src/components/confirm_modal/confirm_modal.vue'
|
|
||||||
|
|
||||||
const Drafts = {
|
const Drafts = {
|
||||||
components: {
|
components: {
|
||||||
|
|
@ -10,7 +10,7 @@ const Drafts = {
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
showingConfirmDialog: false
|
showingConfirmDialog: false,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
|
@ -23,12 +23,14 @@ const Drafts = {
|
||||||
this.showingConfirmDialog = true
|
this.showingConfirmDialog = true
|
||||||
},
|
},
|
||||||
doAbandonAll() {
|
doAbandonAll() {
|
||||||
this.$store.dispatch('abandonAllDrafts').then(() => this.hideConfirmDialog())
|
this.$store
|
||||||
|
.dispatch('abandonAllDrafts')
|
||||||
|
.then(() => this.hideConfirmDialog())
|
||||||
},
|
},
|
||||||
hideConfirmDialog() {
|
hideConfirmDialog() {
|
||||||
this.showingConfirmDialog = false
|
this.showingConfirmDialog = false
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Drafts
|
export default Drafts
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
<div
|
<div
|
||||||
ref="root"
|
ref="root"
|
||||||
class="input emoji-input"
|
class="input emoji-input"
|
||||||
:class="{ '-with-picker': !hideEmojiButton, '-textarea': this.input?.tagName === 'TEXTAREA' }"
|
:class="{ '-with-picker': !hideEmojiButton, '-textarea': input?.tagName === 'TEXTAREA' }"
|
||||||
>
|
>
|
||||||
<slot
|
<slot
|
||||||
:id="'textbox-' + randomSeed"
|
:id="'textbox-' + randomSeed"
|
||||||
|
|
|
||||||
|
|
@ -68,12 +68,23 @@ const Gallery = {
|
||||||
}
|
}
|
||||||
|
|
||||||
const maxPerRow = 3
|
const maxPerRow = 3
|
||||||
const currentRow = acc[acc.length - 1].items
|
const currentRow = acc[acc.length - 1]
|
||||||
if ((nextWide || nextEnd) && currentRow.length >= maxPerRow) {
|
const previousRow = acc[acc.length - 2]
|
||||||
const last = currentRow.splice(-1)[0]
|
|
||||||
return [...acc, { items: [last, attachment] }]
|
if (currentRow.items.length >= maxPerRow) {
|
||||||
|
if (nextWide || nextEnd) {
|
||||||
|
if (previousRow?.items.length > 1) {
|
||||||
|
currentRow.items.push(attachment)
|
||||||
|
return [...acc, { items: [] }]
|
||||||
} else {
|
} else {
|
||||||
currentRow.push(attachment)
|
const last = currentRow.items.splice(-1)[0]
|
||||||
|
return [...acc, { items: [last, attachment] }]
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return [...acc, { items: [attachment] }]
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
currentRow.items.push(attachment)
|
||||||
}
|
}
|
||||||
return acc
|
return acc
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import { get } from 'lodash'
|
import { get } from 'lodash'
|
||||||
import { mapState } from 'pinia'
|
import { mapState } from 'pinia'
|
||||||
|
|
||||||
import { useInstanceStore } from 'src/stores/instance.js'
|
import { useInstanceStore } from 'src/stores/instance.js'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -21,16 +22,11 @@ const MRFTransparencyPanel = {
|
||||||
computed: {
|
computed: {
|
||||||
...mapState(useInstanceStore, {
|
...mapState(useInstanceStore, {
|
||||||
federationPolicy: (state) => state.federationPolicy,
|
federationPolicy: (state) => state.federationPolicy,
|
||||||
mrfPolicies: (state) =>
|
mrfPolicies: (state) => get(state, 'federationPolicy.mrf_policies', []),
|
||||||
get(state, 'federationPolicy.mrf_policies', []),
|
|
||||||
quarantineInstances: (state) =>
|
quarantineInstances: (state) =>
|
||||||
toInstanceReasonObject(
|
toInstanceReasonObject(
|
||||||
get(state, 'federationPolicy.quarantined_instances', []),
|
get(state, 'federationPolicy.quarantined_instances', []),
|
||||||
get(
|
get(state, 'federationPolicy.quarantined_instances_info', []),
|
||||||
state,
|
|
||||||
'federationPolicy.quarantined_instances_info',
|
|
||||||
[],
|
|
||||||
),
|
|
||||||
'quarantined_instances',
|
'quarantined_instances',
|
||||||
),
|
),
|
||||||
acceptInstances: (state) =>
|
acceptInstances: (state) =>
|
||||||
|
|
|
||||||
|
|
@ -211,7 +211,11 @@ const PostStatusForm = {
|
||||||
poll: {},
|
poll: {},
|
||||||
hasPoll: false,
|
hasPoll: false,
|
||||||
hasQuote: false,
|
hasQuote: false,
|
||||||
quote: {},
|
quote: {
|
||||||
|
id: '',
|
||||||
|
url: '',
|
||||||
|
thread: false,
|
||||||
|
},
|
||||||
mediaDescriptions: {},
|
mediaDescriptions: {},
|
||||||
visibility: scope,
|
visibility: scope,
|
||||||
contentType,
|
contentType,
|
||||||
|
|
@ -230,7 +234,11 @@ const PostStatusForm = {
|
||||||
poll: this.statusPoll || {},
|
poll: this.statusPoll || {},
|
||||||
hasPoll: false,
|
hasPoll: false,
|
||||||
hasQuote: false,
|
hasQuote: false,
|
||||||
quote: {},
|
quote: {
|
||||||
|
id: '',
|
||||||
|
url: '',
|
||||||
|
thread: false,
|
||||||
|
},
|
||||||
mediaDescriptions: this.statusMediaDescriptions || {},
|
mediaDescriptions: this.statusMediaDescriptions || {},
|
||||||
visibility: this.statusScope || scope,
|
visibility: this.statusScope || scope,
|
||||||
contentType: statusContentType,
|
contentType: statusContentType,
|
||||||
|
|
@ -378,12 +386,13 @@ const PostStatusForm = {
|
||||||
this.newStatus.hasQuote = value
|
this.newStatus.hasQuote = value
|
||||||
this.newStatus.quote.thread = value
|
this.newStatus.quote.thread = value
|
||||||
this.newStatus.quote.id = value ? this.replyTo : ''
|
this.newStatus.quote.id = value ? this.replyTo : ''
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
defaultQuotable() {
|
defaultQuotable() {
|
||||||
if (
|
if (
|
||||||
!this.quotingAvailable ||
|
!this.quotingAvailable ||
|
||||||
!this.isReply
|
!this.isReply ||
|
||||||
|
!useMergedConfigStore().mergedConfig.quoteReply
|
||||||
) {
|
) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -264,10 +264,10 @@
|
||||||
/>
|
/>
|
||||||
<QuoteForm
|
<QuoteForm
|
||||||
v-if="quotingAvailable"
|
v-if="quotingAvailable"
|
||||||
|
:id="newStatus.quote.id"
|
||||||
ref="quoteForm"
|
ref="quoteForm"
|
||||||
:visible="quoteFormVisible"
|
:visible="quoteFormVisible"
|
||||||
:url="newStatus.quote.url"
|
:url="newStatus.quote.url"
|
||||||
:id="newStatus.quote.id"
|
|
||||||
@update:url="url => newStatus.quote.url = url"
|
@update:url="url => newStatus.quote.url = url"
|
||||||
@update:id="id => newStatus.quote.id = id"
|
@update:id="id => newStatus.quote.id = id"
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -328,7 +328,13 @@ export default {
|
||||||
// slots updated -> rerender -> emit -> update up the tree -> rerender -> ...
|
// slots updated -> rerender -> emit -> update up the tree -> rerender -> ...
|
||||||
// at least until vue3?
|
// at least until vue3?
|
||||||
const result = (
|
const result = (
|
||||||
<span class={['RichContent', this.faint ? '-faint' : '', this.allowNonSquareEmoji ? '-allow-non-square-emoji' : '']}>
|
<span
|
||||||
|
class={[
|
||||||
|
'RichContent',
|
||||||
|
this.faint ? '-faint' : '',
|
||||||
|
this.allowNonSquareEmoji ? '-allow-non-square-emoji' : '',
|
||||||
|
]}
|
||||||
|
>
|
||||||
{this.collapse
|
{this.collapse
|
||||||
? pass2.map((x) => {
|
? pass2.map((x) => {
|
||||||
if (!Array.isArray(x)) return x.replace(/\n/g, ' ')
|
if (!Array.isArray(x)) return x.replace(/\n/g, ' ')
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import { mapState } from 'pinia'
|
import { mapState } from 'pinia'
|
||||||
|
|
||||||
import BooleanSetting from '../helpers/boolean_setting.vue'
|
import BooleanSetting from '../helpers/boolean_setting.vue'
|
||||||
import SharedComputedObject from '../helpers/shared_computed_object.js'
|
import SharedComputedObject from '../helpers/shared_computed_object.js'
|
||||||
|
|
||||||
|
|
@ -17,7 +18,11 @@ const VersionTab = {
|
||||||
frontendVersionLink() {
|
frontendVersionLink() {
|
||||||
return pleromaFeCommitUrl + this.frontendVersion
|
return pleromaFeCommitUrl + this.frontendVersion
|
||||||
},
|
},
|
||||||
...mapState(useInstanceStore, ['backendVersion', 'backendRepository', 'frontendVersion']),
|
...mapState(useInstanceStore, [
|
||||||
|
'backendVersion',
|
||||||
|
'backendRepository',
|
||||||
|
'frontendVersion',
|
||||||
|
]),
|
||||||
...SharedComputedObject(),
|
...SharedComputedObject(),
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ library.add(faEllipsisH)
|
||||||
|
|
||||||
const StatusActionButtons = {
|
const StatusActionButtons = {
|
||||||
props: ['status', 'replying'],
|
props: ['status', 'replying'],
|
||||||
emits: ['toggleReplying'],
|
emits: ['toggleReplying', 'onSuccess', 'onError'],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
showPin: false,
|
showPin: false,
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,7 @@ const KNOWN_TAGS = new Set([
|
||||||
'mrf_tag:force-unlisted',
|
'mrf_tag:force-unlisted',
|
||||||
'mrf_tag:sandbox',
|
'mrf_tag:sandbox',
|
||||||
'mrf_tag:disable-remote-subscription',
|
'mrf_tag:disable-remote-subscription',
|
||||||
'mrf_tag:disable-any-subscription'
|
'mrf_tag:disable-any-subscription',
|
||||||
])
|
])
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
|
@ -119,7 +119,7 @@ export default {
|
||||||
required: false,
|
required: false,
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
DialogModal,
|
DialogModal,
|
||||||
|
|
|
||||||
|
|
@ -218,6 +218,7 @@
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
v-for="tag in user.tags"
|
v-for="tag in user.tags"
|
||||||
|
:key="tag"
|
||||||
class="alert warning user-role"
|
class="alert warning user-role"
|
||||||
>
|
>
|
||||||
{{ isKnownTag ? $t('user_card.tags.' + tag) : tag }}
|
{{ isKnownTag ? $t('user_card.tags.' + tag) : tag }}
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,11 @@ import { defineAsyncComponent } from 'vue'
|
||||||
import RichContent from 'src/components/rich_content/rich_content.jsx'
|
import RichContent from 'src/components/rich_content/rich_content.jsx'
|
||||||
import UnicodeDomainIndicator from '../unicode_domain_indicator/unicode_domain_indicator.vue'
|
import UnicodeDomainIndicator from '../unicode_domain_indicator/unicode_domain_indicator.vue'
|
||||||
|
|
||||||
|
import { useMergedConfigStore } from 'src/stores/merged_config.js'
|
||||||
|
|
||||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||||
import { faCircleNotch } from '@fortawesome/free-solid-svg-icons'
|
import { faCircleNotch } from '@fortawesome/free-solid-svg-icons'
|
||||||
|
|
||||||
import { useMergedConfigStore } from 'src/stores/merged_config.js'
|
|
||||||
|
|
||||||
library.add(faCircleNotch)
|
library.add(faCircleNotch)
|
||||||
|
|
||||||
const UserListPopover = {
|
const UserListPopover = {
|
||||||
|
|
|
||||||
|
|
@ -10,9 +10,9 @@ import List from '../list/list.vue'
|
||||||
import Timeline from '../timeline/timeline.vue'
|
import Timeline from '../timeline/timeline.vue'
|
||||||
import UserCard from '../user_card/user_card.vue'
|
import UserCard from '../user_card/user_card.vue'
|
||||||
|
|
||||||
import { useMergedConfigStore } from 'src/stores/merged_config.js'
|
|
||||||
import { useInstanceStore } from 'src/stores/instance.js'
|
import { useInstanceStore } from 'src/stores/instance.js'
|
||||||
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
|
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
|
||||||
|
import { useMergedConfigStore } from 'src/stores/merged_config.js'
|
||||||
|
|
||||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||||
import { faCircleNotch } from '@fortawesome/free-solid-svg-icons'
|
import { faCircleNotch } from '@fortawesome/free-solid-svg-icons'
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ const saveDraftToStorage = async (draft) => {
|
||||||
|
|
||||||
const deleteDraftFromStorage = async (ids) => {
|
const deleteDraftFromStorage = async (ids) => {
|
||||||
const currentData = await getStorageData()
|
const currentData = await getStorageData()
|
||||||
ids.forEach(id => {
|
ids.forEach((id) => {
|
||||||
delete currentData[id]
|
delete currentData[id]
|
||||||
})
|
})
|
||||||
await storage.setItem(storageKey, currentData)
|
await storage.setItem(storageKey, currentData)
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,10 @@ export const maybeShowNotification = (
|
||||||
|
|
||||||
if (notification.seen) return
|
if (notification.seen) return
|
||||||
if (!visibleTypes(notificationVisibility).includes(notification.type)) return
|
if (!visibleTypes(notificationVisibility).includes(notification.type)) return
|
||||||
if (notification.type === 'mention' && isMutedNotification(muteFilters, notification))
|
if (
|
||||||
|
notification.type === 'mention' &&
|
||||||
|
isMutedNotification(muteFilters, notification)
|
||||||
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
const notificationObject = prepareNotificationObject(
|
const notificationObject = prepareNotificationObject(
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,15 @@ export const muteFilterHits = (muteFilters, status) => {
|
||||||
return muteFilters
|
return muteFilters
|
||||||
.toSorted((a, b) => b.order - a.order)
|
.toSorted((a, b) => b.order - a.order)
|
||||||
.map((filter) => {
|
.map((filter) => {
|
||||||
const { hide, expires, name, value, type, enabled, caseSensitive = false } = filter
|
const {
|
||||||
|
hide,
|
||||||
|
expires,
|
||||||
|
name,
|
||||||
|
value,
|
||||||
|
type,
|
||||||
|
enabled,
|
||||||
|
caseSensitive = false,
|
||||||
|
} = filter
|
||||||
if (!enabled) return false
|
if (!enabled) return false
|
||||||
if (value === '') return false
|
if (value === '') return false
|
||||||
if (expires !== null && expires < Date.now()) return false
|
if (expires !== null && expires < Date.now()) return false
|
||||||
|
|
@ -18,9 +26,7 @@ export const muteFilterHits = (muteFilters, status) => {
|
||||||
case 'word': {
|
case 'word': {
|
||||||
let match = false
|
let match = false
|
||||||
if (caseSensitive) {
|
if (caseSensitive) {
|
||||||
match =
|
match = statusText.includes(value) || statusSummary.includes(value)
|
||||||
statusText.includes(value) ||
|
|
||||||
statusSummary.includes(value)
|
|
||||||
} else {
|
} else {
|
||||||
const lowercaseValue = value.toLowerCase()
|
const lowercaseValue = value.toLowerCase()
|
||||||
match =
|
match =
|
||||||
|
|
@ -56,7 +62,9 @@ export const muteFilterHits = (muteFilters, status) => {
|
||||||
match =
|
match =
|
||||||
poster.toLowerCase().includes(lowercaseValue) ||
|
poster.toLowerCase().includes(lowercaseValue) ||
|
||||||
replyToUser.toLowerCase().includes(lowercaseValue) ||
|
replyToUser.toLowerCase().includes(lowercaseValue) ||
|
||||||
mentions.some((mention) => mention.toLowerCase().includes(lowercaseValue))
|
mentions.some((mention) =>
|
||||||
|
mention.toLowerCase().includes(lowercaseValue),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
if (match) {
|
if (match) {
|
||||||
return { hide, name }
|
return { hide, name }
|
||||||
|
|
|
||||||
|
|
@ -499,10 +499,7 @@ export const init = ({
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
const lastVariantRule = variantRules[variantRules.length - 1]
|
const lastVariantRule = variantRules[variantRules.length - 1]
|
||||||
const lastVariantSelector = ruleToSelector(
|
const lastVariantSelector = ruleToSelector(lastVariantRule, true)
|
||||||
lastVariantRule,
|
|
||||||
true,
|
|
||||||
)
|
|
||||||
|
|
||||||
if (lastVariantRule && lastVariantSelector !== selector) {
|
if (lastVariantRule && lastVariantSelector !== selector) {
|
||||||
inheritRule = lastVariantRule
|
inheritRule = lastVariantRule
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,8 @@ import {
|
||||||
uniqWith,
|
uniqWith,
|
||||||
unset,
|
unset,
|
||||||
} from 'lodash'
|
} from 'lodash'
|
||||||
import { v4 as uuidv4 } from 'uuid'
|
|
||||||
import { defineStore } from 'pinia'
|
import { defineStore } from 'pinia'
|
||||||
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
import { toRaw } from 'vue'
|
import { toRaw } from 'vue'
|
||||||
|
|
||||||
import { CURRENT_UPDATE_COUNTER } from 'src/components/update_notification/update_notification.js'
|
import { CURRENT_UPDATE_COUNTER } from 'src/components/update_notification/update_notification.js'
|
||||||
|
|
@ -684,8 +684,6 @@ export const useSyncConfigStore = defineStore('sync_config', {
|
||||||
`Already migrated Values: ${[...migratedEntries].join() || '[none]'}`,
|
`Already migrated Values: ${[...migratedEntries].join() || '[none]'}`,
|
||||||
)
|
)
|
||||||
|
|
||||||
const { configMigration } = useSyncConfigStore().flagStorage
|
|
||||||
|
|
||||||
Object.entries(oldDefaultConfigSync).forEach(([key, value]) => {
|
Object.entries(oldDefaultConfigSync).forEach(([key, value]) => {
|
||||||
const oldValue = config[key]
|
const oldValue = config[key]
|
||||||
const defaultValue = value
|
const defaultValue = value
|
||||||
|
|
|
||||||
|
|
@ -292,7 +292,10 @@ export const useUserHighlightStore = defineStore('user_highlight', {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
storage.setItem('vuex-lz', { ...vuexState, config: { ...config, highlight } })
|
storage.setItem('vuex-lz', {
|
||||||
|
...vuexState,
|
||||||
|
config: { ...config, highlight },
|
||||||
|
})
|
||||||
|
|
||||||
if (recent === null) {
|
if (recent === null) {
|
||||||
console.debug(
|
console.debug(
|
||||||
|
|
|
||||||
|
|
@ -129,7 +129,7 @@ describe('Gallery', () => {
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
it('mixed attachments', () => {
|
it('mixed attachments 1', () => {
|
||||||
local = {
|
local = {
|
||||||
attachments: [
|
attachments: [
|
||||||
{ type: 'audio' },
|
{ type: 'audio' },
|
||||||
|
|
@ -138,7 +138,6 @@ describe('Gallery', () => {
|
||||||
{ type: 'image' },
|
{ type: 'image' },
|
||||||
{ type: 'image' },
|
{ type: 'image' },
|
||||||
{ type: 'image' },
|
{ type: 'image' },
|
||||||
{ type: 'image' },
|
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -151,17 +150,17 @@ describe('Gallery', () => {
|
||||||
{ type: 'image' },
|
{ type: 'image' },
|
||||||
{ type: 'image' },
|
{ type: 'image' },
|
||||||
{ type: 'image' },
|
{ type: 'image' },
|
||||||
{ type: 'image' },
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
it('mixed attachments 2', () => {
|
||||||
local = {
|
local = {
|
||||||
attachments: [
|
attachments: [
|
||||||
{ type: 'image' },
|
{ type: 'image' },
|
||||||
{ type: 'image' },
|
{ type: 'image' },
|
||||||
{ type: 'image' },
|
{ type: 'image' },
|
||||||
{ type: 'image' },
|
|
||||||
{ type: 'audio' },
|
{ type: 'audio' },
|
||||||
{ type: 'image' },
|
{ type: 'image' },
|
||||||
{ type: 'audio' },
|
{ type: 'audio' },
|
||||||
|
|
@ -172,12 +171,13 @@ describe('Gallery', () => {
|
||||||
{
|
{
|
||||||
items: [{ type: 'image' }, { type: 'image' }, { type: 'image' }],
|
items: [{ type: 'image' }, { type: 'image' }, { type: 'image' }],
|
||||||
},
|
},
|
||||||
{ items: [{ type: 'image' }] },
|
|
||||||
{ audio: true, items: [{ type: 'audio' }] },
|
{ audio: true, items: [{ type: 'audio' }] },
|
||||||
{ items: [{ type: 'image' }] },
|
{ items: [{ type: 'image' }] },
|
||||||
{ audio: true, items: [{ type: 'audio' }] },
|
{ audio: true, items: [{ type: 'audio' }] },
|
||||||
])
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
it('7 images', () => {
|
||||||
local = {
|
local = {
|
||||||
attachments: [
|
attachments: [
|
||||||
{ type: 'image' },
|
{ type: 'image' },
|
||||||
|
|
@ -205,7 +205,9 @@ describe('Gallery', () => {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
it('8 images', () => {
|
||||||
local = {
|
local = {
|
||||||
attachments: [
|
attachments: [
|
||||||
{ type: 'image' },
|
{ type: 'image' },
|
||||||
|
|
@ -230,6 +232,54 @@ describe('Gallery', () => {
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('4 images + audio + image + 4 images', () => {
|
||||||
|
local = {
|
||||||
|
attachments: [
|
||||||
|
{ type: 'image' },
|
||||||
|
{ type: 'image' },
|
||||||
|
{ type: 'image' },
|
||||||
|
{ type: 'image' },
|
||||||
|
{ type: 'audio' },
|
||||||
|
{ type: 'image' },
|
||||||
|
{ type: 'audio' },
|
||||||
|
{ type: 'image' },
|
||||||
|
{ type: 'image' },
|
||||||
|
{ type: 'image' },
|
||||||
|
{ type: 'image' },
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(Gallery.computed.rows.call(local)).to.eql([
|
||||||
|
{
|
||||||
|
items: [
|
||||||
|
{ type: 'image' },
|
||||||
|
{ type: 'image' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
items: [
|
||||||
|
{ type: 'image' },
|
||||||
|
{ type: 'image' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{ audio: true, items: [{ type: 'audio' }] },
|
||||||
|
{ items: [{ type: 'image' }] },
|
||||||
|
{ audio: true, items: [{ type: 'audio' }] },
|
||||||
|
{
|
||||||
|
items: [
|
||||||
|
{ type: 'image' },
|
||||||
|
{ type: 'image' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
items: [
|
||||||
|
{ type: 'image' },
|
||||||
|
{ type: 'image' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
it('does not do grouping when grid is set', () => {
|
it('does not do grouping when grid is set', () => {
|
||||||
const attachments = [
|
const attachments = [
|
||||||
{ type: 'audio' },
|
{ type: 'audio' },
|
||||||
|
|
|
||||||
61
test/unit/specs/components/post_status_form.spec.js
Normal file
61
test/unit/specs/components/post_status_form.spec.js
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
import { createTestingPinia } from '@pinia/testing'
|
||||||
|
import { mount } from '@vue/test-utils'
|
||||||
|
import { setActivePinia } from 'pinia'
|
||||||
|
|
||||||
|
import PostStatusForm from 'src/components/post_status_form/post_status_form.vue'
|
||||||
|
import { mountOpts } from '../../../fixtures/setup_test'
|
||||||
|
|
||||||
|
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
|
||||||
|
|
||||||
|
const currentUser = {
|
||||||
|
id: 'current-user',
|
||||||
|
default_scope: 'public',
|
||||||
|
locked: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
const repliedUser = {
|
||||||
|
id: 'replied-user',
|
||||||
|
screen_name: 'replied',
|
||||||
|
}
|
||||||
|
|
||||||
|
const repliedStatus = {
|
||||||
|
id: 'status-1',
|
||||||
|
visibility: 'public',
|
||||||
|
user: repliedUser,
|
||||||
|
}
|
||||||
|
|
||||||
|
const replyMountOpts = () =>
|
||||||
|
mountOpts({
|
||||||
|
props: {
|
||||||
|
replyTo: repliedStatus.id,
|
||||||
|
repliedUser,
|
||||||
|
attentions: [],
|
||||||
|
copyMessageScope: repliedStatus.visibility,
|
||||||
|
disableDraft: true,
|
||||||
|
},
|
||||||
|
afterStore(store) {
|
||||||
|
store.state.users.currentUser = currentUser
|
||||||
|
store.state.statuses.allStatusesObject = {
|
||||||
|
[repliedStatus.id]: repliedStatus,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('PostStatusForm', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
setActivePinia(createTestingPinia())
|
||||||
|
})
|
||||||
|
|
||||||
|
it('initializes a reply form when quoteReply is unset', () => {
|
||||||
|
useInstanceCapabilitiesStore().quotingAvailable = true
|
||||||
|
|
||||||
|
const wrapper = mount(PostStatusForm, replyMountOpts())
|
||||||
|
|
||||||
|
expect(wrapper.vm.newStatus.type).to.equal('reply')
|
||||||
|
expect(wrapper.vm.newStatus.quote).to.eql({
|
||||||
|
id: '',
|
||||||
|
url: '',
|
||||||
|
thread: false,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
@ -232,7 +232,8 @@ describe('The SyncConfig store', () => {
|
||||||
expect(store.prefsStorage._journal.length).to.eql(2)
|
expect(store.prefsStorage._journal.length).to.eql(2)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should remove depth = 3 set/unset entries from journal', () => {
|
// TODO We need a proper test for object-based stores
|
||||||
|
it.skip('should remove depth = 3 set/unset entries from journal', () => {
|
||||||
const store = useSyncConfigStore()
|
const store = useSyncConfigStore()
|
||||||
// PushSyncConfig is very simple but uses vuex to push data
|
// PushSyncConfig is very simple but uses vuex to push data
|
||||||
store.pushSyncConfig = () => {
|
store.pushSyncConfig = () => {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue