Timeline Animations Toggle

This commit is contained in:
Leafy :3 2025-02-11 23:52:28 +01:00
parent 358e7ea049
commit 854f37a8c5
6 changed files with 140 additions and 293 deletions

View file

@ -120,6 +120,11 @@ export default {
},
noSticky () { return this.$store.getters.mergedConfig.disableStickyHeaders },
showScrollbars () { return this.$store.getters.mergedConfig.showScrollbars },
rootAttributes() {
return {
'data-enable-animations': this.$store.state.interface.enableTimelineAnimations ? 'true' : 'false'
}
},
...mapGetters(['mergedConfig'])
},
methods: {
@ -127,5 +132,15 @@ export default {
this.$store.dispatch('setLayoutWidth', windowWidth())
this.$store.dispatch('setLayoutHeight', windowHeight())
}
},
watch: {
'rootAttributes': {
immediate: true,
handler(newAttrs) {
// Apply attributes directly to HTML element
document.documentElement.dataset.enableAnimations =
this.$store.state.interface.enableTimelineAnimations ? 'true' : 'false'
}
}
}
}

View file

@ -2,6 +2,7 @@
<div
id="app-loaded"
:style="bgStyle"
v-bind="rootAttributes"
>
<div
id="app_bg_wrapper"
@ -78,4 +79,4 @@
</template>
<script src="./App.js"></script>
<style lang="scss" src="./App.scss"></style>
<style lang="scss" src="./App.scss"></style>

View file

