Compare commits
4 Commits
ec73511759
...
55aa86777d
Author | SHA1 | Date |
---|---|---|
syuilo | 55aa86777d | |
syuilo | b982ba56bc | |
鴇峰 朔華 | 4603ab67bb | |
zawa-ch. | 763c708253 |
|
@ -65,6 +65,7 @@
|
||||||
- Fix: FTT無効時にユーザーリストタイムラインが使用できない問題を修正
|
- Fix: FTT無効時にユーザーリストタイムラインが使用できない問題を修正
|
||||||
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/709)
|
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/709)
|
||||||
- Fix: User Webhookテスト機能のMock Payloadを修正
|
- Fix: User Webhookテスト機能のMock Payloadを修正
|
||||||
|
- Fix: アカウント削除のモデレーションログが動作していないのを修正 (#14996)
|
||||||
|
|
||||||
### Misskey.js
|
### Misskey.js
|
||||||
- Fix: Stream初期化時、別途WebSocketを指定する場合の型定義を修正
|
- Fix: Stream初期化時、別途WebSocketを指定する場合の型定義を修正
|
||||||
|
|
|
@ -46,7 +46,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||||
throw new Error('cannot delete a root account');
|
throw new Error('cannot delete a root account');
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.deleteAccoountService.deleteAccount(user);
|
await this.deleteAccoountService.deleteAccount(user, me);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,13 +33,13 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||||
|
|
||||||
private deleteAccountService: DeleteAccountService,
|
private deleteAccountService: DeleteAccountService,
|
||||||
) {
|
) {
|
||||||
super(meta, paramDef, async (ps) => {
|
super(meta, paramDef, async (ps, me) => {
|
||||||
const user = await this.usersRepository.findOneByOrFail({ id: ps.userId });
|
const user = await this.usersRepository.findOneByOrFail({ id: ps.userId });
|
||||||
if (user.isDeleted) {
|
if (user.isDeleted) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.deleteAccountService.deleteAccount(user);
|
await this.deleteAccountService.deleteAccount(user, me);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,17 +25,18 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, inject, ref } from 'vue';
|
import { computed, defineAsyncComponent, inject, ref } from 'vue';
|
||||||
|
import type { MenuItem } from '@/types/menu.js';
|
||||||
import { getProxiedImageUrl, getStaticImageUrl } from '@/scripts/media-proxy.js';
|
import { getProxiedImageUrl, getStaticImageUrl } from '@/scripts/media-proxy.js';
|
||||||
import { defaultStore } from '@/store.js';
|
import { defaultStore } from '@/store.js';
|
||||||
import { customEmojisMap } from '@/custom-emojis.js';
|
import { customEmojisMap } from '@/custom-emojis.js';
|
||||||
import * as os from '@/os.js';
|
import * as os from '@/os.js';
|
||||||
import { misskeyApiGet } from '@/scripts/misskey-api.js';
|
import { misskeyApi, misskeyApiGet } from '@/scripts/misskey-api.js';
|
||||||
import { copyToClipboard } from '@/scripts/copy-to-clipboard.js';
|
import { copyToClipboard } from '@/scripts/copy-to-clipboard.js';
|
||||||
import * as sound from '@/scripts/sound.js';
|
import * as sound from '@/scripts/sound.js';
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
import MkCustomEmojiDetailedDialog from '@/components/MkCustomEmojiDetailedDialog.vue';
|
import MkCustomEmojiDetailedDialog from '@/components/MkCustomEmojiDetailedDialog.vue';
|
||||||
import type { MenuItem } from '@/types/menu.js';
|
import { $i } from '@/account.js';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
name: string;
|
name: string;
|
||||||
|
@ -125,9 +126,31 @@ function onClick(ev: MouseEvent) {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if ($i?.isModerator ?? $i?.isAdmin) {
|
||||||
|
menuItems.push({
|
||||||
|
text: i18n.ts.edit,
|
||||||
|
icon: 'ti ti-pencil',
|
||||||
|
action: async () => {
|
||||||
|
await edit(props.name);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
os.popupMenu(menuItems, ev.currentTarget ?? ev.target);
|
os.popupMenu(menuItems, ev.currentTarget ?? ev.target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function edit(name: string) {
|
||||||
|
const emoji = await misskeyApi('emoji', {
|
||||||
|
name: name,
|
||||||
|
});
|
||||||
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/pages/emoji-edit-dialog.vue')), {
|
||||||
|
emoji: emoji,
|
||||||
|
}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" module>
|
<style lang="scss" module>
|
||||||
|
|
|
@ -33,26 +33,28 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, watch, provide, ref } from 'vue';
|
import { computed, watch, provide, ref } from 'vue';
|
||||||
import * as Misskey from 'misskey-js';
|
import * as Misskey from 'misskey-js';
|
||||||
|
import { url } from '@@/js/config.js';
|
||||||
|
import type { MenuItem } from '@/types/menu.js';
|
||||||
import MkNotes from '@/components/MkNotes.vue';
|
import MkNotes from '@/components/MkNotes.vue';
|
||||||
import { $i } from '@/account.js';
|
import { $i } from '@/account.js';
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
import * as os from '@/os.js';
|
import * as os from '@/os.js';
|
||||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||||
import { url } from '@@/js/config.js';
|
|
||||||
import MkButton from '@/components/MkButton.vue';
|
import MkButton from '@/components/MkButton.vue';
|
||||||
import { clipsCache } from '@/cache.js';
|
import { clipsCache } from '@/cache.js';
|
||||||
import { isSupportShare } from '@/scripts/navigator.js';
|
import { isSupportShare } from '@/scripts/navigator.js';
|
||||||
import { copyToClipboard } from '@/scripts/copy-to-clipboard.js';
|
import { copyToClipboard } from '@/scripts/copy-to-clipboard.js';
|
||||||
import { genEmbedCode } from '@/scripts/get-embed-code.js';
|
import { genEmbedCode } from '@/scripts/get-embed-code.js';
|
||||||
import type { MenuItem } from '@/types/menu.js';
|
|
||||||
import { getServerContext } from '@/server-context.js';
|
import { getServerContext } from '@/server-context.js';
|
||||||
|
|
||||||
|
const CTX_CLIP = getServerContext('clip');
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
clipId: string,
|
clipId: string,
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const clip = ref<Misskey.entities.Clip | null>(getServerContext('clip'));
|
const clip = ref<Misskey.entities.Clip | null>(CTX_CLIP);
|
||||||
const favorited = ref(false);
|
const favorited = ref(false);
|
||||||
const pagination = {
|
const pagination = {
|
||||||
endpoint: 'clips/notes' as const,
|
endpoint: 'clips/notes' as const,
|
||||||
|
@ -65,8 +67,8 @@ const pagination = {
|
||||||
const isOwned = computed<boolean | null>(() => $i && clip.value && ($i.id === clip.value.userId));
|
const isOwned = computed<boolean | null>(() => $i && clip.value && ($i.id === clip.value.userId));
|
||||||
|
|
||||||
watch(() => props.clipId, async () => {
|
watch(() => props.clipId, async () => {
|
||||||
if (getServerContext('clip') && getServerContext('clip').id === props.clipId) {
|
if (CTX_CLIP && CTX_CLIP.id === props.clipId) {
|
||||||
clip.value = getServerContext('clip');
|
clip.value = CTX_CLIP;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,18 +15,22 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import * as Misskey from 'misskey-js';
|
import * as Misskey from 'misskey-js';
|
||||||
|
import { defineAsyncComponent } from 'vue';
|
||||||
|
import type { MenuItem } from '@/types/menu.js';
|
||||||
import * as os from '@/os.js';
|
import * as os from '@/os.js';
|
||||||
import { misskeyApiGet } from '@/scripts/misskey-api.js';
|
import { misskeyApiGet } from '@/scripts/misskey-api.js';
|
||||||
import { copyToClipboard } from '@/scripts/copy-to-clipboard.js';
|
import { copyToClipboard } from '@/scripts/copy-to-clipboard.js';
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
import MkCustomEmojiDetailedDialog from '@/components/MkCustomEmojiDetailedDialog.vue';
|
import MkCustomEmojiDetailedDialog from '@/components/MkCustomEmojiDetailedDialog.vue';
|
||||||
|
import { $i } from '@/account.js';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
emoji: Misskey.entities.EmojiSimple;
|
emoji: Misskey.entities.EmojiSimple;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
function menu(ev) {
|
function menu(ev) {
|
||||||
os.popupMenu([{
|
const menuItems: MenuItem[] = [];
|
||||||
|
menuItems.push({
|
||||||
type: 'label',
|
type: 'label',
|
||||||
text: ':' + props.emoji.name + ':',
|
text: ':' + props.emoji.name + ':',
|
||||||
}, {
|
}, {
|
||||||
|
@ -48,8 +52,28 @@ function menu(ev) {
|
||||||
closed: () => dispose(),
|
closed: () => dispose(),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
}], ev.currentTarget ?? ev.target);
|
});
|
||||||
|
|
||||||
|
if ($i?.isModerator ?? $i?.isAdmin) {
|
||||||
|
menuItems.push({
|
||||||
|
text: i18n.ts.edit,
|
||||||
|
icon: 'ti ti-pencil',
|
||||||
|
action: () => {
|
||||||
|
edit(props.emoji);
|
||||||
|
},
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
os.popupMenu(menuItems, ev.currentTarget ?? ev.target);
|
||||||
|
}
|
||||||
|
|
||||||
|
const edit = async (emoji) => {
|
||||||
|
const { dispose } = os.popup(defineAsyncComponent(() => import('@/pages/emoji-edit-dialog.vue')), {
|
||||||
|
emoji: emoji,
|
||||||
|
}, {
|
||||||
|
closed: () => dispose(),
|
||||||
|
});
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" module>
|
<style lang="scss" module>
|
||||||
|
|
|
@ -64,12 +64,14 @@ import { defaultStore } from '@/store.js';
|
||||||
import { pleaseLogin } from '@/scripts/please-login.js';
|
import { pleaseLogin } from '@/scripts/please-login.js';
|
||||||
import { getServerContext } from '@/server-context.js';
|
import { getServerContext } from '@/server-context.js';
|
||||||
|
|
||||||
|
const CTX_NOTE = getServerContext('note');
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
noteId: string;
|
noteId: string;
|
||||||
initialTab?: string;
|
initialTab?: string;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const note = ref<null | Misskey.entities.Note>(getServerContext('note'));
|
const note = ref<null | Misskey.entities.Note>(CTX_NOTE);
|
||||||
const clips = ref<Misskey.entities.Clip[]>();
|
const clips = ref<Misskey.entities.Clip[]>();
|
||||||
const showPrev = ref<'user' | 'channel' | false>(false);
|
const showPrev = ref<'user' | 'channel' | false>(false);
|
||||||
const showNext = ref<'user' | 'channel' | false>(false);
|
const showNext = ref<'user' | 'channel' | false>(false);
|
||||||
|
@ -118,8 +120,8 @@ function fetchNote() {
|
||||||
showNext.value = false;
|
showNext.value = false;
|
||||||
note.value = null;
|
note.value = null;
|
||||||
|
|
||||||
if (getServerContext('note') && getServerContext('note').id === props.noteId) {
|
if (CTX_NOTE && CTX_NOTE.id === props.noteId) {
|
||||||
note.value = getServerContext('note');
|
note.value = CTX_NOTE;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,7 @@ import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||||
import { i18n } from '@/i18n.js';
|
import { i18n } from '@/i18n.js';
|
||||||
import { $i } from '@/account.js';
|
import { $i } from '@/account.js';
|
||||||
import MkHorizontalSwipe from '@/components/MkHorizontalSwipe.vue';
|
import MkHorizontalSwipe from '@/components/MkHorizontalSwipe.vue';
|
||||||
|
import { getServerContext } from '@/server-context.js';
|
||||||
|
|
||||||
const XHome = defineAsyncComponent(() => import('./home.vue'));
|
const XHome = defineAsyncComponent(() => import('./home.vue'));
|
||||||
const XTimeline = defineAsyncComponent(() => import('./index.timeline.vue'));
|
const XTimeline = defineAsyncComponent(() => import('./index.timeline.vue'));
|
||||||
|
@ -52,6 +53,8 @@ const XFlashs = defineAsyncComponent(() => import('./flashs.vue'));
|
||||||
const XGallery = defineAsyncComponent(() => import('./gallery.vue'));
|
const XGallery = defineAsyncComponent(() => import('./gallery.vue'));
|
||||||
const XRaw = defineAsyncComponent(() => import('./raw.vue'));
|
const XRaw = defineAsyncComponent(() => import('./raw.vue'));
|
||||||
|
|
||||||
|
const CTX_USER = getServerContext('user');
|
||||||
|
|
||||||
const props = withDefaults(defineProps<{
|
const props = withDefaults(defineProps<{
|
||||||
acct: string;
|
acct: string;
|
||||||
page?: string;
|
page?: string;
|
||||||
|
@ -61,13 +64,24 @@ const props = withDefaults(defineProps<{
|
||||||
|
|
||||||
const tab = ref(props.page);
|
const tab = ref(props.page);
|
||||||
|
|
||||||
const user = ref<null | Misskey.entities.UserDetailed>(null);
|
const user = ref<null | Misskey.entities.UserDetailed>(CTX_USER);
|
||||||
const error = ref<any>(null);
|
const error = ref<any>(null);
|
||||||
|
|
||||||
function fetchUser(): void {
|
function fetchUser(): void {
|
||||||
if (props.acct == null) return;
|
if (props.acct == null) return;
|
||||||
|
|
||||||
|
const { username, host } = Misskey.acct.parse(props.acct);
|
||||||
|
|
||||||
|
if (CTX_USER && CTX_USER.username === username && CTX_USER.host === host) {
|
||||||
|
user.value = CTX_USER;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
user.value = null;
|
user.value = null;
|
||||||
misskeyApi('users/show', Misskey.acct.parse(props.acct)).then(u => {
|
misskeyApi('users/show', {
|
||||||
|
username,
|
||||||
|
host,
|
||||||
|
}).then(u => {
|
||||||
user.value = u;
|
user.value = u;
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
error.value = err;
|
error.value = err;
|
||||||
|
|
Loading…
Reference in New Issue