227 lines
5.9 KiB
TypeScript
227 lines
5.9 KiB
TypeScript
/*
|
|
* SPDX-FileCopyrightText: syuilo and misskey-project
|
|
* SPDX-License-Identifier: AGPL-3.0-only
|
|
*/
|
|
|
|
import { ref, watch } from 'vue';
|
|
import type { PreferencesProfile } from './profile.js';
|
|
import type { MenuItem } from '@/types/menu.js';
|
|
import { copyToClipboard } from '@/scripts/copy-to-clipboard.js';
|
|
import { i18n } from '@/i18n.js';
|
|
import { miLocalStorage } from '@/local-storage.js';
|
|
import { prefer, profileManager } from '@/preferences.js';
|
|
import * as os from '@/os.js';
|
|
import { store } from '@/store.js';
|
|
import { $i } from '@/account.js';
|
|
import { misskeyApi } from '@/scripts/misskey-api.js';
|
|
import { unisonReload } from '@/scripts/unison-reload.js';
|
|
|
|
function canAutoBackup() {
|
|
return profileManager.profile.name != null && profileManager.profile.name.trim() !== '';
|
|
}
|
|
|
|
export function getPreferencesProfileMenu(): MenuItem[] {
|
|
const autoBackupEnabled = ref(store.state.enablePreferencesAutoCloudBackup);
|
|
|
|
watch(autoBackupEnabled, () => {
|
|
if (autoBackupEnabled.value) {
|
|
if (!canAutoBackup()) {
|
|
autoBackupEnabled.value = false;
|
|
os.alert({
|
|
type: 'warning',
|
|
title: i18n.ts._preferencesBackup.youNeedToNameYourProfileToEnableAutoBackup,
|
|
});
|
|
return;
|
|
}
|
|
|
|
store.set('enablePreferencesAutoCloudBackup', true);
|
|
} else {
|
|
store.set('enablePreferencesAutoCloudBackup', false);
|
|
}
|
|
});
|
|
|
|
const menu: MenuItem[] = [{
|
|
type: 'label',
|
|
text: profileManager.profile.name || `(${i18n.ts.noName})`,
|
|
}, {
|
|
text: i18n.ts.rename,
|
|
icon: 'ti ti-pencil',
|
|
action: () => {
|
|
renameProfile();
|
|
},
|
|
}, {
|
|
type: 'switch',
|
|
icon: 'ti ti-cloud-up',
|
|
text: i18n.ts._preferencesBackup.autoBackup,
|
|
ref: autoBackupEnabled,
|
|
}, {
|
|
text: i18n.ts.export,
|
|
icon: 'ti ti-download',
|
|
action: () => {
|
|
exportCurrentProfile();
|
|
},
|
|
}, {
|
|
type: 'divider',
|
|
}, {
|
|
text: i18n.ts._preferencesBackup.restoreFromBackup,
|
|
icon: 'ti ti-cloud-down',
|
|
action: () => {
|
|
restoreFromCloudBackup();
|
|
},
|
|
}, {
|
|
text: i18n.ts.import,
|
|
icon: 'ti ti-upload',
|
|
action: () => {
|
|
importProfile();
|
|
},
|
|
}];
|
|
|
|
if (prefer.s.devMode) {
|
|
menu.push({
|
|
type: 'divider',
|
|
}, {
|
|
text: 'Copy profile as text',
|
|
icon: 'ti ti-clipboard',
|
|
action: () => {
|
|
copyToClipboard(JSON.stringify(profileManager.profile, null, '\t'));
|
|
},
|
|
});
|
|
}
|
|
|
|
return menu;
|
|
}
|
|
|
|
async function renameProfile() {
|
|
const { canceled, result: name } = await os.inputText({
|
|
title: i18n.ts._preferencesProfile.profileName,
|
|
text: i18n.ts._preferencesProfile.profileNameDescription + '\n' + i18n.ts._preferencesProfile.profileNameDescription2,
|
|
placeholder: profileManager.profile.name || null,
|
|
default: profileManager.profile.name || null,
|
|
});
|
|
if (canceled || name == null || name.trim() === '') return;
|
|
|
|
profileManager.renameProfile(name);
|
|
}
|
|
|
|
function exportCurrentProfile() {
|
|
const p = profileManager.profile;
|
|
const txtBlob = new Blob([JSON.stringify(p)], { type: 'text/plain' });
|
|
const dummya = document.createElement('a');
|
|
dummya.href = URL.createObjectURL(txtBlob);
|
|
dummya.download = `${p.name || p.id}.misskeypreferences`;
|
|
dummya.click();
|
|
}
|
|
|
|
function importProfile() {
|
|
const input = document.createElement('input');
|
|
input.type = 'file';
|
|
input.accept = '.misskeypreferences';
|
|
input.onchange = async () => {
|
|
if (input.files == null || input.files.length === 0) return;
|
|
|
|
const file = input.files[0];
|
|
const txt = await file.text();
|
|
const profile = JSON.parse(txt) as PreferencesProfile;
|
|
|
|
miLocalStorage.setItem('preferences', JSON.stringify(profile));
|
|
miLocalStorage.setItem('hidePreferencesRestoreSuggestion', 'true');
|
|
shouldSuggestRestoreBackup.value = false;
|
|
unisonReload();
|
|
};
|
|
|
|
input.click();
|
|
}
|
|
|
|
export async function cloudBackup() {
|
|
if ($i == null) return;
|
|
if (!canAutoBackup()) {
|
|
throw new Error('Profile name is not set');
|
|
}
|
|
|
|
await misskeyApi('i/registry/set', {
|
|
scope: ['client', 'preferences', 'backups'],
|
|
key: profileManager.profile.name,
|
|
value: profileManager.profile,
|
|
});
|
|
}
|
|
|
|
export async function restoreFromCloudBackup() {
|
|
if ($i == null) return;
|
|
|
|
// TODO: 更新日時でソートして取得したい
|
|
const keys = await misskeyApi('i/registry/keys', {
|
|
scope: ['client', 'preferences', 'backups'],
|
|
});
|
|
|
|
console.log(keys);
|
|
|
|
if (keys.length === 0) {
|
|
os.alert({
|
|
type: 'warning',
|
|
title: i18n.ts._preferencesBackup.noBackupsFoundTitle,
|
|
text: i18n.ts._preferencesBackup.noBackupsFoundDescription,
|
|
});
|
|
return;
|
|
}
|
|
|
|
const select = await os.select({
|
|
title: i18n.ts._preferencesBackup.selectBackupToRestore,
|
|
items: keys.map(k => ({
|
|
text: k,
|
|
value: k,
|
|
})),
|
|
});
|
|
if (select.canceled) return;
|
|
if (select.result == null) return;
|
|
|
|
const profile = await misskeyApi('i/registry/get', {
|
|
scope: ['client', 'preferences', 'backups'],
|
|
key: select.result,
|
|
});
|
|
|
|
console.log(profile);
|
|
|
|
miLocalStorage.setItem('preferences', JSON.stringify(profile));
|
|
miLocalStorage.setItem('hidePreferencesRestoreSuggestion', 'true');
|
|
store.set('enablePreferencesAutoCloudBackup', true);
|
|
shouldSuggestRestoreBackup.value = false;
|
|
unisonReload();
|
|
}
|
|
|
|
export async function enableAutoBackup() {
|
|
if (!canAutoBackup()) {
|
|
await renameProfile();
|
|
}
|
|
|
|
if (!canAutoBackup()) {
|
|
return;
|
|
}
|
|
|
|
store.set('enablePreferencesAutoCloudBackup', true);
|
|
}
|
|
|
|
export const shouldSuggestRestoreBackup = ref(false);
|
|
|
|
if ($i != null) {
|
|
if (new Date($i.createdAt).getTime() < (Date.now() - 1000 * 60 * 30)) { // アカウント作成直後は意味ないので除外
|
|
miLocalStorage.setItem('hidePreferencesRestoreSuggestion', 'true');
|
|
} else {
|
|
if (miLocalStorage.getItem('hidePreferencesRestoreSuggestion') !== 'true') {
|
|
misskeyApi('i/registry/keys', {
|
|
scope: ['client', 'preferences', 'backups'],
|
|
}).then(keys => {
|
|
if (keys.length === 0) {
|
|
miLocalStorage.setItem('hidePreferencesRestoreSuggestion', 'true');
|
|
} else {
|
|
shouldSuggestRestoreBackup.value = true;
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
export function hideRestoreBackupSuggestion() {
|
|
miLocalStorage.setItem('hidePreferencesRestoreSuggestion', 'true');
|
|
shouldSuggestRestoreBackup.value = false;
|
|
}
|