wip
This commit is contained in:
parent
05d41f2a7a
commit
a37a945f95
|
@ -0,0 +1,38 @@
|
||||||
|
<!--
|
||||||
|
SPDX-FileCopyrightText: syuilo and misskey-project
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
-->
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div :class="[$style.root, { [$style.highlighted]: highlighted }]">
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { onMounted, onUnmounted, ref, shallowRef } from 'vue';
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
markerId: string;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const highlighted = window.location.hash.slice(1) === props.markerId;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" module>
|
||||||
|
.root {
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlighted {
|
||||||
|
animation: blink 1s infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes blink {
|
||||||
|
0%, 100% {
|
||||||
|
box-shadow: 0 0 0 2px color(from var(--MI_THEME-accent) srgb r g b / 0.3);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
box-shadow: 0 0 0 2px transparent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -5,26 +5,40 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="rrevdjwu" :class="{ grid }">
|
<div class="rrevdjwu" :class="{ grid }">
|
||||||
<div v-for="group in def" class="group">
|
<MkInput v-model="search" :placeholder="i18n.ts.search" type="search" style="margin-bottom: 16px;" @keydown.enter="searchSubmit">
|
||||||
<div v-if="group.title" class="title">{{ group.title }}</div>
|
<template #prefix><i class="ti ti-search"></i></template>
|
||||||
|
</MkInput>
|
||||||
|
|
||||||
<div class="items">
|
<template v-if="search == ''">
|
||||||
<template v-for="(item, i) in group.items">
|
<div v-for="group in def" class="group">
|
||||||
<a v-if="item.type === 'a'" :href="item.href" :target="item.target" class="_button item" :class="{ danger: item.danger, active: item.active }">
|
<div v-if="group.title" class="title">{{ group.title }}</div>
|
||||||
<span v-if="item.icon" class="icon"><i :class="item.icon" class="ti-fw"></i></span>
|
|
||||||
<span class="text">{{ item.text }}</span>
|
<div class="items">
|
||||||
</a>
|
<template v-for="(item, i) in group.items">
|
||||||
<button v-else-if="item.type === 'button'" class="_button item" :class="{ danger: item.danger, active: item.active }" :disabled="item.active" @click="ev => item.action(ev)">
|
<a v-if="item.type === 'a'" :href="item.href" :target="item.target" class="_button item" :class="{ danger: item.danger, active: item.active }">
|
||||||
<span v-if="item.icon" class="icon"><i :class="item.icon" class="ti-fw"></i></span>
|
<span v-if="item.icon" class="icon"><i :class="item.icon" class="ti-fw"></i></span>
|
||||||
<span class="text">{{ item.text }}</span>
|
<span class="text">{{ item.text }}</span>
|
||||||
</button>
|
</a>
|
||||||
<MkA v-else :to="item.to" class="_button item" :class="{ danger: item.danger, active: item.active }">
|
<button v-else-if="item.type === 'button'" class="_button item" :class="{ danger: item.danger, active: item.active }" :disabled="item.active" @click="ev => item.action(ev)">
|
||||||
<span v-if="item.icon" class="icon"><i :class="item.icon" class="ti-fw"></i></span>
|
<span v-if="item.icon" class="icon"><i :class="item.icon" class="ti-fw"></i></span>
|
||||||
<span class="text">{{ item.text }}</span>
|
<span class="text">{{ item.text }}</span>
|
||||||
</MkA>
|
</button>
|
||||||
</template>
|
<MkA v-else :to="item.to" class="_button item" :class="{ danger: item.danger, active: item.active }">
|
||||||
|
<span v-if="item.icon" class="icon"><i :class="item.icon" class="ti-fw"></i></span>
|
||||||
|
<span class="text">{{ item.text }}</span>
|
||||||
|
</MkA>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<div v-for="item in searchResult">
|
||||||
|
<MkA :to="item.path + '#' + item.id" class="_button searchResultItem">
|
||||||
|
<span v-if="item.icon" class="icon"><i :class="item.icon" class="ti-fw"></i></span>
|
||||||
|
<span class="text">{{ item.locationLabel.join(' > ') }}</span>
|
||||||
|
</MkA>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -58,10 +72,52 @@ export type SuperMenuDef = {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import { ref, watch } from 'vue';
|
||||||
|
import MkInput from '@/components/MkInput.vue';
|
||||||
|
import { i18n } from '@/i18n.js';
|
||||||
|
|
||||||
defineProps<{
|
defineProps<{
|
||||||
def: SuperMenuDef[];
|
def: SuperMenuDef[];
|
||||||
grid?: boolean;
|
grid?: boolean;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
|
const search = ref('');
|
||||||
|
const searchResult = ref<any[]>([]);
|
||||||
|
|
||||||
|
const INDEX = [{
|
||||||
|
id: '727cc9e8-ad67-474a-9241-b5a9a6475e47',
|
||||||
|
locationLabel: [i18n.ts.profile, i18n.ts._profile.name],
|
||||||
|
icon: 'ti ti-user',
|
||||||
|
keywords: ['name'],
|
||||||
|
path: '/settings/profile',
|
||||||
|
}, {
|
||||||
|
id: '1a06c7f9-e85e-46cb-bf5f-b3efa8e71b93',
|
||||||
|
locationLabel: [i18n.ts.profile, i18n.ts._profile.description],
|
||||||
|
icon: 'ti ti-user',
|
||||||
|
keywords: ['bio'],
|
||||||
|
path: '/settings/profile',
|
||||||
|
}, {
|
||||||
|
id: 'acbfe8cb-c3c9-4d90-8c62-713025814b2e',
|
||||||
|
locationLabel: [i18n.ts.privacy, i18n.ts.makeFollowManuallyApprove],
|
||||||
|
icon: 'ti ti-lock-open',
|
||||||
|
keywords: ['follow', 'lock', i18n.ts.lockedAccountInfo],
|
||||||
|
path: '/settings/privacy',
|
||||||
|
}];
|
||||||
|
|
||||||
|
watch(search, (value) => {
|
||||||
|
if (value === '') {
|
||||||
|
searchResult.value = [];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
searchResult.value = INDEX.filter((item) => {
|
||||||
|
// TODO: 日本語でひらがなカタカナの区別をしない
|
||||||
|
return item.locationLabel.some((x) => x.toLowerCase().includes(value.toLowerCase())) || item.keywords.some((x) => x.toLowerCase().includes(value.toLowerCase()));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function searchSubmit() {
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
@ -184,5 +240,47 @@ defineProps<{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.searchResultItem {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 9px 16px 9px 8px;
|
||||||
|
border-radius: 9px;
|
||||||
|
font-size: 0.9em;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
text-decoration: none;
|
||||||
|
background: var(--MI_THEME-panelHighlight);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus-visible {
|
||||||
|
outline-offset: -2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
color: var(--MI_THEME-accent);
|
||||||
|
background: var(--MI_THEME-accentedBg);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.danger {
|
||||||
|
color: var(--MI_THEME-error);
|
||||||
|
}
|
||||||
|
|
||||||
|
> .icon {
|
||||||
|
width: 32px;
|
||||||
|
margin-right: 2px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
text-align: center;
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
> .text {
|
||||||
|
white-space: normal;
|
||||||
|
padding-right: 12px;
|
||||||
|
flex-shrink: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -5,7 +5,10 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="_gaps_m">
|
<div class="_gaps_m">
|
||||||
<MkSwitch v-model="isLocked" @update:modelValue="save()">{{ i18n.ts.makeFollowManuallyApprove }}<template #caption>{{ i18n.ts.lockedAccountInfo }}</template></MkSwitch>
|
<MkSearchMarker markerId="acbfe8cb-c3c9-4d90-8c62-713025814b2e">
|
||||||
|
<MkSwitch v-model="isLocked" @update:modelValue="save()">{{ i18n.ts.makeFollowManuallyApprove }}<template #caption>{{ i18n.ts.lockedAccountInfo }}</template></MkSwitch>
|
||||||
|
</MkSearchMarker>
|
||||||
|
|
||||||
<MkSwitch v-if="isLocked" v-model="autoAcceptFollowed" @update:modelValue="save()">{{ i18n.ts.autoAcceptFollowed }}</MkSwitch>
|
<MkSwitch v-if="isLocked" v-model="autoAcceptFollowed" @update:modelValue="save()">{{ i18n.ts.autoAcceptFollowed }}</MkSwitch>
|
||||||
|
|
||||||
<MkSwitch v-model="publicReactions" @update:modelValue="save()">
|
<MkSwitch v-model="publicReactions" @update:modelValue="save()">
|
||||||
|
@ -174,6 +177,7 @@ import FormSlot from '@/components/form/slot.vue';
|
||||||
import { formatDateTimeString } from '@/scripts/format-time-string.js';
|
import { formatDateTimeString } from '@/scripts/format-time-string.js';
|
||||||
import MkInput from '@/components/MkInput.vue';
|
import MkInput from '@/components/MkInput.vue';
|
||||||
import * as os from '@/os.js';
|
import * as os from '@/os.js';
|
||||||
|
import MkSearchMarker from '@/components/MkSearchMarker.vue';
|
||||||
|
|
||||||
const $i = signinRequired();
|
const $i = signinRequired();
|
||||||
|
|
||||||
|
|
|
@ -18,14 +18,18 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<MkInput v-model="profile.name" :max="30" manualSave :mfmAutocomplete="['emoji']">
|
<MkSearchMarker markerId="727cc9e8-ad67-474a-9241-b5a9a6475e47">
|
||||||
<template #label>{{ i18n.ts._profile.name }}</template>
|
<MkInput v-model="profile.name" :max="30" manualSave :mfmAutocomplete="['emoji']">
|
||||||
</MkInput>
|
<template #label>{{ i18n.ts._profile.name }}</template>
|
||||||
|
</MkInput>
|
||||||
|
</MkSearchMarker>
|
||||||
|
|
||||||
<MkTextarea v-model="profile.description" :max="500" tall manualSave mfmAutocomplete :mfmPreview="true">
|
<MkSearchMarker markerId="1a06c7f9-e85e-46cb-bf5f-b3efa8e71b93">
|
||||||
<template #label>{{ i18n.ts._profile.description }}</template>
|
<MkTextarea v-model="profile.description" :max="500" tall manualSave mfmAutocomplete :mfmPreview="true">
|
||||||
<template #caption>{{ i18n.ts._profile.youCanIncludeHashtags }}</template>
|
<template #label>{{ i18n.ts._profile.description }}</template>
|
||||||
</MkTextarea>
|
<template #caption>{{ i18n.ts._profile.youCanIncludeHashtags }}</template>
|
||||||
|
</MkTextarea>
|
||||||
|
</MkSearchMarker>
|
||||||
|
|
||||||
<MkInput v-model="profile.location" manualSave>
|
<MkInput v-model="profile.location" manualSave>
|
||||||
<template #label>{{ i18n.ts.location }}</template>
|
<template #label>{{ i18n.ts.location }}</template>
|
||||||
|
@ -121,6 +125,7 @@ import MkButton from '@/components/MkButton.vue';
|
||||||
import MkInput from '@/components/MkInput.vue';
|
import MkInput from '@/components/MkInput.vue';
|
||||||
import MkSwitch from '@/components/MkSwitch.vue';
|
import MkSwitch from '@/components/MkSwitch.vue';
|
||||||
import MkSelect from '@/components/MkSelect.vue';
|
import MkSelect from '@/components/MkSelect.vue';
|
||||||
|
import MkSearchMarker from '@/components/MkSearchMarker.vue';
|
||||||
import FormSplit from '@/components/form/split.vue';
|
import FormSplit from '@/components/form/split.vue';
|
||||||
import MkFolder from '@/components/MkFolder.vue';
|
import MkFolder from '@/components/MkFolder.vue';
|
||||||
import FormSlot from '@/components/form/slot.vue';
|
import FormSlot from '@/components/form/slot.vue';
|
||||||
|
|
Loading…
Reference in New Issue