投稿フォームでどこからでもチャンネルに投げられるようにしたい

This commit is contained in:
FruitRiin 2023-12-16 12:57:53 +09:00
parent 272dc208b4
commit 20e4c6b01e
2 changed files with 51 additions and 16 deletions

View File

@ -19,20 +19,20 @@ SPDX-License-Identifier: AGPL-3.0-only
</button> </button>
</div> </div>
<div :class="$style.headerRight"> <div :class="$style.headerRight">
<template v-if="!(channel != null && fixed)"> <template v-if="!(postChannel != null && fixed)">
<button v-if="channel == null" ref="visibilityButton" v-click-anime v-tooltip="i18n.ts.visibility" :class="['_button', $style.headerRightItem, $style.visibility]" @click="setVisibility"> <button v-if="postChannel == null" ref="visibilityButton" v-click-anime v-tooltip="i18n.ts.visibility" :class="['_button', $style.headerRightItem, $style.visibility]" @click="setVisibility">
<span v-if="visibility === 'public'"><i class="ti ti-world"></i></span> <span v-if="visibility === 'public'"><i class="ti ti-world"></i></span>
<span v-if="visibility === 'home'"><i class="ti ti-home"></i></span> <span v-if="visibility === 'home'"><i class="ti ti-home"></i></span>
<span v-if="visibility === 'followers'"><i class="ti ti-lock"></i></span> <span v-if="visibility === 'followers'"><i class="ti ti-lock"></i></span>
<span v-if="visibility === 'specified'"><i class="ti ti-mail"></i></span> <span v-if="visibility === 'specified'"><i class="ti ti-mail"></i></span>
<span :class="$style.headerRightButtonText">{{ i18n.ts._visibility[visibility] }}</span> <span :class="$style.headerRightButtonText">{{ i18n.ts._visibility[visibility] }}</span>
</button> </button>
<button v-else class="_button" :class="[$style.headerRightItem, $style.visibility]" disabled> <button v-else v-tooltip="i18n.ts.visibility" v-click-anime class="_button" :class="[$style.headerRightItem, $style.visibility]" @click="setVisibility">
<span><i class="ti ti-device-tv"></i></span> <span><i class="ti ti-device-tv"></i></span>
<span :class="$style.headerRightButtonText">{{ channel.name }}</span> <span :class="$style.headerRightButtonText">{{ postChannel.name }}</span>
</button> </button>
</template> </template>
<button v-click-anime v-tooltip="i18n.ts._visibility.disableFederation" class="_button" :class="[$style.headerRightItem, { [$style.danger]: localOnly }]" :disabled="channel != null || visibility === 'specified'" @click="toggleLocalOnly"> <button v-click-anime v-tooltip="i18n.ts._visibility.disableFederation" class="_button" :class="[$style.headerRightItem, { [$style.danger]: localOnly }]" :disabled="postChannel != null || visibility === 'specified'" @click="toggleLocalOnly">
<span v-if="!localOnly"><i class="ti ti-rocket"></i></span> <span v-if="!localOnly"><i class="ti ti-rocket"></i></span>
<span v-else><i class="ti ti-rocket-off"></i></span> <span v-else><i class="ti ti-rocket-off"></i></span>
</button> </button>
@ -128,6 +128,8 @@ import { emojiPicker } from '@/scripts/emoji-picker.js';
const modal = inject('modal'); const modal = inject('modal');
const props = withDefaults(defineProps<{ const props = withDefaults(defineProps<{
reply?: Misskey.entities.Note; reply?: Misskey.entities.Note;
renote?: Misskey.entities.Note; renote?: Misskey.entities.Note;
@ -152,6 +154,8 @@ const props = withDefaults(defineProps<{
mock: false, mock: false,
}); });
let postChannel = ref(props.channel)
provide('mock', props.mock); provide('mock', props.mock);
const emit = defineEmits<{ const emit = defineEmits<{
@ -199,7 +203,7 @@ const showingOptions = ref(false);
const textAreaReadOnly = ref(false); const textAreaReadOnly = ref(false);
const draftKey = computed((): string => { const draftKey = computed((): string => {
let key = props.channel ? `channel:${props.channel.id}` : ''; let key = postChannel.value ? `channel:${postChannel.value.id}` : '';
if (props.renote) { if (props.renote) {
key += `renote:${props.renote.id}`; key += `renote:${props.renote.id}`;
@ -217,7 +221,7 @@ const placeholder = computed((): string => {
return i18n.ts._postForm.quotePlaceholder; return i18n.ts._postForm.quotePlaceholder;
} else if (props.reply) { } else if (props.reply) {
return i18n.ts._postForm.replyPlaceholder; return i18n.ts._postForm.replyPlaceholder;
} else if (props.channel) { } else if (postChannel.value) {
return i18n.ts._postForm.channelPlaceholder; return i18n.ts._postForm.channelPlaceholder;
} else { } else {
const xs = [ const xs = [
@ -306,7 +310,7 @@ if ($i?.isSilenced && visibility.value === 'public') {
visibility.value = 'home'; visibility.value = 'home';
} }
if (props.channel) { if (postChannel.value) {
visibility.value = 'public'; visibility.value = 'public';
localOnly.value = true; // TODO: localOnly.value = true; // TODO:
} }
@ -447,12 +451,6 @@ function upload(file: File, name?: string): void {
} }
function setVisibility() { function setVisibility() {
if (props.channel) {
visibility.value = 'public';
localOnly.value = true; // TODO:
return;
}
os.popup(defineAsyncComponent(() => import('@/components/MkVisibilityPicker.vue')), { os.popup(defineAsyncComponent(() => import('@/components/MkVisibilityPicker.vue')), {
currentVisibility: visibility.value, currentVisibility: visibility.value,
isSilenced: $i?.isSilenced, isSilenced: $i?.isSilenced,
@ -465,11 +463,16 @@ function setVisibility() {
defaultStore.set('visibility', visibility.value); defaultStore.set('visibility', visibility.value);
} }
}, },
changeChannel: channel => {
postChannel.value = channel;
visibility.value = 'public';
localOnly.value = true;
}
}, 'closed'); }, 'closed');
} }
async function toggleLocalOnly() { async function toggleLocalOnly() {
if (props.channel) { if (postChannel.value) {
visibility.value = 'public'; visibility.value = 'public';
localOnly.value = true; // TODO: localOnly.value = true; // TODO:
return; return;
@ -736,7 +739,7 @@ async function post(ev?: MouseEvent) {
fileIds: files.value.length > 0 ? files.value.map(f => f.id) : undefined, fileIds: files.value.length > 0 ? files.value.map(f => f.id) : undefined,
replyId: props.reply ? props.reply.id : undefined, replyId: props.reply ? props.reply.id : undefined,
renoteId: props.renote ? props.renote.id : quoteId.value ? quoteId.value : undefined, renoteId: props.renote ? props.renote.id : quoteId.value ? quoteId.value : undefined,
channelId: props.channel ? props.channel.id : undefined, channelId: postChannel.value ? postChannel.value.id : undefined,
poll: poll.value, poll: poll.value,
cw: useCw.value ? cw.value ?? '' : null, cw: useCw.value ? cw.value ?? '' : null,
localOnly: localOnly.value, localOnly: localOnly.value,

View File

@ -37,6 +37,11 @@ SPDX-License-Identifier: AGPL-3.0-only
<span :class="$style.itemDescription">{{ i18n.ts._visibility.specifiedDescription }}</span> <span :class="$style.itemDescription">{{ i18n.ts._visibility.specifiedDescription }}</span>
</div> </div>
</button> </button>
<button v-for="channel in channels" :class="$style.item" class="_button" @click="chooseChannel(channel)" >
<div :class="$style.body" :style="{borderLeft: `solid 2px ${channel.color}`}">
<span :class="$style.itemTitle">{{ channel.name }}</span>
</div>
</button>
</div> </div>
</MkModal> </MkModal>
</template> </template>
@ -46,6 +51,7 @@ import { nextTick, shallowRef, ref } from 'vue';
import * as Misskey from 'misskey-js'; import * as Misskey from 'misskey-js';
import MkModal from '@/components/MkModal.vue'; import MkModal from '@/components/MkModal.vue';
import { i18n } from '@/i18n.js'; import { i18n } from '@/i18n.js';
import * as os from "@/os.js";
const modal = shallowRef<InstanceType<typeof MkModal>>(); const modal = shallowRef<InstanceType<typeof MkModal>>();
@ -64,6 +70,32 @@ const emit = defineEmits<{
const v = ref(props.currentVisibility); const v = ref(props.currentVisibility);
/**
* Visibility とチャンネルはそれぞれ独立だけど今のところはチャンネル投稿は連合なしだし公開範囲も変更できないようである
packages/frontend/src/components/MkPostForm.vue :475
if (props.channel) {
visibility.value = 'public';
localOnly.value = true; // TODO:
return;
}
*/
const channels = ref([]);
async function getChannel(){
const res = await os.api('channels/my-favorites', {
limit: 100,
});
channels.value.splice(0, 0, ...res);
}
getChannel();
async function chooseChannel(channel: string ){
emit("changeChannel", channel);
await nextTick();
if (modal.value) modal.value.close();
}
function choose(visibility: typeof Misskey.noteVisibilities[number]): void { function choose(visibility: typeof Misskey.noteVisibilities[number]): void {
v.value = visibility; v.value = visibility;
emit('changeVisibility', visibility); emit('changeVisibility', visibility);