This commit is contained in:
syuilo 2025-06-06 16:16:40 +09:00
parent c8d2b36ec3
commit 5db01c1c06
4 changed files with 37 additions and 6 deletions

View File

@ -73,7 +73,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<input v-show="withHashtags" ref="hashtagsInputEl" v-model="hashtags" :class="$style.hashtags" :placeholder="i18n.ts.hashtags" list="hashtags">
<XPostFormAttaches v-model="files" @detach="detachFile" @changeSensitive="updateFileSensitive" @changeName="updateFileName"/>
<div v-if="uploader.items.value.length > 0" style="padding: 12px;">
<MkUploaderItems :items="uploader.items.value" @showMenu="(item, ev) => uploader.showMenu(ev, item)"/>
<MkUploaderItems :items="uploader.items.value" @showMenu="(item, ev) => showPerUploadItemMenu(item, ev)" @showMenuViaContextmenu="(item, ev) => showPerUploadItemMenuViaContextmenu(item, ev)"/>
</div>
<MkPollEditor v-if="poll" v-model="poll" @destroyed="poll = null"/>
<MkNotePreview v-if="showPreview" :class="$style.preview" :text="text" :files="files" :poll="poll ?? undefined" :useCw="useCw" :cw="cw" :user="postAccount ?? $i"/>
@ -114,6 +114,7 @@ import type { ShallowRef } from 'vue';
import type { PostFormProps } from '@/types/post-form.js';
import type { MenuItem } from '@/types/menu.js';
import type { PollEditorModelValue } from '@/components/MkPollEditor.vue';
import type { UploaderItem } from '@/composables/use-uploader.js';
import MkNotePreview from '@/components/MkNotePreview.vue';
import XPostFormAttaches from '@/components/MkPostFormAttaches.vue';
import XTextCounter from '@/components/MkPostForm.TextCounter.vue';
@ -1072,6 +1073,16 @@ function openAccountMenu(ev: MouseEvent) {
}, ev);
}
function showPerUploadItemMenu(item: UploaderItem, ev: MouseEvent) {
const menu = uploader.getMenu(item);
os.popupMenu(menu, ev.currentTarget ?? ev.target);
}
function showPerUploadItemMenuViaContextmenu(item: UploaderItem, ev: MouseEvent) {
const menu = uploader.getMenu(item);
os.contextMenu(menu, ev);
}
onMounted(() => {
if (props.autofocus) {
focus();

View File

@ -23,7 +23,7 @@ SPDX-License-Identifier: AGPL-3.0-only
{{ i18n.ts._uploader.tip }}
</MkTip>
<MkUploaderItems :items="items" @showMenu="(item, ev) => uploader.showMenu(ev, item)"/>
<MkUploaderItems :items="items" @showMenu="(item, ev) => showPerItemMenu(item, ev)" @showMenuViaContextmenu="(item, ev) => showPerItemMenuViaContextmenu(item, ev)"/>
<div v-if="props.multiple">
<MkButton style="margin: auto;" :iconOnly="true" rounded @click="chooseFile($event)"><i class="ti ti-plus"></i></MkButton>
@ -52,7 +52,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<script lang="ts" setup>
import { computed, onMounted, ref, useTemplateRef, watch } from 'vue';
import * as Misskey from 'misskey-js';
import type { UploaderFeatures } from '@/composables/use-uploader.js';
import type { UploaderFeatures, UploaderItem } from '@/composables/use-uploader.js';
import MkModalWindow from '@/components/MkModalWindow.vue';
import { i18n } from '@/i18n.js';
import MkButton from '@/components/MkButton.vue';
@ -169,6 +169,16 @@ async function chooseFile(ev: MouseEvent) {
const newFiles = await os.chooseFileFromPc({ multiple: true });
uploader.addFiles(newFiles);
}
function showPerItemMenu(item: UploaderItem, ev: MouseEvent) {
const menu = uploader.getMenu(item);
os.popupMenu(menu, ev.currentTarget ?? ev.target);
}
function showPerItemMenuViaContextmenu(item: UploaderItem, ev: MouseEvent) {
const menu = uploader.getMenu(item);
os.contextMenu(menu, ev);
}
</script>
<style lang="scss" module>

View File

@ -11,6 +11,7 @@ SPDX-License-Identifier: AGPL-3.0-only
v-panel
:class="[$style.item, { [$style.itemWaiting]: item.preprocessing, [$style.itemCompleted]: item.uploaded, [$style.itemFailed]: item.uploadFailed }]"
:style="{ '--p': item.progress != null ? `${item.progress.value / item.progress.max * 100}%` : '0%' }"
@contextmenu.prevent.stop="onContextmenu(item, $event)"
>
<div :class="$style.itemInner">
<div :class="$style.itemActionWrapper">
@ -38,6 +39,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</template>
<script lang="ts" setup>
import { isLink } from '@@/js/is-link.js';
import type { UploaderItem } from '@/composables/use-uploader.js';
import { i18n } from '@/i18n.js';
import MkButton from '@/components/MkButton.vue';
@ -49,7 +51,15 @@ const props = defineProps<{
const emit = defineEmits<{
(ev: 'showMenu', item: UploaderItem, event: MouseEvent): void;
(ev: 'showMenuViaContextmenu', item: UploaderItem, event: MouseEvent): void;
}>();
function onContextmenu(item: UploaderItem, ev: MouseEvent) {
if (ev.target && isLink(ev.target as HTMLElement)) return;
if (window.getSelection()?.toString() !== '') return;
emit('showMenuViaContextmenu', item, ev);
}
</script>
<style lang="scss" module>

View File

@ -142,7 +142,7 @@ export function useUploader(options: {
items.value.splice(items.value.indexOf(item), 1);
}
function showMenu(ev: MouseEvent, item: UploaderItem) {
function getMenu(item: UploaderItem): MenuItem[] {
const menu: MenuItem[] = [];
menu.push({
@ -354,7 +354,7 @@ export function useUploader(options: {
});
}
os.popupMenu(menu, ev.currentTarget ?? ev.target);
return menu;
}
async function upload() { // エラーハンドリングなどを考慮してシーケンシャルにやる
@ -503,7 +503,7 @@ export function useUploader(options: {
removeItem,
abortAll,
upload,
showMenu,
getMenu,
uploading: computed(() => items.value.some(item => item.uploading)),
readyForUpload: computed(() => items.value.length > 0 && !items.value.some(item => item.uploading || item.preprocessing)),
};