<!-- SPDX-FileCopyrightText: syuilo and misskey-project SPDX-License-Identifier: AGPL-3.0-only --> <template> <div class="_gaps"> <div style="word-break: auto-phrase; text-align: center; padding: 0 16px;">{{ i18n.ts._initialTutorial._profileSettings.description }}</div> <FormSlot> <template #label>{{ i18n.ts.avatar }}</template> <div v-adaptive-bg :class="$style.avatarSection" class="_panel"> <MkAvatar :class="$style.avatar" :user="$i" @click="setAvatar"/> <div style="margin-top: 16px;"> <MkButton primary rounded inline @click="setAvatar">{{ i18n.ts._profile.changeAvatar }}</MkButton> </div> </div> </FormSlot> <MkInput v-model="name" :max="30" manualSave> <template #label>{{ i18n.ts._profile.name }}</template> </MkInput> <MkTextarea v-model="description" :max="500" tall manualSave> <template #label>{{ i18n.ts._profile.description }}</template> </MkTextarea> <MkInfo>{{ i18n.ts._initialTutorial._profileSettings.youCanChangeThemLater }}</MkInfo> </div> </template> <script lang="ts" setup> import { ref, watch } from 'vue'; import { i18n } from '@/i18n.js'; import MkButton from '@/components/MkButton.vue'; import MkInput from '@/components/MkInput.vue'; import MkTextarea from '@/components/MkTextarea.vue'; import FormSlot from '@/components/form/slot.vue'; import MkInfo from '@/components/MkInfo.vue'; import { selectFile } from '@/scripts/select-file.js'; import * as os from '@/os.js'; import { signinRequired } from '@/account.js'; const $i = signinRequired(); const name = ref($i.name ?? ''); const description = ref($i.description ?? ''); watch(name, () => { os.apiWithDialog('i/update', { // 空文字列をnullにしたいので??は使うな // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing name: name.value || null, }); }); watch(description, () => { os.apiWithDialog('i/update', { // 空文字列をnullにしたいので??は使うな // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing description: description.value || null, }); }); function setAvatar(ev: MouseEvent) { selectFile(ev.currentTarget ?? ev.target).then(async (file) => { let originalOrCropped = file; const { canceled } = await os.confirm({ type: 'question', text: i18n.ts.cropImageAsk, okText: i18n.ts.cropYes, cancelText: i18n.ts.cropNo, }); if (!canceled) { originalOrCropped = await os.cropImage(file, { aspectRatio: 1, }); } const i = await os.apiWithDialog('i/update', { avatarId: originalOrCropped.id, }); $i.avatarId = i.avatarId; $i.avatarUrl = i.avatarUrl; }); } </script> <style lang="scss" module> .avatarSection { text-align: center; padding: 20px; } .avatar { width: 100px; height: 100px; background: var(--bg); } </style>