enhance(profile): 相互リンクの機能改善 (MisskeyIO#703)

This commit is contained in:
まっちゃてぃー。 2024-08-18 04:17:27 +09:00 committed by GitHub
parent 08fcb3b3fa
commit c239c425b4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 61 additions and 7 deletions

4
locales/index.d.ts vendored
View File

@ -5095,6 +5095,10 @@ export interface Locale extends ILocale {
* *
*/ */
"mutualLink": string; "mutualLink": string;
/**
*
*/
"saveThisFile": string;
"_bubbleGame": { "_bubbleGame": {
/** /**
* *

View File

@ -1269,6 +1269,7 @@ blockThisUser: "このユーザーをブロックする"
muteThisUser: "このユーザーをミュートする" muteThisUser: "このユーザーをミュートする"
here: "こちら" here: "こちら"
mutualLink: "相互リンク" mutualLink: "相互リンク"
saveThisFile: "このファイルをドライブに保存する"
_bubbleGame: _bubbleGame:
howToPlay: "遊び方" howToPlay: "遊び方"

View File

@ -19,8 +19,9 @@ export const paramDef = {
type: 'object', type: 'object',
properties: { properties: {
userId: { type: 'string', format: 'misskey:id' }, userId: { type: 'string', format: 'misskey:id' },
itemId: { type: 'string', format: 'misskey:id' },
}, },
required: ['userId'], required: ['userId', 'itemId'],
} as const; } as const;
// eslint-disable-next-line import/no-default-export // eslint-disable-next-line import/no-default-export
@ -43,7 +44,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
} }
await this.userProfilesRepository.update(user.id, { await this.userProfilesRepository.update(user.id, {
mutualLinkSections: [], mutualLinkSections: userProfile.mutualLinkSections.map(section => ({
...section,
mutualLinks: section.mutualLinks.filter(item => item.id !== ps.itemId),
})),
}); });
this.moderationLogService.log(me, 'unsetUserMutualLink', { this.moderationLogService.log(me, 'unsetUserMutualLink', {

View File

@ -62,6 +62,7 @@ import { i18n } from '@/i18n.js';
import * as os from '@/os.js'; import * as os from '@/os.js';
import { pleaseLogin } from '@/scripts/please-login.js'; import { pleaseLogin } from '@/scripts/please-login.js';
import { $i, iAmModerator } from '@/account.js'; import { $i, iAmModerator } from '@/account.js';
import { misskeyApi } from '@/scripts/misskey-api.js';
const props = withDefaults(defineProps<{ const props = withDefaults(defineProps<{
image: Misskey.entities.DriveFile; image: Misskey.entities.DriveFile;
@ -92,6 +93,20 @@ function showMenu(ev: MouseEvent) {
action: () => { action: () => {
hide.value = true; hide.value = true;
}, },
}, {
text: i18n.ts.saveThisFile,
icon: 'ti ti-cloud-upload',
action: () => {
os.selectDriveFolder(false).then(async folder => {
if (folder[0] == null) {
return;
}
misskeyApi('drive/files/upload-from-url', {
url: props.image.url,
folderId: folder ? folder[0].id : undefined,
});
});
},
}]; }];
if ($i?.id === props.image.userId || iAmModerator) { if ($i?.id === props.image.userId || iAmModerator) {

View File

@ -66,7 +66,19 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkButton v-if="user.host == null" @click="resetPassword"><i class="ti ti-key"></i> {{ i18n.ts.resetPassword }}</MkButton> <MkButton v-if="user.host == null" @click="resetPassword"><i class="ti ti-key"></i> {{ i18n.ts.resetPassword }}</MkButton>
<MkButton inline danger @click="unsetUserAvatar"><i class="ti ti-user-circle"></i> {{ i18n.ts.unsetUserAvatar }}</MkButton> <MkButton inline danger @click="unsetUserAvatar"><i class="ti ti-user-circle"></i> {{ i18n.ts.unsetUserAvatar }}</MkButton>
<MkButton inline danger @click="unsetUserBanner"><i class="ti ti-photo"></i> {{ i18n.ts.unsetUserBanner }}</MkButton> <MkButton inline danger @click="unsetUserBanner"><i class="ti ti-photo"></i> {{ i18n.ts.unsetUserBanner }}</MkButton>
<MkButton inline danger @click="unsetUserMutualLink"><i class="ti ti-photo"></i> {{ i18n.ts.unsetUserMutualLink }}</MkButton> <MkFolder v-if="user?.mutualLinkSections && user?.mutualLinkSections.reduce((acc, section) => acc + section.mutualLinks.length, 0) > 0">
<template #icon><i class="ti ti-link"></i></template>
<template #label>{{ i18n.ts._profile.mutualLinksEdit }}</template>
<div v-for="mutualLinkSection in user?.mutualLinkSections">
<div v-for="mutualLink in mutualLinkSection.mutualLinks" :key="mutualLink.id" :class="$style.fields">
<p> {{ mutualLink.url }} </p>
<img :class="$style.mutualLinkImg" :src="mutualLink.imgSrc" :alt="mutualLink.description"/>
<p> {{ mutualLink.description }} </p>
<MkButton inline danger @click="unsetUserMutualLink(mutualLink.id)"><i class="ti ti-link"></i> {{ i18n.ts.unsetUserMutualLink }}</MkButton>
</div>
</div>
</MkFolder>
</div> </div>
</MkFolder> </MkFolder>
@ -365,15 +377,16 @@ async function unsetUserBanner() {
}).then(refreshUser); }).then(refreshUser);
} }
async function unsetUserMutualLink() { async function unsetUserMutualLink(mutualLinkid: string) {
const confirm = await os.confirm({ const confirm = await os.confirm({
type: 'warning', type: 'warning',
text: i18n.ts.unsetUserMutualLinkConfirm, text: i18n.ts.unsetUserMutualLinkConfirm,
}); });
if (confirm.canceled) return; if (confirm.canceled) return;
await os.apiWithDialog('admin/unset-user-mutual-banner', { await os.apiWithDialog('admin/unset-user-mutual-link', {
userId: user.value.id, userId: user.value.id,
itemId: mutualLinkid,
}).then(refreshUser); }).then(refreshUser);
} }
@ -705,4 +718,16 @@ definePageMetadata(() => ({
border-radius: 6px; border-radius: 6px;
cursor: pointer; cursor: pointer;
} }
.mutualLinkImg {
max-width: 200px;
max-height: 40px;
}
.fields {
padding: 24px;
border-bottom: solid 0.5px var(--divider);
&:last-child {
border-bottom: none;
}
}
</style> </style>

View File

@ -112,7 +112,9 @@ SPDX-License-Identifier: AGPL-3.0-only
<template #item="{ element: sectionElement, index: sectionIndex }"> <template #item="{ element: sectionElement, index: sectionIndex }">
<div :class="$style.mutualLinkSectionRoot"> <div :class="$style.mutualLinkSectionRoot">
<button v-if="!mutualLinkSectionEditMode" class="_button" :class="$style.dragItemHandle" tabindex="-1"><i class="ti ti-menu"></i></button> <button v-if="!mutualLinkSectionEditMode" class="_button" :class="$style.dragItemHandle" tabindex="-1"><i class="ti ti-menu"></i></button>
<button v-if="mutualLinkSectionEditMode" :disabled="fields.length <= 1" class="_button" :class="$style.dragItemRemove" @click="deleteMutualLinkSection(sectionIndex)"><i class="ti ti-x"></i></button>
{{sectionElement.length }}
<button v-if="mutualLinkSectionEditMode" :disabled="sectionElement.length <= 1" class="_button" :class="$style.dragItemRemove" @click="deleteMutualLinkSection(sectionIndex)"><i class="ti ti-x"></i></button>
<FormSlot :style="{flexGrow: 1}"> <FormSlot :style="{flexGrow: 1}">
<MkFolder> <MkFolder>
<template #label>{{ sectionElement.name || i18n.ts._profile.sectionNameNone }}</template> <template #label>{{ sectionElement.name || i18n.ts._profile.sectionNameNone }}</template>
@ -136,7 +138,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template #item="{ element: linkElement, index: linkIndex }"> <template #item="{ element: linkElement, index: linkIndex }">
<div :class="$style.mutualLinkRoot"> <div :class="$style.mutualLinkRoot">
<button v-if="!mutualLinkSectionEditMode" class="_button" :class="$style.dragItemHandle" tabindex="-1"><i class="ti ti-menu"></i></button> <button v-if="!mutualLinkSectionEditMode" class="_button" :class="$style.dragItemHandle" tabindex="-1"><i class="ti ti-menu"></i></button>
<button v-if="mutualLinkSectionEditMode" :disabled="fields.length <= 1" class="_button" :class="$style.dragItemRemove" @click="deleteMutualLink(sectionIndex,linkIndex)"><i class="ti ti-x"></i></button> <button v-if="mutualLinkSectionEditMode" class="_button" :class="$style.dragItemRemove" @click="deleteMutualLink(sectionIndex,linkIndex)"><i class="ti ti-x"></i></button>
<div class="_gaps_s" :style="{flex: 1}"> <div class="_gaps_s" :style="{flex: 1}">
<MkInfo v-if="linkIndex >= $i.policies.mutualLinkLimit" warn><Mfm :text="i18n.tsx._profile.policyDisplayLimitExceeded({ max: $i.policies.mutualLinkLimit })"/></MkInfo> <MkInfo v-if="linkIndex >= $i.policies.mutualLinkLimit" warn><Mfm :text="i18n.tsx._profile.policyDisplayLimitExceeded({ max: $i.policies.mutualLinkLimit })"/></MkInfo>

View File

@ -624,6 +624,7 @@ onUnmounted(() => {
padding: 24px; padding: 24px;
font-size: 0.9em; font-size: 0.9em;
border-top: solid 0.5px var(--divider); border-top: solid 0.5px var(--divider);
margin-top: 0.5px;
> .field { > .field {
display: flex; display: flex;

View File

@ -6855,6 +6855,8 @@ export type operations = {
'application/json': { 'application/json': {
/** Format: misskey:id */ /** Format: misskey:id */
userId: string; userId: string;
/** Format: misskey:id */
itemId: string;
}; };
}; };
}; };