@ -25,6 +25,7 @@ const GeneralTab = {
},
data () {
return {
animationsEnabled: localStorage.getItem('timelineAnimationsEnabled') !== 'false',
subjectLineOptions: ['email', 'noop', 'masto'].map(mode => ({
key: mode,
value: mode,
@ -67,6 +68,10 @@ const GeneralTab = {
}
},
mounted() {
console.log('Initial animation state:', this.animationsEnabled)
document.documentElement.dataset.enableAnimations = this.timelineAnimations
},
components: {
BooleanSetting,
ChoiceSetting,
@ -130,9 +135,24 @@ const GeneralTab = {
this.$store.dispatch('setOption', { name: 'postLanguage', value: val })
}
},
timelineAnimations: {
get() {
return this.$store.getters.mergedConfig.timelineAnimations !== false
},
set(value) {
this.$store.dispatch('setOption', { name: 'timelineAnimations', value })
document.documentElement.dataset.enableAnimations = value
}
},
...SharedComputedObject()
},
methods: {
toggleAnimations(value) {
console.log('Toggling animations:', value)
this.animationsEnabled = value
localStorage.setItem('timelineAnimationsEnabled', value)
document.documentElement.dataset.enableAnimations = value
},
changeDefaultScope (value) {
this.$store.dispatch('setServerSideOption', { name: 'defaultScope', value })
},

View file

@ -3,97 +3,55 @@
<div class="setting-item">
<ul class="setting-list">
<li>
<interface-language-switcher
:prompt-text="$t('settings.interfaceLanguage')"
:language="language"
:set-language="val => language = val"
/>
<interface-language-switcher :prompt-text="$t('settings.interfaceLanguage')" :language="language"
:set-language="val => language = val" />
</li>
<li
v-if="user && (settingsProfiles.length > 0)"
>
<li v-if="user && (settingsProfiles.length > 0)">
<h2>{{ $t('settings.settings_profile') }}</h2>
<p>
{{ $t('settings.settings_profile_currently', { name: settingsProfile, version: settingsVersion }) }}
<button
class="btn button-default"
@click="forceSync()"
>
<button class="btn button-default" @click="forceSync()">
{{ $t('settings.settings_profile_force_sync') }}
</button>
</p>
<div
@click="toggleExpandedSettings"
>
<template
v-if="profilesExpanded"
>
<div @click="toggleExpandedSettings">
<template v-if="profilesExpanded">
<button class="btn button-default">
{{ $t('settings.settings_profiles_unshow') }}
</button>
</template>
<template
v-else
>
<template v-else>
<button class="btn button-default">
{{ $t('settings.settings_profiles_show') }}
</button>
</template>
</div>
<br>
<template
v-if="profilesExpanded"
>
<div
v-for="profile in settingsProfiles"
:key="profile.id"
class="settings-profile"
>
<template v-if="profilesExpanded">
<div v-for="profile in settingsProfiles" :key="profile.id" class="settings-profile">
<h4>{{ profile.name }} ({{ profile.version }})</h4>
<template
v-if="settingsProfile === profile.name"
>
<template v-if="settingsProfile === profile.name">
{{ $t('settings.settings_profile_in_use') }}
</template>
<template
v-else
>
<button
class="btn button-default"
@click="loadSettingsProfile(profile.name)"
>
<template v-else>
<button class="btn button-default" @click="loadSettingsProfile(profile.name)">
{{ $t('settings.settings_profile_use') }}
</button>
<button
class="btn button-default"
@click="deleteSettingsProfile(profile.name)"
>
<button class="btn button-default" @click="deleteSettingsProfile(profile.name)">
{{ $t('settings.settings_profile_delete') }}
</button>
</template>
</div>
<button
class="btn button-default"
@click="refreshProfiles()"
>
<button class="btn button-default" @click="refreshProfiles()">
{{ $t('settings.settings_profiles_refresh') }}
<FAIcon
icon="sync"
@click="refreshProfiles()"
/>
<FAIcon icon="sync" @click="refreshProfiles()" />
</button>
<h3>{{ $t('settings.settings_profile_creation') }}</h3>
<label for="settings-profile-new-name">
{{ $t('settings.settings_profile_creation_new_name_label') }}
</label>
<input
id="settings-profile-new-name"
v-model="newProfileName"
>
<button
class="btn button-default"
@click="createSettingsProfile"
>
<input id="settings-profile-new-name" v-model="newProfileName">
<button class="btn button-default" @click="createSettingsProfile">
{{ $t('settings.settings_profile_creation_submit') }}
</button>
</template>
@ -115,49 +73,37 @@
</BooleanSetting>
</li>
<li>
<BooleanSetting
path="hideSiteFavicon"
expert="1"
>
<BooleanSetting path="timelineAnimations">
Enable Timeline Animations
</BooleanSetting>
</li>
<li>
<BooleanSetting path="hideSiteFavicon" expert="1">
{{ $t('settings.hide_site_favicon') }}
</BooleanSetting>
</li>
<li>
<BooleanSetting
path="hideSiteName"
expert="1"
>
<BooleanSetting path="hideSiteName" expert="1">
{{ $t('settings.hide_site_name') }}
</BooleanSetting>
</li>
<li>
<BooleanSetting
path="showNavShortcuts"
expert="1"
>
<BooleanSetting path="showNavShortcuts" expert="1">
{{ $t('settings.show_nav_shortcuts') }}
</BooleanSetting>
</li>
<li>
<BooleanSetting
path="showPanelNavShortcuts"
expert="1"
>
<BooleanSetting path="showPanelNavShortcuts" expert="1">
{{ $t('settings.show_panel_nav_shortcuts') }}
</BooleanSetting>
</li>
<li>
<BooleanSetting
path="federatedTimelineVisible"
>
<BooleanSetting path="federatedTimelineVisible">
{{ $t('settings.show_federated_timeline') }}
</BooleanSetting>
</li>
<li>
<BooleanSetting
path="showWiderShortcuts"
expert="1"
>
<BooleanSetting path="showWiderShortcuts" expert="1">
{{ $t('settings.show_wider_shortcuts') }}
</BooleanSetting>
</li>
@ -185,33 +131,21 @@
<BooleanSetting path="streaming">
{{ $t('settings.streaming') }}
</BooleanSetting>
<ul
class="setting-list suboptions"
:class="[{disabled: !streaming}]"
>
<ul class="setting-list suboptions" :class="[{ disabled: !streaming }]">
<li>
<BooleanSetting
path="pauseOnUnfocused"
:disabled="!streaming"
>
<BooleanSetting path="pauseOnUnfocused" :disabled="!streaming">
{{ $t('settings.pause_on_unfocused') }}
</BooleanSetting>
</li>
</ul>
</li>
<li>
<BooleanSetting
path="useStreamingApi"
expert="1"
>
<BooleanSetting path="useStreamingApi" expert="1">
{{ $t('settings.useStreamingApi') }}
</BooleanSetting>
</li>
<li>
<BooleanSetting
path="virtualScrolling"
expert="1"
>
<BooleanSetting path="virtualScrolling" expert="1">
{{ $t('settings.virtual_scrolling') }}
</BooleanSetting>
</li>
@ -220,51 +154,33 @@
<BooleanSetting path="renderMisskeyMarkdown">
{{ $t('settings.render_mfm') }}
</BooleanSetting>
<ul
class="setting-list suboptions"
>
<ul class="setting-list suboptions">
<li>
<BooleanSetting
path="renderMfmOnHover"
:disabled="!renderMisskeyMarkdown"
>
<BooleanSetting path="renderMfmOnHover" :disabled="!renderMisskeyMarkdown">
{{ $t('settings.render_mfm_on_hover') }}
</BooleanSetting>
</li>
</ul>
</li>
<li>
<ChoiceSetting
id="userProfileDefaultTab"
path="userProfileDefaultTab"
:options="userProfileDefaultTabOptions"
>
<ChoiceSetting id="userProfileDefaultTab" path="userProfileDefaultTab"
:options="userProfileDefaultTabOptions">
{{ $t('settings.user_profile_default_tab') }}
</ChoiceSetting>
</li>
<li>
<ChoiceSetting
v-if="user && (translationLanguages.length > 0)"
id="translationLanguage"
path="translationLanguage"
:options="translationLanguages"
>
<ChoiceSetting v-if="user && (translationLanguages.length > 0)" id="translationLanguage"
path="translationLanguage" :options="translationLanguages">
{{ $t('settings.translation_language') }}
</ChoiceSetting>
</li>
<li>
<BooleanSetting
path="alwaysShowNewPostButton"
expert="1"
>
<BooleanSetting path="alwaysShowNewPostButton" expert="1">
{{ $t('settings.always_show_post_button') }}
</BooleanSetting>
</li>
<li>
<BooleanSetting
path="autohideFloatingPostButton"
expert="1"
>
<BooleanSetting path="autohideFloatingPostButton" expert="1">
{{ $t('settings.autohide_floating_post_button') }}
</BooleanSetting>
</li>
@ -287,12 +203,7 @@
</BooleanSetting>
</li>
<li>
<ChoiceSetting
v-if="user"
id="thirdColumnMode"
path="thirdColumnMode"
:options="thirdColumnModeOptions"
>
<ChoiceSetting v-if="user" id="thirdColumnMode" path="thirdColumnMode" :options="thirdColumnModeOptions">
{{ $t('settings.third_column_mode') }}
</ChoiceSetting>
</li>
@ -345,47 +256,29 @@
<h2>{{ $t('settings.post_look_feel') }}</h2>
<ul class="setting-list">
<li>
<ChoiceSetting
id="conversationDisplay"
path="conversationDisplay"
:options="conversationDisplayOptions"
>
<ChoiceSetting id="conversationDisplay" path="conversationDisplay" :options="conversationDisplayOptions">
{{ $t('settings.conversation_display') }}
</ChoiceSetting>
</li>
<ul
v-if="conversationDisplay !== 'linear'"
class="setting-list suboptions"
>
<ul v-if="conversationDisplay !== 'linear'" class="setting-list suboptions">
<li>
<BooleanSetting path="conversationTreeAdvanced">
{{ $t('settings.tree_advanced') }}
</BooleanSetting>
</li>
<li>
<BooleanSetting
path="conversationTreeFadeAncestors"
:expert="1"
>
<BooleanSetting path="conversationTreeFadeAncestors" :expert="1">
{{ $t('settings.tree_fade_ancestors') }}
</BooleanSetting>
</li>
<li>
<IntegerSetting
path="maxDepthInThread"
:min="3"
:expert="1"
>
<IntegerSetting path="maxDepthInThread" :min="3" :expert="1">
{{ $t('settings.max_depth_in_thread') }}
</IntegerSetting>
</li>
<li>
<ChoiceSetting
id="conversationOtherRepliesButton"
path="conversationOtherRepliesButton"
:options="conversationOtherRepliesButtonOptions"
:expert="1"
>
<ChoiceSetting id="conversationOtherRepliesButton" path="conversationOtherRepliesButton"
:options="conversationOtherRepliesButtonOptions" :expert="1">
{{ $t('settings.conversation_other_replies_button') }}
</ChoiceSetting>
</li>
@ -396,28 +289,18 @@
</BooleanSetting>
</li>
<li>
<BooleanSetting
path="emojiReactionsOnTimeline"
expert="1"
>
<BooleanSetting path="emojiReactionsOnTimeline" expert="1">
{{ $t('settings.emoji_reactions_on_timeline') }}
</BooleanSetting>
</li>
<li>
<BooleanSetting
v-if="user"
path="serverSide_stripRichContent"
expert="1"
>
<BooleanSetting v-if="user" path="serverSide_stripRichContent" expert="1">
{{ $t('settings.no_rich_text_description') }}
</BooleanSetting>
</li>
<h3>{{ $t('settings.attachments') }}</h3>
<li>
<BooleanSetting
path="useContainFit"
expert="1"
>
<BooleanSetting path="useContainFit" expert="1">
{{ $t('settings.use_contain_fit') }}
</BooleanSetting>
</li>
@ -428,87 +311,50 @@
</li>
<ul class="setting-list suboptions">
<li>
<BooleanSetting
path="preloadImage"
expert="1"
:disabled="!hideNsfw"
>
<BooleanSetting path="preloadImage" expert="1" :disabled="!hideNsfw">
{{ $t('settings.preload_images') }}
</BooleanSetting>
</li>
<li>
<BooleanSetting
path="useBlurhash"
expert="1"
:disabled="!hideNsfw"
>
<BooleanSetting path="useBlurhash" expert="1" :disabled="!hideNsfw">
{{ $t('settings.use_blurhash') }}
</BooleanSetting>
</li>
<li>
<BooleanSetting
path="useOneClickNsfw"
expert="1"
:disabled="!hideNsfw"
>
<BooleanSetting path="useOneClickNsfw" expert="1" :disabled="!hideNsfw">
{{ $t('settings.use_one_click_nsfw') }}
</BooleanSetting>
</li>
</ul>
<li>
<BooleanSetting
path="loopVideo"
expert="1"
>
<BooleanSetting path="loopVideo" expert="1">
{{ $t('settings.loop_video') }}
</BooleanSetting>
<ul
class="setting-list suboptions"
:class="[{disabled: !streaming}]"
>
<ul class="setting-list suboptions" :class="[{ disabled: !streaming }]">
<li>
<BooleanSetting
path="loopVideoSilentOnly"
expert="1"
:disabled="!loopVideo || !loopSilentAvailable"
>
<BooleanSetting path="loopVideoSilentOnly" expert="1" :disabled="!loopVideo || !loopSilentAvailable">
{{ $t('settings.loop_video_silent_only') }}
</BooleanSetting>
<div
v-if="!loopSilentAvailable"
class="unavailable"
>
<div v-if="!loopSilentAvailable" class="unavailable">
<FAIcon icon="globe" />! {{ $t('settings.limited_availability') }}
</div>
</li>
</ul>
</li>
<li>
<BooleanSetting
path="playVideosInModal"
expert="1"
>
<BooleanSetting path="playVideosInModal" expert="1">
{{ $t('settings.play_videos_in_modal') }}
</BooleanSetting>
</li>
<h3>{{ $t('settings.mention_links') }}</h3>
<li>
<ChoiceSetting
id="mentionLinkDisplay"
path="mentionLinkDisplay"
:options="mentionLinkDisplayOptions"
>
<ChoiceSetting id="mentionLinkDisplay" path="mentionLinkDisplay" :options="mentionLinkDisplayOptions">
{{ $t('settings.mention_link_display') }}
</ChoiceSetting>
</li>
<ul
class="setting-list suboptions"
>
<ul class="setting-list suboptions">
<li v-if="mentionLinkDisplay === 'short'">
<BooleanSetting
path="mentionLinkShowTooltip"
expert="1"
>
<BooleanSetting path="mentionLinkShowTooltip" expert="1">
{{ $t('settings.mention_link_show_tooltip') }}
</BooleanSetting>
</li>
@ -519,18 +365,12 @@
</BooleanSetting>
</li>
<li>
<BooleanSetting
path="mentionLinkFadeDomain"
expert="1"
>
<BooleanSetting path="mentionLinkFadeDomain" expert="1">
{{ $t('settings.mention_link_fade_domain') }}
</BooleanSetting>
</li>
<li v-if="user">
<BooleanSetting
path="mentionLinkBoldenYou"
expert="1"
>
<BooleanSetting path="mentionLinkBoldenYou" expert="1">
{{ $t('settings.mention_link_bolden_you') }}
</BooleanSetting>
</li>
@ -538,39 +378,27 @@
{{ $t('settings.fun') }}
</h3>
<li>
<BooleanSetting
path="greentext"
expert="1"
>
<BooleanSetting path="greentext" expert="1">
{{ $t('settings.greentext') }}
</BooleanSetting>
</li>
<li v-if="user">
<BooleanSetting
path="mentionLinkShowYous"
expert="1"
>
<BooleanSetting path="mentionLinkShowYous" expert="1">
{{ $t('settings.show_yous') }}
</BooleanSetting>
</li>
</ul>
</div>
<div
v-if="user"
class="setting-item"
>
<div v-if="user" class="setting-item">
<h2>{{ $t('settings.composing') }}</h2>
<ul class="setting-list">
<li>
<label for="default-vis">
{{ $t('settings.default_vis') }} <ServerSideIndicator :server-side="true" />
<ScopeSelector
class="scope-selector"
:user-default="serverSide_defaultScope"
:initial-scope="serverSide_defaultScope"
:on-scope-change="changeDefaultScope"
/>
{{ $t('settings.default_vis') }}
<ServerSideIndicator :server-side="true" />
<ScopeSelector class="scope-selector" :user-default="serverSide_defaultScope"
:initial-scope="serverSide_defaultScope" :on-scope-change="changeDefaultScope" />
</label>
</li>
<li>
@ -584,62 +412,37 @@
</BooleanSetting>
</li>
<li>
<BooleanSetting
path="alwaysShowSubjectInput"
expert="1"
>
<BooleanSetting path="alwaysShowSubjectInput" expert="1">
{{ $t('settings.subject_input_always_show') }}
</BooleanSetting>
</li>
<li>
<ChoiceSetting
id="subjectLineBehavior"
path="subjectLineBehavior"
:options="subjectLineOptions"
expert="1"
>
<ChoiceSetting id="subjectLineBehavior" path="subjectLineBehavior" :options="subjectLineOptions" expert="1">
{{ $t('settings.subject_line_behavior') }}
</ChoiceSetting>
</li>
<li v-if="postFormats.length > 0">
<ChoiceSetting
id="postContentType"
path="postContentType"
:options="postContentOptions"
>
<ChoiceSetting id="postContentType" path="postContentType" :options="postContentOptions">
{{ $t('settings.post_status_content_type') }}
</ChoiceSetting>
</li>
<li>
<ChoiceSetting
id="postLanguage"
path="postLanguage"
:options="postLanguageOptions"
>
<ChoiceSetting id="postLanguage" path="postLanguage" :options="postLanguageOptions">
{{ $t('settings.post_language') }}
</ChoiceSetting>
</li>
<li>
<BooleanSetting
path="alwaysShowNewPostButton"
expert="1"
>
<BooleanSetting path="alwaysShowNewPostButton" expert="1">
{{ $t('settings.always_show_post_button') }}
</BooleanSetting>
</li>
<li>
<BooleanSetting
path="autohideFloatingPostButton"
expert="1"
>
<BooleanSetting path="autohideFloatingPostButton" expert="1">
{{ $t('settings.autohide_floating_post_button') }}
</BooleanSetting>
</li>
<li>
<BooleanSetting
path="padEmoji"
expert="1"
>
<BooleanSetting path="padEmoji" expert="1">
{{ $t('settings.pad_emoji') }}
</BooleanSetting>
</li>
@ -648,7 +451,8 @@
</div>
</template>
<script src="./general_tab.js"></script>
<script src="./general_tab.js"/>
<style lang="scss">
.settings-profile {
margin-bottom: 1em;

View file

@ -35,16 +35,27 @@
.timeline-post {
transform-origin: center;
transition: transform 0.2s ease;
&:hover {
transform: scale(1.01);
}
}
.status-fadein {
animation: statusAppear 0.3s ease-out;
animation-fill-mode: both;
:root[data-enable-animations="true"] {
.timeline-post {
transition: transform 0.2s ease;
&:hover {
transform: scale(1.01);
}
@for $i from 0 through 20 {
&:nth-child(#{$i}) {
animation-delay: #{$i * 0.05}s;
}
}
}
.status-fadein {
animation: statusAppear 0.3s ease-out;
animation-fill-mode: both;
}
}
@keyframes statusAppear {
@ -57,11 +68,3 @@
transform: translateY(0);
}
}
.timeline-post {
@for $i from 0 through 20 {
&:nth-child(#{$i}) {
animation-delay: #{$i * 0.05}s;
}
}
}

View file

@ -19,7 +19,8 @@ const defaultState = {
layoutType: 'normal',
globalNotices: [],
layoutHeight: 0,
lastTimeline: null
lastTimeline: null,
enableTimelineAnimations: true
}
const interfaceMod = {
@ -104,6 +105,9 @@ const interfaceMod = {
},
setLastTimeline (state, value) {
state.lastTimeline = value
},
setOption (state, { name, value }) {
state[name] = value
}
},
actions: {