copy sharkey settings into new frontend preferences model

This commit is contained in:
Hazelnoot 2025-03-31 14:53:02 -04:00
parent 59ce4d6c28
commit c371af34e8
50 changed files with 468 additions and 425 deletions

View file

@ -30,7 +30,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<FormSection v-if="instance.repositoryUrl !== 'https://activitypub.software/TransFem-org/Sharkey/'">
<div class="_gaps_s">
<MkInfo>
{{ i18n.tsx._aboutMisskey.thisIsModifiedVersion({ name: instance.name }) }}
{{ i18n.tsx._aboutMisskey.thisIsModifiedVersion({ name: instance.name ?? '' }) }}
</MkInfo>
<FormLink v-if="instance.repositoryUrl" :to="instance.repositoryUrl" external>
<template #icon><i class="ti ti-code"></i></template>
@ -91,7 +91,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</template>
<script lang="ts" setup>
import { nextTick, onBeforeUnmount, ref, shallowRef, computed } from 'vue';
import { nextTick, onBeforeUnmount, ref, computed, useTemplateRef } from 'vue';
import { version } from '@@/js/config.js';
import FormLink from '@/components/form/link.vue';
import FormSection from '@/components/form/section.vue';
@ -101,12 +101,12 @@ import MkInfo from '@/components/MkInfo.vue';
import { physics } from '@/utility/physics.js';
import { i18n } from '@/i18n.js';
import { instance } from '@/instance.js';
import { defaultStore } from '@/store.js';
import * as os from '@/os.js';
import { misskeyApi } from '@/utility/misskey-api.js';
import { definePageMetadata } from '@/utility/page-metadata.js';
import { claimAchievement, claimedAchievements } from '@/utility/achievements.js';
import { $i } from '@/account.js';
import { $i } from '@/i';
import { definePage } from '@/page';
import { store } from '@/store.js';
type Section = {
heading: string,
@ -124,8 +124,13 @@ type Section = {
const thereIsTreasure = ref($i && !claimedAchievements.includes('foundTreasure'));
let easterEggReady = false;
const easterEggEmojis = ref([]);
const easterEggEngine = ref(null);
const easterEggEmojis = ref<{
id: string,
top: number,
left: number,
emoji: string
}[]>([]);
const easterEggEngine = ref<{ stop: () => void } | null>(null);
const everyone = ref<Section[]>([
{
heading: i18n.ts._aboutMisskey.projectMembers,
@ -262,7 +267,7 @@ const everyone = ref<Section[]>([
],
},
]);
const containerEl = shallowRef<HTMLElement>();
const containerEl = useTemplateRef('containerEl');
await misskeyApi('sponsors', { forceUpdate: false }).then((res) => {
const section: Section = {
@ -293,7 +298,7 @@ function fisher_yates<T>(array: T[]): T[] {
}
function iconLoaded() {
const emojis = defaultStore.state.reactions;
const emojis = store.s.reactions;
const containerWidth = containerEl.value.offsetWidth;
for (let i = 0; i < 32; i++) {
easterEggEmojis.value.push({
@ -337,7 +342,7 @@ const headerActions = computed(() => []);
const headerTabs = computed(() => []);
definePageMetadata(() => ({
definePage(() => ({
title: i18n.ts.aboutMisskey,
icon: null,
}));

View file

@ -63,7 +63,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<script lang="ts" setup>
import { computed, useTemplateRef, ref, watchEffect } from 'vue';
import XHeader from './_header_.vue';
import { defaultMemoryStorage } from '@/memory-storage';
import { defaultMemoryStorage } from '@/memory-storage.js';
import MkButton from '@/components/MkButton.vue';
import MkInput from '@/components/MkInput.vue';
import MkSelect from '@/components/MkSelect.vue';

View file

@ -100,6 +100,7 @@ import { notesSearchAvailable } from '@/utility/check-permissions.js';
import { miLocalStorage } from '@/local-storage.js';
import { useRouter } from '@/router.js';
import { deepMerge } from '@/utility/merge.js';
import { store } from '@/store.js';
const router = useRouter();
@ -122,12 +123,12 @@ const featuredPagination = computed(() => ({
},
}));
const withRenotes = computed<boolean>({
get: () => defaultStore.reactiveState.tl.value.filter.withRenotes,
get: () => store.r.tl.value.filter.withRenotes,
set: (x) => saveTlFilter('withRenotes', x),
});
const onlyFiles = computed<boolean>({
get: () => defaultStore.reactiveState.tl.value.filter.onlyFiles,
get: () => store.r.tl.value.filter.onlyFiles,
set: (x) => saveTlFilter('onlyFiles', x),
});
@ -150,10 +151,9 @@ watch(() => props.channelId, async () => {
}
}, { immediate: true });
function saveTlFilter(key: keyof typeof defaultStore.state.tl.filter, newValue: boolean) {
function saveTlFilter(key: keyof typeof store.s.tl.filter, newValue: boolean) {
if (key !== 'withReplies' || $i) {
const out = deepMerge({ filter: { [key]: newValue } }, defaultStore.state.tl);
defaultStore.set('tl', out);
store.r.tl.value = deepMerge({ filter: { [key]: newValue } }, store.s.tl);
}
}

View file

@ -16,7 +16,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template #default="{ items }">
<MkDateSeparatedList v-slot="{ item }" :items="items" :direction="'down'" :noGap="false" :ad="false">
<MkNote :key="item.id" :note="item.note" :class="$style.note"/>
<DynamicNote :key="item.id" :note="item.note" :class="$style.note"/>
</MkDateSeparatedList>
</template>
</MkPagination>
@ -27,17 +27,10 @@ SPDX-License-Identifier: AGPL-3.0-only
<script lang="ts" setup>
import MkPagination from '@/components/MkPagination.vue';
import MkDateSeparatedList from '@/components/MkDateSeparatedList.vue';
import { defineAsyncComponent } from 'vue';
import { i18n } from '@/i18n.js';
import { definePage } from '@/page.js';
import { infoImageUrl } from '@/instance.js';
import { defaultStore } from '@/store.js';
const MkNote = defineAsyncComponent(() =>
(defaultStore.state.noteDesign === 'misskey') ? import('@/components/MkNote.vue') :
(defaultStore.state.noteDesign === 'sharkey') ? import('@/components/SkNote.vue') :
null
);
import DynamicNote from '@/components/DynamicNote.vue';
const pagination = {
endpoint: 'i/favorites' as const,

View file

@ -70,8 +70,9 @@ import { $i } from '@/i.js';
// context
const CTX_NOTE = !$i && assertServerContext(serverContext, 'note') ? serverContext.note : null;
// TODO DynamicNoteDetailed
const MkNoteDetailed = defineAsyncComponent(() =>
(defaultStore.state.noteDesign === 'misskey')
(prefer.s.noteDesign === 'misskey')
? import('@/components/MkNoteDetailed.vue')
: import('@/components/SkNoteDetailed.vue'),
);

View file

@ -936,15 +936,15 @@ const noteDesign = prefer.model('noteDesign');
const uncollapseCW = prefer.model('uncollapseCW');
const expandLongNote = prefer.model('expandLongNote');
const disableCatSpeak = prefer.model('disableCatSpeak');
const enableFaviconNotificationDot = prefer.model('enableFaviconNotificationDot');
const enableFaviconNotificationDot = computed(store.makeGetterSetter('enableFaviconNotificationDot'));
const warnMissingAltText = prefer.model('warnMissingAltText');
const notificationClickable = prefer.model('notificationClickable');
const notificationClickable = computed(store.makeGetterSetter('notificationClickable'));
const warnExternalUrl = prefer.model('warnExternalUrl');
const showVisibilitySelectorOnBoost = prefer.model('showVisibilitySelectorOnBoost');
const visibilityOnBoost = prefer.model('visibilityOnBoost');
const cornerRadius = prefer.model('cornerRadius');
const oneko = prefer.model('oneko');
const numberOfReplies = prefer.model('numberOfReplies');
const cornerRadius = computed(store.makeGetterSetter('cornerRadius'));
const oneko = computed(store.makeGetterSetter('oneko'));
const numberOfReplies = computed(store.makeGetterSetter('numberOfReplies'));
const useCustomSearchEngine = computed(() => !Object.keys(searchEngineMap).includes(searchEngine.value));

View file

@ -7,15 +7,15 @@ SPDX-License-Identifier: AGPL-3.0-only
<SearchMarker path="/settings/profile" :label="i18n.ts.profile" :keywords="['profile']" icon="ti ti-user">
<div class="_gaps_m">
<div class="_panel">
<div :class="$style.banner" :style="{ backgroundImage: $i.bannerUrl ? `url(${ $i.bannerUrl })` : null }">
<div :class="$style.banner" :style="{ backgroundImage: $i.bannerUrl ? `url(${ $i.bannerUrl })` : '' }">
<div :class="$style.bannerEdit">
<SearchMarker :keywords="['banner', 'change', 'remove']">
<MkButton primary rounded @click="changeOrRemoveBanner">{{ <SearchLabel>{{ i18n.ts._profile.changeBanner }}</SearchLabel> }}</MkButton>
<MkButton primary rounded @click="changeOrRemoveBanner"><SearchLabel>{{ i18n.ts._profile.changeBanner }}</SearchLabel></MkButton>
</SearchMarker>
</div>
<div :class="$style.backgroundEdit">
<SearchMarker :keywords="['background', 'change', 'remove']">
<MkButton primary rounded @click="changeOrRemoveBackground">{{ <SearchLabel>{{ i18n.ts._profile.changeBackground }}</SearchLabel> }}</MkButton>
<MkButton primary rounded @click="changeOrRemoveBackground"><SearchLabel>{{ i18n.ts._profile.changeBackground }}</SearchLabel></MkButton>
</SearchMarker>
</div>
</div>
@ -187,6 +187,7 @@ import { claimAchievement } from '@/utility/achievements.js';
import { store } from '@/store.js';
import MkInfo from '@/components/MkInfo.vue';
import MkTextarea from '@/components/MkTextarea.vue';
import { globalEvents } from '@/events.js';
const $i = ensureSignin();
@ -314,7 +315,6 @@ function changeAvatar(ev) {
$i.avatarId = i.avatarId;
$i.avatarUrl = i.avatarUrl;
claimAchievement('profileFilled');
globalEvents.emit('requestClearPageCache');
});
}
@ -365,7 +365,6 @@ function changeBackground(ev) {
});
$i.backgroundId = i.backgroundId;
$i.backgroundUrl = i.backgroundUrl;
globalEvents.emit('requestClearPageCache');
});
}
@ -382,7 +381,6 @@ function changeOrRemoveAvatar(ev) {
});
$i.avatarId = i.avatarId;
$i.avatarUrl = i.avatarUrl;
globalEvents.emit('requestClearPageCache');
},
}], ev.currentTarget ?? ev.target);
} else {
@ -404,7 +402,6 @@ function changeOrRemoveBanner(ev) {
});
$i.bannerId = i.bannerId;
$i.bannerUrl = i.bannerUrl;
globalEvents.emit('requestClearPageCache');
},
}], ev.currentTarget ?? ev.target);
} else {
@ -426,7 +423,6 @@ function changeOrRemoveBackground(ev) {
});
$i.backgroundId = i.backgroundId;
$i.backgroundUrl = i.backgroundUrl;
globalEvents.emit('requestClearPageCache');
},
}], ev.currentTarget ?? ev.target);
} else {

View file

@ -33,10 +33,10 @@ import { misskeyApi } from '@/utility/misskey-api.js';
import { definePage } from '@/page.js';
import { i18n } from '@/i18n.js';
import { useRouter } from '@/router.js';
import { defaultStore } from '@/store.js';
import { store } from '@/store.js';
import { deepMerge } from '@/utility/merge.js';
import * as os from '@/os.js';
import { $i } from '@/account.js';
import { $i } from '@/i.js';
const router = useRouter();
@ -50,19 +50,18 @@ const tlEl = useTemplateRef('tlEl');
const rootEl = useTemplateRef('rootEl');
const withRenotes = computed<boolean>({
get: () => defaultStore.reactiveState.tl.value.filter.withRenotes,
get: () => store.r.tl.value.filter.withRenotes,
set: (x) => saveTlFilter('withRenotes', x),
});
const onlyFiles = computed<boolean>({
get: () => defaultStore.reactiveState.tl.value.filter.onlyFiles,
get: () => store.r.tl.value.filter.onlyFiles,
set: (x) => saveTlFilter('onlyFiles', x),
});
function saveTlFilter(key: keyof typeof defaultStore.state.tl.filter, newValue: boolean) {
function saveTlFilter(key: keyof typeof store.s.tl.filter, newValue: boolean) {
if (key !== 'withReplies' || $i) {
const out = deepMerge({ filter: { [key]: newValue } }, defaultStore.state.tl);
defaultStore.set('tl', out);
store.r.tl.value = deepMerge({ filter: { [key]: newValue } }, store.s.tl);
}
}

View file

@ -175,7 +175,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<div>{{ i18n.ts.noNotes }}</div>
</div>
<div v-else class="_panel">
<MkNote v-for="note of user.pinnedNotes" :key="note.id" class="note" :class="$style.pinnedNote" :note="note" :pinned="true"/>
<DynamicNote v-for="note of user.pinnedNotes" :key="note.id" class="note" :class="$style.pinnedNote" :note="note" :pinned="true"/>
</div>
</div>
<MkNotes v-else :class="$style.tl" :noGap="true" :pagination="AllPagination"/>
@ -221,12 +221,7 @@ import { getStaticImageUrl } from '@/utility/media-proxy.js';
import { infoImageUrl } from '@/instance.js';
import MkSparkle from '@/components/MkSparkle.vue';
import { prefer } from '@/preferences.js';
const MkNote = defineAsyncComponent(() =>
defaultStore.state.noteDesign === 'sharkey'
? import('@/components/SkNote.vue')
: import('@/components/MkNote.vue'),
);
import DynamicNote from '@/components/DynamicNote.vue';
function calcAge(birthdate: string): number {
const date = new Date(birthdate);
@ -277,7 +272,7 @@ const listenbrainzdata = ref(false);
if (props.user.listenbrainz) {
(async function() {
try {
const response = await fetch(`https://api.listenbrainz.org/1/user/${props.user.listenbrainz}/playing-now`, {
const response = await window.fetch(`https://api.listenbrainz.org/1/user/${props.user.listenbrainz}/playing-now`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
@ -295,7 +290,7 @@ if (props.user.listenbrainz) {
const background = computed(() => {
if (props.user.backgroundUrl == null) return {};
if (defaultStore.state.disableShowingAnimatedImages) {
if (prefer.s.disableShowingAnimatedImages) {
return {
'--backgroundImageStatic': `url('${getStaticImageUrl(props.user.backgroundUrl)}')`,
};

View file

@ -20,7 +20,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<div>{{ i18n.ts.noNotes }}</div>
</div>
<div v-else class="_panel">
<MkNote v-for="note of user.pinnedNotes" :key="note.id" class="note" :class="$style.pinnedNote" :note="note" :pinned="true"/>
<DynamicNote v-for="note of user.pinnedNotes" :key="note.id" class="note" :class="$style.pinnedNote" :note="note" :pinned="true"/>
</div>
</div>
<MkNotes v-else :noGap="true" :pagination="pagination" :class="$style.tl"/>
@ -28,19 +28,13 @@ SPDX-License-Identifier: AGPL-3.0-only
</template>
<script lang="ts" setup>
import { ref, computed, defineAsyncComponent } from 'vue';
import { ref, computed } from 'vue';
import * as Misskey from 'misskey-js';
import MkNotes from '@/components/MkNotes.vue';
import MkTab from '@/components/MkTab.vue';
import { i18n } from '@/i18n.js';
import { infoImageUrl } from '@/instance.js';
import { defaultStore } from '@/store.js';
const MkNote = defineAsyncComponent(() =>
defaultStore.state.noteDesign === 'sharkey'
? import('@/components/SkNote.vue')
: import('@/components/MkNote.vue'),
);
import DynamicNote from '@/components/DynamicNote.vue';
const props = defineProps<{
user: Misskey.entities.UserDetailed;