enhance(profile): 相互リンクの機能改善 (MisskeyIO#703)
This commit is contained in:
parent
08fcb3b3fa
commit
c239c425b4
4
locales/index.d.ts
vendored
4
locales/index.d.ts
vendored
@ -5095,6 +5095,10 @@ export interface Locale extends ILocale {
|
|||||||
* 相互リンク
|
* 相互リンク
|
||||||
*/
|
*/
|
||||||
"mutualLink": string;
|
"mutualLink": string;
|
||||||
|
/**
|
||||||
|
* このファイルをドライブに保存する
|
||||||
|
*/
|
||||||
|
"saveThisFile": string;
|
||||||
"_bubbleGame": {
|
"_bubbleGame": {
|
||||||
/**
|
/**
|
||||||
* 遊び方
|
* 遊び方
|
||||||
|
@ -1269,6 +1269,7 @@ blockThisUser: "このユーザーをブロックする"
|
|||||||
muteThisUser: "このユーザーをミュートする"
|
muteThisUser: "このユーザーをミュートする"
|
||||||
here: "こちら"
|
here: "こちら"
|
||||||
mutualLink: "相互リンク"
|
mutualLink: "相互リンク"
|
||||||
|
saveThisFile: "このファイルをドライブに保存する"
|
||||||
|
|
||||||
_bubbleGame:
|
_bubbleGame:
|
||||||
howToPlay: "遊び方"
|
howToPlay: "遊び方"
|
||||||
|
@ -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', {
|
||||||
|
@ -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) {
|
||||||
|
@ -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>
|
||||||
|
@ -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>
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user