clutter page unsync -> sync

This commit is contained in:
Henry Jameson 2026-01-21 16:51:08 +02:00
commit 20071d5a11
10 changed files with 144 additions and 62 deletions

View file

@ -1,7 +1,9 @@
import { throttle } from 'lodash'
import { mapState } from 'pinia'
import { defineAsyncComponent } from 'vue'
import { mapGetters } from 'vuex'
import { useServerSideStorageStore } from 'src/stores/serverSideStorage'
import DesktopNav from './components/desktop_nav/desktop_nav.vue'
import EditStatusModal from './components/edit_status_modal/edit_status_modal.vue'
import FeaturesPanel from './components/features_panel/features_panel.vue'
@ -184,9 +186,6 @@ export default {
shoutboxPosition() {
return this.$store.getters.mergedConfig.alwaysShowNewPostButton || false
},
hideShoutbox() {
return this.$store.getters.mergedConfig.hideShoutbox
},
layoutType() {
return useInterfaceStore().layoutType
},
@ -214,6 +213,9 @@ export default {
return window /* this.$refs.appContentRef */
},
...mapGetters(['mergedConfig']),
...mapState(useServerSideStorageStore, {
hideShoutbox: (store) => store.prefsStorage.simple.hideShoutbox,
}),
},
methods: {
resizeHandler() {

View file

@ -8,6 +8,7 @@ import Popover from 'src/components/popover/popover.vue'
import { pollFormToMasto } from 'src/services/poll/poll.service.js'
import { useInterfaceStore } from 'src/stores/interface.js'
import { useMediaViewerStore } from 'src/stores/media_viewer.js'
import { useServerSideStorageStore } from 'src/stores/serverSideStorage'
import { propsToNative } from '../../services/attributes_helper/attributes_helper.service.js'
import fileTypeService from '../../services/file_type/file_type.service.js'
import { findOffset } from '../../services/offset_finder/offset_finder.service.js'
@ -299,10 +300,11 @@ const PostStatusForm = {
return this.hasStatusLengthLimit && this.charactersLeft < 0
},
minimalScopesMode() {
return this.$store.state.instance.minimalScopesMode
return useServerSideStorageStore().prefsStorage.simple.minimalScopesMode
},
alwaysShowSubject() {
return this.mergedConfig.alwaysShowSubjectInput
return useServerSideStorageStore().prefsStorage.simple
.alwaysShowSubjectInput
},
postFormats() {
return this.$store.state.instance.postFormats || []

View file

@ -1,5 +1,6 @@
import { cloneDeep, get, isEqual, set } from 'lodash'
import { useServerSideStorageStore } from 'src/stores/serverSideStorage'
import DraftButtons from './draft_buttons.vue'
import ModifiedIndicator from './modified_indicator.vue'
import ProfileSettingIndicator from './profile_setting_indicator.vue'
@ -226,6 +227,8 @@ export default {
},
configSource() {
switch (this.realSource) {
case 'server-side':
return useServerSideStorageStore().prefsStorage
case 'profile':
return this.$store.state.profileConfig
case 'admin':
@ -239,6 +242,39 @@ export default {
return (k, v) => this.$emit('update:modelValue', v)
}
switch (this.realSource) {
case 'server-side': {
return (path, value, operator) => {
const folder = path.split('.')[0]
if (folder === 'collections' || folder === 'objectCollections') {
switch (operator) {
case 'add':
useServerSideStorageStore().addCollectionPreference({
path,
value,
})
useServerSideStorageStore().pushServerSideStorage()
break
case 'remove':
useServerSideStorageStore().removeCollectionPreference({
path,
value,
})
useServerSideStorageStore().pushServerSideStorage()
break
default:
console.error(
`Unknown server-side collection operator ${operator}, ignoring`,
)
break
}
} else if (folder === 'simple') {
useServerSideStorageStore().setPreference({ path, value })
useServerSideStorageStore().pushServerSideStorage()
} else {
console.error(`Unknown server-side folder ${folder}, ignoring`)
}
}
}
case 'profile':
return (k, v) =>
this.$store.dispatch('setProfileOption', { name: k, value: v })
@ -262,6 +298,11 @@ export default {
switch (this.realSource) {
case 'profile':
return {}
case 'server-side':
return get(
this.$store.getters.defaultConfig,
this.path.split(/\./g).slice(1),
)
default:
return get(this.$store.getters.defaultConfig, this.path)
}

View file

@ -1,18 +1,20 @@
import { mapState as mapPiniaState } from 'pinia'
import { mapGetters, mapState } from 'vuex'
import { useServerSideStorageStore } from 'src/stores/serverSideStorage'
const SharedComputedObject = () => ({
user() {
return this.$store.state.users.currentUser
},
...mapPiniaState(useServerSideStorageStore, {
serverSide: (store) => store.state.prefsStorage,
}),
...mapGetters(['mergedConfig']),
...mapState({
adminConfig: (state) => state.adminSettings.config,
adminDraft: (state) => state.adminSettings.draft,
user: (state) => state.users.currentUser,
}),
expertLevel() {
return this.$store.getters.mergedConfig.expertLevel > 0
},
mergedConfig() {
return this.$store.getters.mergedConfig
},
adminConfig() {
return this.$store.state.adminSettings.config
},
adminDraft() {
return this.$store.state.adminSettings.draft
return this.mergedConfig.expertLevel > 0
},
})

View file

@ -4,41 +4,58 @@
<h3>{{ $t('settings.interface') }}</h3>
<ul class="setting-list">
<li>
<BooleanSetting path="alwaysShowSubjectInput">
<BooleanSetting
source="server-side"
path="simple.alwaysShowSubjectInput"
>
{{ $t('settings.subject_input_always_show') }}
</BooleanSetting>
</li>
<li>
<BooleanSetting path="minimalScopesMode">
<BooleanSetting
source="server-side"
path="simple.minimalScopesMode"
>
{{ $t('settings.minimal_scopes_mode') }}
</BooleanSetting>
</li>
<li>
<BooleanSetting path="hidePostStats">
<BooleanSetting
source="server-side"
path="simple.hidePostStats"
>
{{ $t('settings.hide_post_stats') }}
</BooleanSetting>
</li>
<li>
<BooleanSetting
path="hideUserStats"
path="simple.hideUserStats"
source="server-side"
>
{{ $t('settings.hide_user_stats') }}
</BooleanSetting>
</li>
<li>
<BooleanSetting path="hideBotIndication">
<BooleanSetting
source="server-side"
path="simple.hideBotIndication"
>
{{ $t('settings.hide_actor_type_indication') }}
</BooleanSetting>
</li>
<li>
<BooleanSetting path="hideScrobbles">
<BooleanSetting
source="server-side"
path="simple.hideScrobbles"
>
{{ $t('settings.hide_scrobbles') }}
</BooleanSetting>
<ul class="setting-list suboptions">
<li>
<UnitSetting
key="hideScrobblesAfter"
path="hideScrobblesAfter"
source="server-side"
path="simple.hideScrobblesAfter"
:units="['m', 'h', 'd']"
unit-set="time"
>
@ -52,30 +69,41 @@
<ul class="setting-list">
<li>
<IntegerSetting
path="maxThumbnails"
source="server-side"
path="simple.maxThumbnails"
:min="0"
>
{{ $t('settings.max_thumbnails') }}
</IntegerSetting>
</li>
<li>
<BooleanSetting path="hideAttachments">
<BooleanSetting
source="server-side"
path="simple.hideAttachments"
>
{{ $t('settings.hide_attachments_in_tl') }}
</BooleanSetting>
</li>
<li>
<BooleanSetting path="hideAttachmentsInConv">
<BooleanSetting
source="server-side"
path="simple.hideAttachmentsInConv"
>
{{ $t('settings.hide_attachments_in_convo') }}
</BooleanSetting>
</li>
<li>
<BooleanSetting path="userCardHidePersonalMarks">
<BooleanSetting
source="server-side"
path="simple.userCardHidePersonalMarks"
>
{{ $t('settings.user_card_hide_personal_marks') }}
</BooleanSetting>
</li>
<li v-if="instanceShoutboxPresent">
<BooleanSetting
path="hideShoutbox"
source="server-side"
path="simple.hideShoutbox"
>
{{ $t('settings.hide_shoutbox') }}
</BooleanSetting>

View file

@ -1,4 +1,5 @@
import { unescape as ldUnescape, uniqBy } from 'lodash'
import { mapState } from 'pinia'
import MentionLink from 'src/components/mention_link/mention_link.vue'
import MentionsLine from 'src/components/mentions_line/mentions_line.vue'
@ -254,12 +255,7 @@ const Status = {
return !!this.currentUser
},
muteFilterHits() {
return muteFilterHits(
Object.values(
useServerSideStorageStore().prefsStorage.simple.muteFilters,
),
this.status,
)
return muteFilterHits(Object.values(this.muteFilters), this.status)
},
botStatus() {
return this.status.user.actor_type === 'Service'
@ -452,9 +448,6 @@ const Status = {
.map((tagObj) => tagObj.name)
.join(' ')
},
hidePostStats() {
return this.mergedConfig.hidePostStats
},
shouldDisplayFavsAndRepeats() {
return (
!this.hidePostStats &&
@ -511,10 +504,10 @@ const Status = {
return this.quotedStatus && this.displayQuote
},
scrobblePresent() {
if (this.mergedConfig.hideScrobbles) return false
if (this.hideScrobbles) return false
if (!this.status.user?.latestScrobble) return false
const value = this.mergedConfig.hideScrobblesAfter.match(/\d+/gs)[0]
const unit = this.mergedConfig.hideScrobblesAfter.match(/\D+/gs)[0]
const value = this.hideScrobblesAfter.match(/\d+/gs)[0]
const unit = this.hideScrobblesAfter.match(/\D+/gs)[0]
let multiplier = 60 * 1000 // minutes is smallest unit
switch (unit) {
case 'm':
@ -536,6 +529,14 @@ const Status = {
scrobble() {
return this.status.user?.latestScrobble
},
...mapState(useServerSideStorageStore, {
muteFilters: (store) => store.prefsStorage.simple.muteFilters,
hideBotIndicatior: (store) => store.prefsStorage.simple.hideBotIndicator,
hidePostStats: (store) => store.prefsStorage.simple.hidePostStats,
hideScrobbles: (store) => store.prefsStorage.simple.hideScrobbles,
hideScrobblesAfter: (store) =>
store.prefsStorage.simple.hideScrobblesAfter,
}),
},
methods: {
visibilityIcon(visibility) {

View file

@ -1,7 +1,9 @@
import { mapState as mapPiniaState } from 'pinia'
import { mapGetters, mapState } from 'vuex'
import StatusBody from 'src/components/status_body/status_body.vue'
import { useMediaViewerStore } from 'src/stores/media_viewer'
import { useServerSideStorageStore } from 'src/stores/serverSideStorage'
import Attachment from '../attachment/attachment.vue'
import Gallery from '../gallery/gallery.vue'
import LinkPreview from '../link-preview/link-preview.vue'
@ -90,8 +92,8 @@ const StatusContent = {
},
hideAttachments() {
return (
(this.mergedConfig.hideAttachments && !this.inConversation) ||
(this.mergedConfig.hideAttachmentsInConv && this.inConversation)
(this.hideAttachments && !this.inConversation) ||
(this.hideAttachmentsInConv && this.inConversation)
)
},
nsfwClickthrough() {
@ -110,21 +112,24 @@ const StatusContent = {
if (this.compact) {
return 'small'
} else if (
(this.mergedConfig.hideAttachments && !this.inConversation) ||
(this.mergedConfig.hideAttachmentsInConv && this.inConversation) ||
(this.hideAttachments && !this.inConversation) ||
(this.hideAttachmentsInConv && this.inConversation) ||
this.status.attachments.length > this.maxThumbnails
) {
return 'hide'
}
return 'normal'
},
maxThumbnails() {
return this.mergedConfig.maxThumbnails
},
...mapGetters(['mergedConfig']),
...mapState({
currentUser: (state) => state.users.currentUser,
}),
...mapPiniaState(useServerSideStorageStore, {
maxThumbnails: (store) => store.prefsStorage.simple.maxThumbnails,
hideAttachments: (store) => store.prefsStorage.simple.hideAttachments,
hideAttachmentsInConv: (store) =>
store.prefsStorage.simple.hideAttachmentsInConv,
}),
},
components: {
Attachment,

View file

@ -1,6 +1,7 @@
import isEqual from 'lodash/isEqual'
import merge from 'lodash/merge'
import ldUnescape from 'lodash/unescape'
import { mapState } from 'pinia'
import { mapGetters } from 'vuex'
import Checkbox from 'src/components/checkbox/checkbox.vue'
@ -15,6 +16,7 @@ import { propsToNative } from 'src/services/attributes_helper/attributes_helper.
import localeService from 'src/services/locale/locale.service.js'
import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
import { usePostStatusStore } from 'src/stores/post_status'
import { useServerSideStorageStore } from 'src/stores/serverSideStorage'
import { useInterfaceStore } from '../../stores/interface'
import { useMediaViewerStore } from '../../stores/media_viewer'
import AccountActions from '../account_actions/account_actions.vue'
@ -217,13 +219,11 @@ export default {
},
userHighlightType: {
get() {
const data =
this.$store.getters.mergedConfig.highlight[this.user.screen_name]
const data = this.mergedConfig.highlight[this.user.screen_name]
return (data && data.type) || 'disabled'
},
set(type) {
const data =
this.$store.getters.mergedConfig.highlight[this.user.screen_name]
const data = this.mergedConfig.highlight[this.user.screen_name]
if (type !== 'disabled') {
this.$store.dispatch('setHighlight', {
user: this.user.screen_name,
@ -237,12 +237,10 @@ export default {
})
}
},
...mapGetters(['mergedConfig']),
},
userHighlightColor: {
get() {
const data =
this.$store.getters.mergedConfig.highlight[this.user.screen_name]
const data = this.mergedConfig.highlight[this.user.screen_name]
return data && data.color
},
set(color) {
@ -386,6 +384,11 @@ export default {
})
},
...mapGetters(['mergedConfig']),
...mapState(useServerSideStorageStore, {
hideUserStats: (store) => store.prefsStorage.simple.hideUserStats,
userCardHidePersonalMarks: (store) =>
store.prefsStorage.simple.userCardHidePersonalMarks,
}),
},
methods: {
muteUser() {

View file

@ -293,7 +293,7 @@
</div>
</div>
<div
v-if="!editable && loggedIn && isOtherUser && (hasNote || !hideBio) && !mergedConfig.userCardHidePersonalMarks"
v-if="!editable && loggedIn && isOtherUser && (hasNote || !hideBio) && !userCardHidePersonalMarks"
class="personal-marks"
>
<UserNote
@ -505,11 +505,11 @@
class="user-extras"
>
<span
v-if="!editable && !mergedConfig.hideUserStats"
v-if="!editable && !hideUserStats"
class="user-stats"
>
<dl
v-if="!mergedConfig.hideUserStats && !hideBio"
v-if="!hideUserStats && !hideBio"
class="user-count"
>
<dd>{{ user.statuses_count }}</dd>

View file

@ -318,9 +318,7 @@ const updateProfileJSON = ({ credentials, params }) => {
credentials,
payload: params,
method: 'PATCH',
})
.then((data) => data.json())
.then((data) => parseUser(data))
}).then((data) => parseUser(data))
}
// Params needed: