Mod: プロキシアカウントの設定画面で名前,概要,アバター,バナーを変更可能に

This commit is contained in:
鴇峰 朔華 2024-11-22 11:19:40 +09:00
parent 0d6cbf60b8
commit 00c0ad6d92

View file

@ -238,15 +238,33 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkFolder>
<template #icon><i class="ti ti-ghost"></i></template>
<template #label>{{ i18n.ts.proxyAccount }}</template>
<template v-if="proxyAccountForm.modified.value" #footer>
<MkFormFooter :form="proxyAccountForm"/>
</template>
<div class="_gaps">
<MkInfo>{{ i18n.ts.proxyAccountDescription }}</MkInfo>
<MkKeyValue>
<template #key>{{ i18n.ts.proxyAccount }}</template>
<template #value>{{ proxyAccount ? `@${proxyAccount.username}` : i18n.ts.none }}</template>
</MkKeyValue>
<MkButton primary @click="chooseProxyAccount">{{ i18n.ts.selectAccount }}</MkButton>
<div class="_panel">
<div :class="$style.banner" :style="{ backgroundImage: proxyAccount.bannerUrl ? `url(${ proxyAccount.bannerUrl })` : null }">
<MkButton primary rounded :class="$style.bannerEdit" @click="changeProxyAccountBanner">{{ i18n.ts._profile.changeBanner }}</MkButton>
</div>
<div :class="$style.avatarContainer">
<MkAvatar :class="$style.avatar" :user="proxyAccount" forceShowDecoration @click="changeProxyAccountAvatar"/>
<div class="_buttonsCenter">
<MkButton primary rounded @click="changeProxyAccountAvatar">{{ i18n.ts._profile.changeAvatar }}</MkButton>
</div>
</div>
</div>
<MkInput v-model="proxyAccountForm.state.name" :max="30" :mfmAutocomplete="['emoji']">
<template #label>{{ i18n.ts._profile.name }}</template>
</MkInput>
<MkTextarea v-model="proxyAccountForm.state.description" :max="500" tall mfmAutocomplete :mfmPreview="true">
<template #label>{{ i18n.ts._profile.description }}</template>
<template #caption>{{ i18n.ts._profile.youCanIncludeHashtags }}</template>
</MkTextarea>
</div>
</MkFolder>
</div>
@ -256,7 +274,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</template>
<script lang="ts" setup>
import { ref, computed } from 'vue';
import { ref, computed, reactive } from 'vue';
import XHeader from './_header_.vue';
import MkSwitch from '@/components/MkSwitch.vue';
import MkInput from '@/components/MkInput.vue';
@ -274,10 +292,17 @@ import MkKeyValue from '@/components/MkKeyValue.vue';
import { useForm } from '@/scripts/use-form.js';
import MkFormFooter from '@/components/MkFormFooter.vue';
import MkRadios from '@/components/MkRadios.vue';
import { selectFile } from '@/scripts/select-file.js';
import { globalEvents } from '@/events.js';
import { claimAchievement } from '@/scripts/achievements.js';
const meta = await misskeyApi('admin/meta');
const proxyAccount = ref(meta.proxyAccountId ? await misskeyApi('users/show', { userId: meta.proxyAccountId }) : null);
const proxyAccountProfile = reactive({
name: proxyAccount.value.name,
description: proxyAccount.value.description,
});
const infoForm = useForm({
name: meta.name ?? '',
@ -378,6 +403,69 @@ const federationForm = useForm({
fetchInstance(true);
});
const proxyAccountForm = useForm({
name: proxyAccountProfile.name,
description: proxyAccountProfile.description,
}, async (state) => {
await os.apiWithDialog('admin/update-proxy-account', {
name: state.name,
description: state.description,
});
fetchInstance(true);
});
function changeProxyAccountAvatar(ev) {
selectFile(ev.currentTarget ?? ev.target, i18n.ts.avatar).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 proxy = await os.apiWithDialog('admin/update-proxy-account', {
avatarId: originalOrCropped.id,
});
proxyAccount.value.avatarId = proxy.avatarId;
proxyAccount.value.avatarUrl = proxy.avatarUrl;
globalEvents.emit('requestClearPageCache');
});
}
function changeProxyAccountBanner(ev) {
selectFile(ev.currentTarget ?? ev.target, i18n.ts.banner).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: 2,
});
}
const proxy = await os.apiWithDialog('admin/update-proxy-account', {
bannerId: originalOrCropped.id,
});
proxyAccount.value.bannerId = proxy.bannerId;
proxyAccount.value.bannerUrl = proxy.bannerUrl;
globalEvents.emit('requestClearPageCache');
});
}
function chooseProxyAccount() {
os.selectUser({ localOnly: true }).then(user => {
proxyAccount.value = user;
@ -402,4 +490,32 @@ definePageMetadata(() => ({
font-size: 0.85em;
color: var(--MI_THEME-fgTransparentWeak);
}
.banner {
position: relative;
height: 130px;
background-size: cover;
background-position: center;
border-bottom: solid 1px var(--MI_THEME-divider);
overflow: clip;
}
.avatarContainer {
margin-top: -50px;
padding-bottom: 16px;
text-align: center;
}
.avatar {
display: inline-block;
width: 72px;
height: 72px;
margin: 0 auto 16px auto;
}
.bannerEdit {
position: absolute;
top: 16px;
right: 16px;
}
</style>