Merge branch 'develop' into pag-back

This commit is contained in:
tamaina 2023-07-26 12:41:54 +00:00
commit 848b72ae21

View file

@ -32,7 +32,7 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { computed, onMounted, onUnmounted } from 'vue'; import { computed, onMounted, onUnmounted, ref } from 'vue';
import { v4 as uuid } from 'uuid'; import { v4 as uuid } from 'uuid';
import FormSection from '@/components/form/section.vue'; import FormSection from '@/components/form/section.vue';
import MkButton from '@/components/MkButton.vue'; import MkButton from '@/components/MkButton.vue';
@ -94,15 +94,6 @@ const coldDeviceStorageSaveKeys: (keyof typeof ColdDeviceStorage.default)[] = [
'darkTheme', 'darkTheme',
'syncDeviceDarkMode', 'syncDeviceDarkMode',
'plugins', 'plugins',
'mediaVolume',
'sound_masterVolume',
'sound_note',
'sound_noteMy',
'sound_notification',
'sound_chat',
'sound_chatBg',
'sound_antenna',
'sound_channel',
]; ];
const scope = ['clientPreferencesProfiles']; const scope = ['clientPreferencesProfiles'];
@ -126,18 +117,18 @@ type Profile = {
const connection = $i && useStream().useChannel('main'); const connection = $i && useStream().useChannel('main');
let profiles = $ref<Record<string, Profile> | null>(null); const profiles = ref<Record<string, Profile> | null>(null);
os.api('i/registry/get-all', { scope }) os.api('i/registry/get-all', { scope })
.then(res => { .then(res => {
profiles = res || {}; profiles.value = res || {};
}); });
function isObject(value: unknown): value is Record<string, unknown> { function isObject(value: unknown): value is Record<string, unknown> {
return value != null && typeof value === 'object' && !Array.isArray(value); return value != null && typeof value === 'object' && !Array.isArray(value);
} }
function validate(profile: unknown): void { function validate(profile: any): void {
if (!isObject(profile)) throw new Error('not an object'); if (!isObject(profile)) throw new Error('not an object');
// Check if unnecessary properties exist // Check if unnecessary properties exist
@ -148,9 +139,9 @@ function validate(profile: unknown): void {
// Check if createdAt and updatedAt is Date // Check if createdAt and updatedAt is Date
// https://zenn.dev/lollipop_onl/articles/eoz-judge-js-invalid-date // https://zenn.dev/lollipop_onl/articles/eoz-judge-js-invalid-date
if (!profile.createdAt || Number.isNaN(new Date(profile.createdAt).getTime())) throw new Error('createdAt is falsy or not Date'); if (!profile.createdAt || Number.isNaN(new Date(profile.createdAt as any).getTime())) throw new Error('createdAt is falsy or not Date');
if (profile.updatedAt) { if (profile.updatedAt) {
if (Number.isNaN(new Date(profile.updatedAt).getTime())) { if (Number.isNaN(new Date(profile.updatedAt as any).getTime())) {
throw new Error('updatedAt is not Date'); throw new Error('updatedAt is not Date');
} }
} else if (profile.updatedAt !== null) { } else if (profile.updatedAt !== null) {
@ -182,14 +173,14 @@ function getSettings(): Profile['settings'] {
} }
async function saveNew(): Promise<void> { async function saveNew(): Promise<void> {
if (!profiles) return; if (!profiles.value) return;
const { canceled, result: name } = await os.inputText({ const { canceled, result: name } = await os.inputText({
title: ts._preferencesBackups.inputName, title: ts._preferencesBackups.inputName,
}); });
if (canceled) return; if (canceled) return;
if (Object.values(profiles).some(x => x.name === name)) { if (Object.values(profiles.value).some(x => x.name === name)) {
return os.alert({ return os.alert({
title: ts._preferencesBackups.cannotSave, title: ts._preferencesBackups.cannotSave,
text: t('_preferencesBackups.nameAlreadyExists', { name }), text: t('_preferencesBackups.nameAlreadyExists', { name }),
@ -213,7 +204,7 @@ function loadFile(): void {
input.type = 'file'; input.type = 'file';
input.multiple = false; input.multiple = false;
input.onchange = async () => { input.onchange = async () => {
if (!profiles) return; if (!profiles.value) return;
if (!input.files || input.files.length === 0) return; if (!input.files || input.files.length === 0) return;
const file = input.files[0]; const file = input.files[0];
@ -234,7 +225,7 @@ function loadFile(): void {
return os.alert({ return os.alert({
type: 'error', type: 'error',
title: ts._preferencesBackups.cannotLoad, title: ts._preferencesBackups.cannotLoad,
text: err?.message, text: (err as any)?.message ?? '',
}); });
} }
@ -253,9 +244,9 @@ function loadFile(): void {
} }
async function applyProfile(id: string): Promise<void> { async function applyProfile(id: string): Promise<void> {
if (!profiles) return; if (!profiles.value) return;
const profile = profiles[id]; const profile = profiles.value[id];
const { canceled: cancel1 } = await os.confirm({ const { canceled: cancel1 } = await os.confirm({
type: 'warning', type: 'warning',
@ -313,23 +304,23 @@ async function applyProfile(id: string): Promise<void> {
} }
async function deleteProfile(id: string): Promise<void> { async function deleteProfile(id: string): Promise<void> {
if (!profiles) return; if (!profiles.value) return;
const { canceled } = await os.confirm({ const { canceled } = await os.confirm({
type: 'info', type: 'info',
title: ts.delete, title: ts.delete,
text: t('deleteAreYouSure', { x: profiles[id].name }), text: t('deleteAreYouSure', { x: profiles.value[id].name }),
}); });
if (canceled) return; if (canceled) return;
await os.apiWithDialog('i/registry/remove', { scope, key: id }); await os.apiWithDialog('i/registry/remove', { scope, key: id });
delete profiles[id]; delete profiles.value[id];
} }
async function save(id: string): Promise<void> { async function save(id: string): Promise<void> {
if (!profiles) return; if (!profiles.value) return;
const { name, createdAt } = profiles[id]; const { name, createdAt } = profiles.value[id];
const { canceled } = await os.confirm({ const { canceled } = await os.confirm({
type: 'info', type: 'info',
@ -350,25 +341,25 @@ async function save(id: string): Promise<void> {
} }
async function rename(id: string): Promise<void> { async function rename(id: string): Promise<void> {
if (!profiles) return; if (!profiles.value) return;
const { canceled: cancel1, result: name } = await os.inputText({ const { canceled: cancel1, result: name } = await os.inputText({
title: ts._preferencesBackups.inputName, title: ts._preferencesBackups.inputName,
}); });
if (cancel1 || profiles[id].name === name) return; if (cancel1 || profiles.value[id].name === name) return;
if (Object.values(profiles).some(x => x.name === name)) { if (Object.values(profiles.value).some(x => x.name === name)) {
return os.alert({ return os.alert({
title: ts._preferencesBackups.cannotSave, title: ts._preferencesBackups.cannotSave,
text: t('_preferencesBackups.nameAlreadyExists', { name }), text: t('_preferencesBackups.nameAlreadyExists', { name }),
}); });
} }
const registry = Object.assign({}, { ...profiles[id] }); const registry = Object.assign({}, { ...profiles.value[id] });
const { canceled: cancel2 } = await os.confirm({ const { canceled: cancel2 } = await os.confirm({
type: 'info', type: 'info',
title: ts._preferencesBackups.rename, title: ts.rename,
text: t('_preferencesBackups.renameConfirm', { old: registry.name, new: name }), text: t('_preferencesBackups.renameConfirm', { old: registry.name, new: name }),
}); });
if (cancel2) return; if (cancel2) return;
@ -378,7 +369,7 @@ async function rename(id: string): Promise<void> {
} }
function menu(ev: MouseEvent, profileId: string) { function menu(ev: MouseEvent, profileId: string) {
if (!profiles) return; if (!profiles.value) return;
return os.popupMenu([{ return os.popupMenu([{
text: ts._preferencesBackups.apply, text: ts._preferencesBackups.apply,
@ -388,8 +379,8 @@ function menu(ev: MouseEvent, profileId: string) {
type: 'a', type: 'a',
text: ts.download, text: ts.download,
icon: 'ti ti-download', icon: 'ti ti-download',
href: URL.createObjectURL(new Blob([JSON.stringify(profiles[profileId], null, 2)], { type: 'application/json' })), href: URL.createObjectURL(new Blob([JSON.stringify(profiles.value[profileId], null, 2)], { type: 'application/json' })),
download: `${profiles[profileId].name}.json`, download: `${profiles.value[profileId].name}.json`,
}, null, { }, null, {
text: ts.rename, text: ts.rename,
icon: 'ti ti-forms', icon: 'ti ti-forms',
@ -403,16 +394,16 @@ function menu(ev: MouseEvent, profileId: string) {
icon: 'ti ti-trash', icon: 'ti ti-trash',
action: () => deleteProfile(profileId), action: () => deleteProfile(profileId),
danger: true, danger: true,
}], ev.currentTarget ?? ev.target); }], (ev.currentTarget ?? ev.target ?? undefined) as unknown as HTMLElement | undefined);
} }
onMounted(() => { onMounted(() => {
// streaminguser storage update // streaminguser storage update
connection?.on('registryUpdated', ({ scope: recievedScope, key, value }) => { connection?.on('registryUpdated', ({ scope: recievedScope, key, value }) => {
if (!recievedScope || recievedScope.length !== scope.length || recievedScope[0] !== scope[0]) return; if (!recievedScope || recievedScope.length !== scope.length || recievedScope[0] !== scope[0]) return;
if (!profiles) return; if (!profiles.value) return;
profiles[key] = value; profiles.value[key] = value;
}); });
}); });