enhance(frontend): improve preferences

This commit is contained in:
syuilo 2025-03-13 19:44:23 +09:00
parent 0126dba475
commit 44073736de
9 changed files with 164 additions and 165 deletions

View File

@ -191,6 +191,7 @@ export async function mainBoot() {
prefer.commit('skipNoteRender', store.s.skipNoteRender); prefer.commit('skipNoteRender', store.s.skipNoteRender);
prefer.commit('showSoftWordMutedWord', store.s.showSoftWordMutedWord); prefer.commit('showSoftWordMutedWord', store.s.showSoftWordMutedWord);
prefer.commit('confirmOnReact', store.s.confirmOnReact); prefer.commit('confirmOnReact', store.s.confirmOnReact);
prefer.commit('defaultFollowWithReplies', store.s.defaultWithReplies);
prefer.commit('sound.masterVolume', store.s.sound_masterVolume); prefer.commit('sound.masterVolume', store.s.sound_masterVolume);
prefer.commit('sound.notUseSound', store.s.sound_notUseSound); prefer.commit('sound.notUseSound', store.s.sound_notUseSound);
prefer.commit('sound.useSoundOnlyWhenActive', store.s.sound_useSoundOnlyWhenActive); prefer.commit('sound.useSoundOnlyWhenActive', store.s.sound_useSoundOnlyWhenActive);

View File

@ -45,7 +45,6 @@ import { i18n } from '@/i18n.js';
import { claimAchievement } from '@/utility/achievements.js'; import { claimAchievement } from '@/utility/achievements.js';
import { pleaseLogin } from '@/utility/please-login.js'; import { pleaseLogin } from '@/utility/please-login.js';
import { $i } from '@/account.js'; import { $i } from '@/account.js';
import { store } from '@/store.js';
import { prefer } from '@/preferences.js'; import { prefer } from '@/preferences.js';
const props = withDefaults(defineProps<{ const props = withDefaults(defineProps<{
@ -121,11 +120,11 @@ async function onClick() {
} else { } else {
await misskeyApi('following/create', { await misskeyApi('following/create', {
userId: props.user.id, userId: props.user.id,
withReplies: store.s.defaultWithReplies, withReplies: prefer.s.defaultFollowWithReplies,
}); });
emit('update:user', { emit('update:user', {
...props.user, ...props.user,
withReplies: store.s.defaultWithReplies, withReplies: prefer.s.defaultFollowWithReplies,
}); });
hasPendingFollowRequestFromYou.value = true; hasPendingFollowRequestFromYou.value = true;

View File

@ -168,12 +168,12 @@ import { selectFile } from '@/utility/select-file.js';
import { i18n } from '@/i18n.js'; import { i18n } from '@/i18n.js';
import { definePage } from '@/page.js'; import { definePage } from '@/page.js';
import { $i } from '@/account.js'; import { $i } from '@/account.js';
import { store } from '@/store.js';
import MkFeatureBanner from '@/components/MkFeatureBanner.vue'; import MkFeatureBanner from '@/components/MkFeatureBanner.vue';
import { prefer } from '@/preferences.js';
const excludeMutingUsers = ref(false); const excludeMutingUsers = ref(false);
const excludeInactiveUsers = ref(false); const excludeInactiveUsers = ref(false);
const withReplies = ref(store.s.defaultWithReplies); const withReplies = ref(prefer.s.defaultFollowWithReplies);
const onExportSuccess = () => { const onExportSuccess = () => {
os.alert({ os.alert({

View File

@ -16,112 +16,102 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkSwitch v-model="reportError">{{ i18n.ts.sendErrorReports }}<template #caption>{{ i18n.ts.sendErrorReportsDescription }}</template></MkSwitch> <MkSwitch v-model="reportError">{{ i18n.ts.sendErrorReports }}<template #caption>{{ i18n.ts.sendErrorReportsDescription }}</template></MkSwitch>
--> -->
<FormSection first> <div class="_gaps_s">
<div class="_gaps_s"> <SearchMarker :keywords="['account', 'info']">
<SearchMarker :keywords="['account', 'info']"> <MkFolder>
<MkFolder> <template #icon><i class="ti ti-info-circle"></i></template>
<template #icon><i class="ti ti-info-circle"></i></template> <template #label><SearchLabel>{{ i18n.ts.accountInfo }}</SearchLabel></template>
<template #label><SearchLabel>{{ i18n.ts.accountInfo }}</SearchLabel></template>
<div class="_gaps_m"> <div class="_gaps_m">
<MkKeyValue> <MkKeyValue>
<template #key>ID</template> <template #key>ID</template>
<template #value><span class="_monospace">{{ $i.id }}</span></template> <template #value><span class="_monospace">{{ $i.id }}</span></template>
</MkKeyValue> </MkKeyValue>
<MkKeyValue> <MkKeyValue>
<template #key>{{ i18n.ts.registeredDate }}</template> <template #key>{{ i18n.ts.registeredDate }}</template>
<template #value><MkTime :time="$i.createdAt" mode="detail"/></template> <template #value><MkTime :time="$i.createdAt" mode="detail"/></template>
</MkKeyValue> </MkKeyValue>
<MkFolder> <MkFolder>
<template #icon><i class="ti ti-badges"></i></template> <template #icon><i class="ti ti-badges"></i></template>
<template #label><SearchLabel>{{ i18n.ts._role.policies }}</SearchLabel></template> <template #label><SearchLabel>{{ i18n.ts._role.policies }}</SearchLabel></template>
<div class="_gaps_s"> <div class="_gaps_s">
<div v-for="policy in Object.keys($i.policies)" :key="policy"> <div v-for="policy in Object.keys($i.policies)" :key="policy">
{{ policy }} ... {{ $i.policies[policy] }} {{ policy }} ... {{ $i.policies[policy] }}
</div>
</div> </div>
</MkFolder> </div>
</div> </MkFolder>
</MkFolder> </div>
</SearchMarker> </MkFolder>
</SearchMarker>
<SearchMarker :keywords="['roles']"> <SearchMarker :keywords="['roles']">
<MkFolder> <MkFolder>
<template #icon><i class="ti ti-badges"></i></template> <template #icon><i class="ti ti-badges"></i></template>
<template #label><SearchLabel>{{ i18n.ts.rolesAssignedToMe }}</SearchLabel></template> <template #label><SearchLabel>{{ i18n.ts.rolesAssignedToMe }}</SearchLabel></template>
<MkRolePreview v-for="role in $i.roles" :key="role.id" :role="role" :forModeration="false"/> <MkRolePreview v-for="role in $i.roles" :key="role.id" :role="role" :forModeration="false"/>
</MkFolder> </MkFolder>
</SearchMarker> </SearchMarker>
<SearchMarker :keywords="['account', 'move', 'migration']"> <SearchMarker :keywords="['account', 'move', 'migration']">
<MkFolder> <MkFolder>
<template #icon><i class="ti ti-plane"></i></template> <template #icon><i class="ti ti-plane"></i></template>
<template #label><SearchLabel>{{ i18n.ts.accountMigration }}</SearchLabel></template> <template #label><SearchLabel>{{ i18n.ts.accountMigration }}</SearchLabel></template>
<XMigration/> <XMigration/>
</MkFolder> </MkFolder>
</SearchMarker> </SearchMarker>
<SearchMarker :keywords="['account', 'close', 'delete']"> <SearchMarker :keywords="['account', 'close', 'delete']">
<MkFolder> <MkFolder>
<template #icon><i class="ti ti-alert-triangle"></i></template> <template #icon><i class="ti ti-alert-triangle"></i></template>
<template #label><SearchLabel>{{ i18n.ts.closeAccount }}</SearchLabel></template> <template #label><SearchLabel>{{ i18n.ts.closeAccount }}</SearchLabel></template>
<div class="_gaps_m"> <div class="_gaps_m">
<FormInfo warn>{{ i18n.ts._accountDelete.mayTakeTime }}</FormInfo> <FormInfo warn>{{ i18n.ts._accountDelete.mayTakeTime }}</FormInfo>
<FormInfo>{{ i18n.ts._accountDelete.sendEmail }}</FormInfo> <FormInfo>{{ i18n.ts._accountDelete.sendEmail }}</FormInfo>
<MkButton v-if="!$i.isDeleted" danger @click="deleteAccount"><SearchKeyword>{{ i18n.ts._accountDelete.requestAccountDelete }}</SearchKeyword></MkButton> <MkButton v-if="!$i.isDeleted" danger @click="deleteAccount"><SearchKeyword>{{ i18n.ts._accountDelete.requestAccountDelete }}</SearchKeyword></MkButton>
<MkButton v-else disabled>{{ i18n.ts._accountDelete.inProgress }}</MkButton> <MkButton v-else disabled>{{ i18n.ts._accountDelete.inProgress }}</MkButton>
</div> </div>
</MkFolder> </MkFolder>
</SearchMarker> </SearchMarker>
<SearchMarker :keywords="['experimental', 'feature', 'flags']"> <SearchMarker :keywords="['experimental', 'feature', 'flags']">
<MkFolder> <MkFolder>
<template #icon><i class="ti ti-flask"></i></template> <template #icon><i class="ti ti-flask"></i></template>
<template #label><SearchLabel>{{ i18n.ts.experimentalFeatures }}</SearchLabel></template> <template #label><SearchLabel>{{ i18n.ts.experimentalFeatures }}</SearchLabel></template>
<div class="_gaps_m"> <div class="_gaps_m">
<MkSwitch v-model="enableCondensedLine"> <MkSwitch v-model="enableCondensedLine">
<template #label>Enable condensed line</template> <template #label>Enable condensed line</template>
</MkSwitch> </MkSwitch>
<MkSwitch v-model="skipNoteRender"> <MkSwitch v-model="skipNoteRender">
<template #label>Enable note render skipping</template> <template #label>Enable note render skipping</template>
</MkSwitch> </MkSwitch>
</div> </div>
</MkFolder> </MkFolder>
</SearchMarker> </SearchMarker>
<SearchMarker :keywords="['developer', 'mode', 'debug']"> <SearchMarker :keywords="['developer', 'mode', 'debug']">
<MkFolder> <MkFolder>
<template #icon><i class="ti ti-code"></i></template> <template #icon><i class="ti ti-code"></i></template>
<template #label><SearchLabel>{{ i18n.ts.developer }}</SearchLabel></template> <template #label><SearchLabel>{{ i18n.ts.developer }}</SearchLabel></template>
<div class="_gaps_m"> <div class="_gaps_m">
<MkSwitch v-model="devMode"> <MkSwitch v-model="devMode">
<template #label>{{ i18n.ts.devMode }}</template> <template #label>{{ i18n.ts.devMode }}</template>
</MkSwitch> </MkSwitch>
</div> </div>
</MkFolder> </MkFolder>
</SearchMarker> </SearchMarker>
</div> </div>
</FormSection>
<FormSection> <hr>
<FormLink to="/registry"><template #icon><i class="ti ti-adjustments"></i></template>{{ i18n.ts.registry }}</FormLink>
</FormSection>
<FormSection> <FormLink to="/registry"><template #icon><i class="ti ti-adjustments"></i></template>{{ i18n.ts.registry }}</FormLink>
<div class="_gaps_s">
<MkSwitch v-model="defaultWithReplies">{{ i18n.ts.withRepliesByDefaultForNewlyFollowed }}</MkSwitch>
<MkButton danger @click="updateRepliesAll(true)"><i class="ti ti-messages"></i> {{ i18n.ts.showRepliesToOthersInTimelineAll }}</MkButton>
<MkButton danger @click="updateRepliesAll(false)"><i class="ti ti-messages-off"></i> {{ i18n.ts.hideRepliesToOthersInTimelineAll }}</MkButton>
</div>
</FormSection>
</div> </div>
</SearchMarker> </SearchMarker>
</template> </template>
@ -137,7 +127,6 @@ import MkKeyValue from '@/components/MkKeyValue.vue';
import MkButton from '@/components/MkButton.vue'; import MkButton from '@/components/MkButton.vue';
import * as os from '@/os.js'; import * as os from '@/os.js';
import { misskeyApi } from '@/utility/misskey-api.js'; import { misskeyApi } from '@/utility/misskey-api.js';
import { store } from '@/store.js';
import { signout, signinRequired } from '@/account.js'; import { signout, signinRequired } from '@/account.js';
import { i18n } from '@/i18n.js'; import { i18n } from '@/i18n.js';
import { definePage } from '@/page.js'; import { definePage } from '@/page.js';
@ -152,7 +141,6 @@ const reportError = prefer.model('reportError');
const enableCondensedLine = prefer.model('enableCondensedLine'); const enableCondensedLine = prefer.model('enableCondensedLine');
const skipNoteRender = prefer.model('skipNoteRender'); const skipNoteRender = prefer.model('skipNoteRender');
const devMode = prefer.model('devMode'); const devMode = prefer.model('devMode');
const defaultWithReplies = computed(store.makeGetterSetter('defaultWithReplies'));
watch(skipNoteRender, async () => { watch(skipNoteRender, async () => {
await reloadAsk({ reason: i18n.ts.reloadToApplySetting, unison: true }); await reloadAsk({ reason: i18n.ts.reloadToApplySetting, unison: true });
@ -182,16 +170,6 @@ async function deleteAccount() {
await signout(); await signout();
} }
async function updateRepliesAll(withReplies: boolean) {
const { canceled } = await os.confirm({
type: 'warning',
text: withReplies ? i18n.ts.confirmShowRepliesAll : i18n.ts.confirmHideRepliesAll,
});
if (canceled) return;
misskeyApi('following/update-all', { withReplies });
}
const headerActions = computed(() => []); const headerActions = computed(() => []);
const headerTabs = computed(() => []); const headerTabs = computed(() => []);

View File

@ -393,6 +393,39 @@ SPDX-License-Identifier: AGPL-3.0-only
</MkFolder> </MkFolder>
</SearchMarker> </SearchMarker>
<SearchMarker :keywords="['datasaver']">
<MkFolder>
<template #label><SearchLabel>{{ i18n.ts.dataSaver }}</SearchLabel></template>
<div class="_gaps_m">
<MkInfo>{{ i18n.ts.reloadRequiredToApplySettings }}</MkInfo>
<div class="_buttons">
<MkButton inline @click="enableAllDataSaver">{{ i18n.ts.enableAll }}</MkButton>
<MkButton inline @click="disableAllDataSaver">{{ i18n.ts.disableAll }}</MkButton>
</div>
<div class="_gaps_m">
<MkSwitch v-model="dataSaver.media">
{{ i18n.ts._dataSaver._media.title }}
<template #caption>{{ i18n.ts._dataSaver._media.description }}</template>
</MkSwitch>
<MkSwitch v-model="dataSaver.avatar">
{{ i18n.ts._dataSaver._avatar.title }}
<template #caption>{{ i18n.ts._dataSaver._avatar.description }}</template>
</MkSwitch>
<MkSwitch v-model="dataSaver.urlPreview">
{{ i18n.ts._dataSaver._urlPreview.title }}
<template #caption>{{ i18n.ts._dataSaver._urlPreview.description }}</template>
</MkSwitch>
<MkSwitch v-model="dataSaver.code">
{{ i18n.ts._dataSaver._code.title }}
<template #caption>{{ i18n.ts._dataSaver._code.description }}</template>
</MkSwitch>
</div>
</div>
</MkFolder>
</SearchMarker>
<SearchMarker :keywords="['other']"> <SearchMarker :keywords="['other']">
<MkFolder> <MkFolder>
<template #label><SearchLabel>{{ i18n.ts.other }}</SearchLabel></template> <template #label><SearchLabel>{{ i18n.ts.other }}</SearchLabel></template>
@ -422,6 +455,14 @@ SPDX-License-Identifier: AGPL-3.0-only
</MkSwitch> </MkSwitch>
</MkPreferenceContainer> </MkPreferenceContainer>
</SearchMarker> </SearchMarker>
<SearchMarker :keywords="['follow', 'replies']">
<MkPreferenceContainer k="defaultFollowWithReplies">
<MkSwitch v-model="defaultFollowWithReplies">
<template #label><SearchLabel>{{ i18n.ts.withRepliesByDefaultForNewlyFollowed }}</SearchLabel></template>
</MkSwitch>
</MkPreferenceContainer>
</SearchMarker>
</div> </div>
<SearchMarker :keywords="['server', 'disconnect', 'reconnect', 'reload', 'streaming']"> <SearchMarker :keywords="['server', 'disconnect', 'reconnect', 'reload', 'streaming']">
@ -477,43 +518,14 @@ SPDX-License-Identifier: AGPL-3.0-only
</div> </div>
</MkFolder> </MkFolder>
</SearchMarker> </SearchMarker>
</div>
<SearchMarker :keywords="['datasaver']"> <hr>
<MkFolder>
<template #label><SearchLabel>{{ i18n.ts.dataSaver }}</SearchLabel></template>
<div class="_gaps_m"> <div class="_gaps_s">
<MkInfo>{{ i18n.ts.reloadRequiredToApplySettings }}</MkInfo> <FormLink to="/settings/navbar"><template #icon><i class="ti ti-list"></i></template>{{ i18n.ts.navbar }}</FormLink>
<FormLink to="/settings/statusbar"><template #icon><i class="ti ti-list"></i></template>{{ i18n.ts.statusbar }}</FormLink>
<div class="_buttons"> <FormLink to="/settings/deck"><template #icon><i class="ti ti-columns"></i></template>{{ i18n.ts.deck }}</FormLink>
<MkButton inline @click="enableAllDataSaver">{{ i18n.ts.enableAll }}</MkButton>
<MkButton inline @click="disableAllDataSaver">{{ i18n.ts.disableAll }}</MkButton>
</div>
<div class="_gaps_m">
<MkSwitch v-model="dataSaver.media">
{{ i18n.ts._dataSaver._media.title }}
<template #caption>{{ i18n.ts._dataSaver._media.description }}</template>
</MkSwitch>
<MkSwitch v-model="dataSaver.avatar">
{{ i18n.ts._dataSaver._avatar.title }}
<template #caption>{{ i18n.ts._dataSaver._avatar.description }}</template>
</MkSwitch>
<MkSwitch v-model="dataSaver.urlPreview">
{{ i18n.ts._dataSaver._urlPreview.title }}
<template #caption>{{ i18n.ts._dataSaver._urlPreview.description }}</template>
</MkSwitch>
<MkSwitch v-model="dataSaver.code">
{{ i18n.ts._dataSaver._code.title }}
<template #caption>{{ i18n.ts._dataSaver._code.description }}</template>
</MkSwitch>
</div>
</div>
</MkFolder>
</SearchMarker>
<FormLink to="/settings/navbar">{{ i18n.ts.navbar }}</FormLink>
<FormLink to="/settings/statusbar">{{ i18n.ts.statusbar }}</FormLink>
<FormLink to="/settings/deck">{{ i18n.ts.deck }}</FormLink>
<FormLink to="/settings/custom-css"><template #icon><i class="ti ti-code"></i></template>{{ i18n.ts.customCss }}</FormLink> <FormLink to="/settings/custom-css"><template #icon><i class="ti ti-code"></i></template>{{ i18n.ts.customCss }}</FormLink>
</div> </div>
</div> </div>
@ -592,6 +604,7 @@ const nsfw = prefer.model('nsfw');
const emojiStyle = prefer.model('emojiStyle'); const emojiStyle = prefer.model('emojiStyle');
const useBlurEffectForModal = prefer.model('useBlurEffectForModal'); const useBlurEffectForModal = prefer.model('useBlurEffectForModal');
const useBlurEffect = prefer.model('useBlurEffect'); const useBlurEffect = prefer.model('useBlurEffect');
const defaultFollowWithReplies = prefer.model('defaultFollowWithReplies');
watch(lang, () => { watch(lang, () => {
miLocalStorage.setItem('lang', lang.value as string); miLocalStorage.setItem('lang', lang.value as string);

View File

@ -306,6 +306,9 @@ export const PREF_DEF = {
confirmOnReact: { confirmOnReact: {
default: false, default: false,
}, },
defaultFollowWithReplies: {
default: false,
},
plugins: { plugins: {
default: [] as Plugin[], default: [] as Plugin[],
}, },

View File

@ -100,10 +100,6 @@ export const store = markRaw(new Storage('base', {
where: 'device', where: 'device',
default: {} as Record<string, Record<string, string[]>>, default: {} as Record<string, Record<string, string[]>>,
}, },
defaultWithReplies: {
where: 'account',
default: false,
},
pluginTokens: { pluginTokens: {
where: 'deviceAccount', where: 'deviceAccount',
default: {} as Record<string, string>, // plugin id, token default: {} as Record<string, string>, // plugin id, token
@ -119,6 +115,10 @@ export const store = markRaw(new Storage('base', {
}, },
//#region TODO: そのうち消す (preferに移行済み) //#region TODO: そのうち消す (preferに移行済み)
defaultWithReplies: {
where: 'account',
default: false,
},
reactions: { reactions: {
where: 'account', where: 'account',
default: ['👍', '❤️', '😆', '🤔', '😮', '🎉', '💢', '😥', '😇', '🍮'], default: ['👍', '❤️', '😆', '🤔', '😮', '🎉', '💢', '😥', '😇', '🍮'],

View File

@ -128,7 +128,7 @@ optgroup, option {
} }
hr { hr {
margin: var(--MI-margin) 0 var(--MI-margin) 0; margin: 0;
border: none; border: none;
height: 1px; height: 1px;
background: var(--MI_THEME-divider); background: var(--MI_THEME-divider);

View File

@ -482,44 +482,54 @@ export const searchIndexes: SearchIndexItem[] = [
}, },
{ {
id: '2E7vdIUQd', id: '2E7vdIUQd',
label: i18n.ts.dataSaver,
keywords: ['datasaver'],
},
{
id: '6ZbRRIhA6',
children: [ children: [
{ {
id: 'C2iXtZKb3', id: 'soNZaKfiW',
label: i18n.ts.squareAvatars, label: i18n.ts.squareAvatars,
keywords: ['avatar', 'icon', 'square'], keywords: ['avatar', 'icon', 'square'],
}, },
{ {
id: 'DCfJg0bva', id: 'nhwHJJ2tl',
label: i18n.ts.seasonalScreenEffect, label: i18n.ts.seasonalScreenEffect,
keywords: ['effect', 'show'], keywords: ['effect', 'show'],
}, },
{ {
id: 'AV0iGW0vg', id: 'oMAVUuxTm',
label: i18n.ts.openImageInNewTab, label: i18n.ts.openImageInNewTab,
keywords: ['image', 'photo', 'picture', 'media', 'thumbnail', 'new', 'tab'], keywords: ['image', 'photo', 'picture', 'media', 'thumbnail', 'new', 'tab'],
}, },
{ {
id: '5h8vhCX1S', id: 'hSqX5JKM7',
label: i18n.ts.withRepliesByDefaultForNewlyFollowed,
keywords: ['follow', 'replies'],
},
{
id: 'fm98eqzke',
label: i18n.ts.whenServerDisconnected, label: i18n.ts.whenServerDisconnected,
keywords: ['server', 'disconnect', 'reconnect', 'reload', 'streaming'], keywords: ['server', 'disconnect', 'reconnect', 'reload', 'streaming'],
}, },
{ {
id: 'zZxyXHk3A', id: '1rWDVig8Y',
label: i18n.ts.numberOfPageCache, label: i18n.ts.numberOfPageCache,
keywords: ['cache', 'page'], keywords: ['cache', 'page'],
}, },
{ {
id: '7ix3kvMyU', id: 'vXLtihtCp',
label: i18n.ts.forceShowAds, label: i18n.ts.forceShowAds,
keywords: ['ad', 'show'], keywords: ['ad', 'show'],
}, },
{ {
id: '6RxgjmMLN', id: '77YljFpiH',
label: i18n.ts.hemisphere, label: i18n.ts.hemisphere,
keywords: [], keywords: [],
}, },
{ {
id: '5iMpm5rES', id: 'CZgDNPP1h',
label: i18n.ts.additionalEmojiDictionary, label: i18n.ts.additionalEmojiDictionary,
keywords: ['emoji', 'dictionary', 'additional', 'extra'], keywords: ['emoji', 'dictionary', 'additional', 'extra'],
}, },
@ -527,11 +537,6 @@ export const searchIndexes: SearchIndexItem[] = [
label: i18n.ts.other, label: i18n.ts.other,
keywords: ['other'], keywords: ['other'],
}, },
{
id: 'fnR7PRww5',
label: i18n.ts.dataSaver,
keywords: ['datasaver'],
},
], ],
label: i18n.ts.preferences, label: i18n.ts.preferences,
keywords: ['general', 'preferences', i18n.ts._settings.preferencesBanner], keywords: ['general', 'preferences', i18n.ts._settings.preferencesBanner],
@ -549,32 +554,32 @@ export const searchIndexes: SearchIndexItem[] = [
id: 'F1uK9ssiY', id: 'F1uK9ssiY',
children: [ children: [
{ {
id: 'msAcN6u3S', id: 'E0ndmaP6Q',
label: i18n.ts._role.policies, label: i18n.ts._role.policies,
keywords: ['account', 'info'], keywords: ['account', 'info'],
}, },
{ {
id: 'pbTLsgRO7', id: 'r5SjfwZJc',
label: i18n.ts.rolesAssignedToMe, label: i18n.ts.rolesAssignedToMe,
keywords: ['roles'], keywords: ['roles'],
}, },
{ {
id: 'fQpvZyfLK', id: 'cm7LrjgaW',
label: i18n.ts.accountMigration, label: i18n.ts.accountMigration,
keywords: ['account', 'move', 'migration'], keywords: ['account', 'move', 'migration'],
}, },
{ {
id: 'xhfur5m2z', id: 'ozfqNviP3',
label: i18n.ts.closeAccount, label: i18n.ts.closeAccount,
keywords: ['account', 'close', 'delete', i18n.ts._accountDelete.requestAccountDelete], keywords: ['account', 'close', 'delete', i18n.ts._accountDelete.requestAccountDelete],
}, },
{ {
id: 'oAXB8zm2U', id: 'tpywgkpxy',
label: i18n.ts.experimentalFeatures, label: i18n.ts.experimentalFeatures,
keywords: ['experimental', 'feature', 'flags'], keywords: ['experimental', 'feature', 'flags'],
}, },
{ {
id: '95OjjGSo7', id: '54wETGawJ',
label: i18n.ts.developer, label: i18n.ts.developer,
keywords: ['developer', 'mode', 'debug'], keywords: ['developer', 'mode', 'debug'],
}, },