Compare commits
No commits in common. "bff910c62014bfba012bd676280e734e16404932" and "3a874dd59d5c43bb8945cc58bafc6b4edab9a789" have entirely different histories.
bff910c620
...
3a874dd59d
|
@ -8535,6 +8535,10 @@ export interface Locale extends ILocale {
|
|||
* 入力ボックスの縁取り
|
||||
*/
|
||||
"inputBorder": string;
|
||||
/**
|
||||
* ドライブフォルダーの背景
|
||||
*/
|
||||
"driveFolderBg": string;
|
||||
/**
|
||||
* バッジ
|
||||
*/
|
||||
|
@ -11899,10 +11903,6 @@ export interface Locale extends ILocale {
|
|||
* アップロードされていないファイルがありますが、完了しますか?
|
||||
*/
|
||||
"doneConfirm": string;
|
||||
/**
|
||||
* アップロード可能な最大ファイルサイズは{x}です。
|
||||
*/
|
||||
"maxFileSizeIsX": ParameterizedString<"x">;
|
||||
};
|
||||
"_clientPerformanceIssueTip": {
|
||||
/**
|
||||
|
|
|
@ -2237,6 +2237,7 @@ _theme:
|
|||
buttonBg: "ボタンの背景"
|
||||
buttonHoverBg: "ボタンの背景 (ホバー)"
|
||||
inputBorder: "入力ボックスの縁取り"
|
||||
driveFolderBg: "ドライブフォルダーの背景"
|
||||
badge: "バッジ"
|
||||
messageBg: "チャットの背景"
|
||||
fgHighlighted: "強調された文字"
|
||||
|
@ -3183,7 +3184,6 @@ _uploader:
|
|||
savedXPercent: "{x}%節約"
|
||||
abortConfirm: "アップロードされていないファイルがありますが、中止しますか?"
|
||||
doneConfirm: "アップロードされていないファイルがありますが、完了しますか?"
|
||||
maxFileSizeIsX: "アップロード可能な最大ファイルサイズは{x}です。"
|
||||
|
||||
_clientPerformanceIssueTip:
|
||||
title: "バッテリー消費が多いと感じたら"
|
||||
|
|
|
@ -61,6 +61,7 @@
|
|||
switchOnFg: '@accent',
|
||||
inputBorder: 'rgba(255, 255, 255, 0.1)',
|
||||
inputBorderHover: 'rgba(255, 255, 255, 0.2)',
|
||||
driveFolderBg: ':alpha<0.3<@accent',
|
||||
badge: '#31b1ce',
|
||||
messageBg: '@bg',
|
||||
success: '#86b300',
|
||||
|
|
|
@ -61,6 +61,7 @@
|
|||
switchOnFg: '@fgOnAccent',
|
||||
inputBorder: 'rgba(0, 0, 0, 0.1)',
|
||||
inputBorderHover: 'rgba(0, 0, 0, 0.2)',
|
||||
driveFolderBg: ':alpha<0.3<@accent',
|
||||
badge: '#31b1ce',
|
||||
messageBg: '@bg',
|
||||
success: '#86b300',
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
navIndicator: '@accent',
|
||||
buttonGradateA: '@accent',
|
||||
buttonGradateB: ':hue<-20<@accent',
|
||||
driveFolderBg: ':alpha<0.3<@accent',
|
||||
fgHighlighted: ':lighten<3<@fg',
|
||||
panelHeaderBg: ':lighten<3<@panel',
|
||||
panelHeaderFg: '@fg',
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
inputBorder: 'rgba(255, 255, 255, 0.1)',
|
||||
panelBorder: '" solid 1px var(--MI_THEME-divider)',
|
||||
navIndicator: '@indicator',
|
||||
driveFolderBg: ':alpha<0.3<@accent',
|
||||
fgHighlighted: ':lighten<3<@fg',
|
||||
panelHeaderBg: ':lighten<3<@panel',
|
||||
panelHeaderFg: '@fg',
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
panelBorder: '" solid 1px var(--MI_THEME-divider)',
|
||||
navIndicator: '@indicator',
|
||||
buttonHoverBg: '#0000001a',
|
||||
driveFolderBg: ':alpha<0.3<@accent',
|
||||
fgHighlighted: ':lighten<3<@fg',
|
||||
panelHeaderBg: ':lighten<3<@panel',
|
||||
panelHeaderFg: '@fg',
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
inputBorderHover: 'rgba(0, 0, 0, 0.2)',
|
||||
panelBorder: '" solid 1px var(--MI_THEME-divider)',
|
||||
navIndicator: '@accent',
|
||||
driveFolderBg: ':alpha<0.3<@accent',
|
||||
fgHighlighted: ':darken<3<@fg',
|
||||
fgOnWhite: '@accent',
|
||||
panelHeaderBg: ':lighten<3<@panel',
|
||||
|
|
|
@ -8,6 +8,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
:class="[$style.root, { [$style.isSelected]: isSelected }]"
|
||||
draggable="true"
|
||||
:title="title"
|
||||
@click="onClick"
|
||||
@contextmenu.stop="onContextmenu"
|
||||
@dragstart="onDragstart"
|
||||
@dragend="onDragend"
|
||||
|
@ -45,17 +46,24 @@ import * as os from '@/os.js';
|
|||
import { i18n } from '@/i18n.js';
|
||||
import { $i } from '@/i.js';
|
||||
import { getDriveFileMenu } from '@/utility/get-drive-file-menu.js';
|
||||
import { deviceKind } from '@/utility/device-kind.js';
|
||||
import { useRouter } from '@/router.js';
|
||||
import { setDragData } from '@/drag-and-drop.js';
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
file: Misskey.entities.DriveFile;
|
||||
folder: Misskey.entities.DriveFolder | null;
|
||||
isSelected?: boolean;
|
||||
selectMode?: boolean;
|
||||
}>(), {
|
||||
isSelected: false,
|
||||
selectMode: false,
|
||||
});
|
||||
|
||||
const emit = defineEmits<{
|
||||
(ev: 'chosen', r: Misskey.entities.DriveFile): void;
|
||||
(ev: 'dragstart', dragEvent: DragEvent): void;
|
||||
(ev: 'dragend'): void;
|
||||
}>();
|
||||
|
@ -64,6 +72,18 @@ const isDragging = ref(false);
|
|||
|
||||
const title = computed(() => `${props.file.name}\n${props.file.type} ${bytes(props.file.size)}`);
|
||||
|
||||
function onClick(ev: MouseEvent) {
|
||||
if (props.selectMode) {
|
||||
emit('chosen', props.file);
|
||||
} else {
|
||||
if (deviceKind === 'desktop') {
|
||||
router.push(`/my/drive/file/${props.file.id}`);
|
||||
} else {
|
||||
os.popupMenu(getDriveFileMenu(props.file, props.folder), (ev.currentTarget ?? ev.target ?? undefined) as HTMLElement | undefined);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onContextmenu(ev: MouseEvent) {
|
||||
os.contextMenu(getDriveFileMenu(props.file, props.folder), ev);
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
@dragend="onDragend"
|
||||
>
|
||||
<svg :class="[$style.shape]" viewBox="0 0 200 150" preserveAspectRatio="none">
|
||||
<path d="M190,25C195.523,25 200,29.477 200,35C200,58.415 200,116.585 200,140C200,145.523 195.523,150 190,150C155.86,150 44.14,150 10,150C4.477,150 0,145.523 0,140C0,112.727 0,37.273 0,10C0,4.477 4.477,0 10,-0C26.642,0 59.332,0 70.858,0C73.51,-0 76.054,1.054 77.929,2.929C82.74,7.74 92.26,17.26 97.071,22.071C98.946,23.946 101.49,25 104.142,25C118.808,25 168.535,25 190,25Z" style="fill:var(--MI_THEME-accentedBg);"/>
|
||||
<path d="M190,25C195.523,25 200,29.477 200,35C200,58.415 200,116.585 200,140C200,145.523 195.523,150 190,150C155.86,150 44.14,150 10,150C4.477,150 0,145.523 0,140C0,112.727 0,37.273 0,10C0,4.477 4.477,0 10,-0C26.642,0 59.332,0 70.858,0C73.51,-0 76.054,1.054 77.929,2.929C82.74,7.74 92.26,17.26 97.071,22.071C98.946,23.946 101.49,25 104.142,25C118.808,25 168.535,25 190,25Z" style="fill:var(--MI_THEME-driveFolderBg);"/>
|
||||
</svg>
|
||||
<div :class="$style.name">{{ folder.name }}</div>
|
||||
<div v-if="prefer.s.uploadFolder == folder.id" :class="$style.upload">
|
||||
|
|
|
@ -60,58 +60,60 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
@drop.prevent.stop="onDrop"
|
||||
@contextmenu.stop="onContextmenu"
|
||||
>
|
||||
<div v-if="!store.r.readDriveTip.value" style="padding: 8px;">
|
||||
<MkInfo closable @close="closeTip()"><div v-html="i18n.ts.driveAboutTip"></div></MkInfo>
|
||||
</div>
|
||||
|
||||
<div :class="$style.folders">
|
||||
<XFolder
|
||||
v-for="(f, i) in foldersPaginator.items.value"
|
||||
:key="f.id"
|
||||
v-anim="i"
|
||||
:class="$style.folder"
|
||||
:folder="f"
|
||||
:selectMode="select === 'folder'"
|
||||
:isSelected="selectedFolders.some(x => x.id === f.id)"
|
||||
@chosen="chooseFolder"
|
||||
@unchose="unchoseFolder"
|
||||
@click="cd(f)"
|
||||
@upload="onUploadRequested"
|
||||
@dragstart="isDragSource = true"
|
||||
@dragend="isDragSource = false"
|
||||
/>
|
||||
</div>
|
||||
<MkButton v-if="foldersPaginator.canFetchOlder.value" primary rounded @click="foldersPaginator.fetchOlder()">{{ i18n.ts.loadMore }}</MkButton>
|
||||
|
||||
<MkStickyContainer v-for="(item, i) in filesTimeline" :key="`${item.date.getFullYear()}/${item.date.getMonth() + 1}`">
|
||||
<template #header>
|
||||
<div :class="$style.date">
|
||||
<span><i class="ti ti-chevron-down"></i> {{ item.date.getFullYear() }}/{{ item.date.getMonth() + 1 }}</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<TransitionGroup
|
||||
tag="div"
|
||||
:enterActiveClass="prefer.s.animation ? $style.transition_files_enterActive : ''"
|
||||
:leaveActiveClass="prefer.s.animation ? $style.transition_files_leaveActive : ''"
|
||||
:enterFromClass="prefer.s.animation ? $style.transition_files_enterFrom : ''"
|
||||
:leaveToClass="prefer.s.animation ? $style.transition_files_leaveTo : ''"
|
||||
:moveClass="prefer.s.animation ? $style.transition_files_move : ''"
|
||||
:class="$style.files"
|
||||
>
|
||||
<XFile
|
||||
v-for="file in item.items" :key="file.id"
|
||||
:class="$style.file"
|
||||
:file="file"
|
||||
:folder="folder"
|
||||
:isSelected="selectedFiles.some(x => x.id === file.id)"
|
||||
@click="onFileClick($event, file)"
|
||||
@dragstart="onFileDragstart(file, $event)"
|
||||
<MkInfo v-if="!store.r.readDriveTip.value" closable @close="closeTip()"><div v-html="i18n.ts.driveAboutTip"></div></MkInfo>
|
||||
<div v-show="foldersPaginator.items.value.length > 0">
|
||||
<div :class="$style.folders">
|
||||
<XFolder
|
||||
v-for="(f, i) in foldersPaginator.items.value"
|
||||
:key="f.id"
|
||||
v-anim="i"
|
||||
:class="$style.folder"
|
||||
:folder="f"
|
||||
:selectMode="select === 'folder'"
|
||||
:isSelected="selectedFolders.some(x => x.id === f.id)"
|
||||
@chosen="chooseFolder"
|
||||
@unchose="unchoseFolder"
|
||||
@click="cd(f)"
|
||||
@upload="onUploadRequested"
|
||||
@dragstart="isDragSource = true"
|
||||
@dragend="isDragSource = false"
|
||||
/>
|
||||
</TransitionGroup>
|
||||
</MkStickyContainer>
|
||||
<MkButton v-show="filesPaginator.canFetchOlder.value" :class="$style.loadMore" primary rounded @click="filesPaginator.fetchOlder()">{{ i18n.ts.loadMore }}</MkButton>
|
||||
</div>
|
||||
<MkButton v-if="foldersPaginator.canFetchOlder.value" primary rounded @click="foldersPaginator.fetchOlder()">{{ i18n.ts.loadMore }}</MkButton>
|
||||
</div>
|
||||
|
||||
<div v-show="filesPaginator.items.value.length > 0">
|
||||
<MkStickyContainer v-for="(item, i) in filesTimeline" :key="`${item.date.getFullYear()}/${item.date.getMonth() + 1}`">
|
||||
<template #header>
|
||||
<div :class="$style.date">
|
||||
<span><i class="ti ti-chevron-down"></i> {{ item.date.getFullYear() }}/{{ item.date.getMonth() + 1 }}</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<TransitionGroup
|
||||
tag="div"
|
||||
:enterActiveClass="prefer.s.animation ? $style.transition_files_enterActive : ''"
|
||||
:leaveActiveClass="prefer.s.animation ? $style.transition_files_leaveActive : ''"
|
||||
:enterFromClass="prefer.s.animation ? $style.transition_files_enterFrom : ''"
|
||||
:leaveToClass="prefer.s.animation ? $style.transition_files_leaveTo : ''"
|
||||
:moveClass="prefer.s.animation ? $style.transition_files_move : ''"
|
||||
:class="$style.files"
|
||||
>
|
||||
<XFile
|
||||
v-for="file in item.items" :key="file.id"
|
||||
:class="$style.file"
|
||||
:file="file"
|
||||
:folder="folder"
|
||||
:selectMode="select === 'file' || isEditMode"
|
||||
:isSelected="selectedFiles.some(x => x.id === file.id)"
|
||||
@chosen="onChooseFile"
|
||||
@dragstart="onFileDragstart(file, $event)"
|
||||
@dragend="isDragSource = false"
|
||||
/>
|
||||
</TransitionGroup>
|
||||
</MkStickyContainer>
|
||||
<MkButton v-show="filesPaginator.canFetchOlder.value" :class="$style.loadMore" primary rounded @click="filesPaginator.fetchOlder()">{{ i18n.ts.loadMore }}</MkButton>
|
||||
</div>
|
||||
|
||||
<div v-if="filesPaginator.items.value.length == 0 && foldersPaginator.items.value.length == 0 && !fetching" :class="$style.empty">
|
||||
<div v-if="draghover">{{ i18n.ts['empty-draghover'] }}</div>
|
||||
|
@ -152,7 +154,6 @@ import { isSeparatorNeeded, getSeparatorInfo, makeDateGroupedTimelineComputedRef
|
|||
import { usePagination } from '@/composables/use-pagination.js';
|
||||
import { globalEvents, useGlobalEvent } from '@/events.js';
|
||||
import { checkDragDataType, getDragData, setDragData } from '@/drag-and-drop.js';
|
||||
import { getDriveFileMenu } from '@/utility/get-drive-file-menu.js';
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
initialFolder?: Misskey.entities.DriveFolder['id'] | null;
|
||||
|
@ -457,38 +458,30 @@ function deleteFolder(folderToDelete: Misskey.entities.DriveFolder) {
|
|||
});
|
||||
}
|
||||
|
||||
function onFileClick(ev: MouseEvent, file: Misskey.entities.DriveFile) {
|
||||
if (ev.shiftKey) {
|
||||
isEditMode.value = true;
|
||||
function onChooseFile(file: Misskey.entities.DriveFile) {
|
||||
const isAlreadySelected = selectedFiles.value.some(f => f.id === file.id);
|
||||
|
||||
if (isEditMode.value) {
|
||||
if (isAlreadySelected) {
|
||||
selectedFiles.value = selectedFiles.value.filter(f => f.id !== file.id);
|
||||
} else {
|
||||
selectedFiles.value.push(file);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (props.select === 'file' || isEditMode.value) {
|
||||
const isAlreadySelected = selectedFiles.value.some(f => f.id === file.id);
|
||||
|
||||
if (isEditMode.value) {
|
||||
if (isAlreadySelected) {
|
||||
selectedFiles.value = selectedFiles.value.filter(f => f.id !== file.id);
|
||||
} else {
|
||||
selectedFiles.value.push(file);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (props.multiple) {
|
||||
if (isAlreadySelected) {
|
||||
selectedFiles.value = selectedFiles.value.filter(f => f.id !== file.id);
|
||||
} else {
|
||||
selectedFiles.value.push(file);
|
||||
}
|
||||
if (props.multiple) {
|
||||
if (isAlreadySelected) {
|
||||
selectedFiles.value = selectedFiles.value.filter(f => f.id !== file.id);
|
||||
} else {
|
||||
if (isAlreadySelected) {
|
||||
//emit('selected', file);
|
||||
} else {
|
||||
selectedFiles.value = [file];
|
||||
}
|
||||
selectedFiles.value.push(file);
|
||||
}
|
||||
} else {
|
||||
os.popupMenu(getDriveFileMenu(file, folder.value), (ev.currentTarget ?? ev.target ?? undefined) as HTMLElement | undefined);
|
||||
if (isAlreadySelected) {
|
||||
//emit('selected', file);
|
||||
} else {
|
||||
selectedFiles.value = [file];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -823,14 +816,7 @@ onBeforeUnmount(() => {
|
|||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
|
||||
grid-gap: 12px;
|
||||
padding: 16px 32px;
|
||||
}
|
||||
|
||||
@container (max-width: 600px) {
|
||||
.folders,
|
||||
.files {
|
||||
padding: 16px;
|
||||
}
|
||||
padding: var(--MI-margin);
|
||||
}
|
||||
|
||||
.date {
|
||||
|
|
|
@ -15,57 +15,51 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<i class="ti ti-upload"></i> {{ i18n.tsx.uploadNFiles({ n: files.length }) }}
|
||||
</template>
|
||||
|
||||
<div :class="$style.root">
|
||||
<div :class="[$style.overallProgress, canRetry ? $style.overallProgressError : null]" :style="{ '--op': `${overallProgress}%` }"></div>
|
||||
|
||||
<div :class="$style.main" class="_gaps_s">
|
||||
<div :class="$style.items" class="_gaps_s">
|
||||
<div
|
||||
v-for="ctx in items"
|
||||
:key="ctx.id"
|
||||
v-panel
|
||||
:class="[$style.item, ctx.waiting ? $style.itemWaiting : null, ctx.uploaded ? $style.itemCompleted : null, ctx.uploadFailed ? $style.itemFailed : null]"
|
||||
:style="{ '--p': ctx.progress != null ? `${ctx.progress.value / ctx.progress.max * 100}%` : '0%' }"
|
||||
>
|
||||
<div :class="$style.itemInner">
|
||||
<div :class="$style.itemActionWrapper">
|
||||
<MkButton :iconOnly="true" rounded @click="showMenu($event, ctx)"><i class="ti ti-dots"></i></MkButton>
|
||||
<div :class="$style.root" class="_gaps_s">
|
||||
<div :class="$style.items" class="_gaps_s">
|
||||
<div
|
||||
v-for="ctx in items"
|
||||
:key="ctx.id"
|
||||
v-panel
|
||||
:class="[$style.item, ctx.waiting ? $style.itemWaiting : null, ctx.uploaded ? $style.itemCompleted : null, ctx.uploadFailed ? $style.itemFailed : null]"
|
||||
:style="{ '--p': ctx.progress != null ? `${ctx.progress.value / ctx.progress.max * 100}%` : '0%' }"
|
||||
>
|
||||
<div :class="$style.itemInner">
|
||||
<div>
|
||||
<MkButton :iconOnly="true" rounded @click="showMenu($event, ctx)"><i class="ti ti-dots"></i></MkButton>
|
||||
</div>
|
||||
<div :class="$style.itemThumbnail" :style="{ backgroundImage: `url(${ ctx.thumbnail })` }"></div>
|
||||
<div :class="$style.itemBody">
|
||||
<div>{{ ctx.name }}</div>
|
||||
<div :class="$style.itemInfo">
|
||||
<span>{{ ctx.file.type }}</span>
|
||||
<span>{{ bytes(ctx.file.size) }}</span>
|
||||
<span v-if="ctx.compressedSize">({{ i18n.tsx._uploader.compressedToX({ x: bytes(ctx.compressedSize) }) }} = {{ i18n.tsx._uploader.savedXPercent({ x: Math.round((1 - ctx.compressedSize / ctx.file.size) * 100) }) }})</span>
|
||||
</div>
|
||||
<div :class="$style.itemThumbnail" :style="{ backgroundImage: `url(${ ctx.thumbnail })` }"></div>
|
||||
<div :class="$style.itemBody">
|
||||
<div><MkCondensedLine :minScale="2 / 3">{{ ctx.name }}</MkCondensedLine></div>
|
||||
<div :class="$style.itemInfo">
|
||||
<span>{{ ctx.file.type }}</span>
|
||||
<span>{{ bytes(ctx.file.size) }}</span>
|
||||
<span v-if="ctx.compressedSize">({{ i18n.tsx._uploader.compressedToX({ x: bytes(ctx.compressedSize) }) }} = {{ i18n.tsx._uploader.savedXPercent({ x: Math.round((1 - ctx.compressedSize / ctx.file.size) * 100) }) }})</span>
|
||||
</div>
|
||||
<div>
|
||||
</div>
|
||||
</div>
|
||||
<div :class="$style.itemIconWrapper">
|
||||
<MkSystemIcon v-if="ctx.uploading" :class="$style.itemIcon" type="waiting"/>
|
||||
<MkSystemIcon v-else-if="ctx.uploaded" :class="$style.itemIcon" type="success"/>
|
||||
<MkSystemIcon v-else-if="ctx.uploadFailed" :class="$style.itemIcon" type="error"/>
|
||||
<div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<MkSystemIcon v-if="ctx.uploading" :class="$style.itemIcon" type="waiting"/>
|
||||
<MkSystemIcon v-else-if="ctx.uploaded" :class="$style.itemIcon" type="success"/>
|
||||
<MkSystemIcon v-else-if="ctx.uploadFailed" :class="$style.itemIcon" type="error"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<MkSelect
|
||||
v-if="items.length > 0"
|
||||
v-model="compressionLevel"
|
||||
:items="[
|
||||
{ value: 0, label: i18n.ts.none },
|
||||
{ value: 1, label: i18n.ts.low },
|
||||
{ value: 2, label: i18n.ts.middle },
|
||||
{ value: 3, label: i18n.ts.high },
|
||||
]"
|
||||
>
|
||||
<template #label>{{ i18n.ts.compress }}</template>
|
||||
</MkSelect>
|
||||
|
||||
<div>{{ i18n.tsx._uploader.maxFileSizeIsX({ x: $i.policies.maxFileSizeMb + 'MB' }) }}</div>
|
||||
</div>
|
||||
|
||||
<MkSelect
|
||||
v-if="items.length > 0"
|
||||
v-model="compressionLevel"
|
||||
:items="[
|
||||
{ value: 0, label: i18n.ts.none },
|
||||
{ value: 1, label: i18n.ts.low },
|
||||
{ value: 2, label: i18n.ts.middle },
|
||||
{ value: 3, label: i18n.ts.high },
|
||||
]"
|
||||
>
|
||||
<template #label>{{ i18n.ts.compress }}</template>
|
||||
</MkSelect>
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
|
@ -97,9 +91,6 @@ import MkSelect from '@/components/MkSelect.vue';
|
|||
import { isWebpSupported } from '@/utility/isWebpSupported.js';
|
||||
import { uploadFile } from '@/utility/drive.js';
|
||||
import * as os from '@/os.js';
|
||||
import { ensureSignin } from '@/i.js';
|
||||
|
||||
const $i = ensureSignin();
|
||||
|
||||
const COMPRESSION_SUPPORTED_TYPES = [
|
||||
'image/jpeg',
|
||||
|
@ -153,16 +144,6 @@ const firstUploadAttempted = ref(false);
|
|||
const isUploading = computed(() => items.value.some(item => item.uploading));
|
||||
const canRetry = computed(() => firstUploadAttempted.value && !items.value.some(item => item.uploading || item.waiting) && items.value.some(item => item.uploaded == null));
|
||||
const canDone = computed(() => items.value.some(item => item.uploaded != null));
|
||||
const overallProgress = computed(() => {
|
||||
const max = items.value.length;
|
||||
if (max === 0) return 0;
|
||||
const v = items.value.reduce((acc, item) => {
|
||||
if (item.uploaded) return acc + 1;
|
||||
if (item.progress) return acc + (item.progress.value / item.progress.max);
|
||||
return acc;
|
||||
}, 0);
|
||||
return Math.round((v / max) * 100);
|
||||
});
|
||||
|
||||
const compressionLevel = ref<0 | 1 | 2 | 3>(2);
|
||||
const compressionSettings = computed(() => {
|
||||
|
@ -338,25 +319,6 @@ onMounted(() => {
|
|||
|
||||
<style lang="scss" module>
|
||||
.root {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.overallProgress {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: var(--op);
|
||||
height: 4px;
|
||||
background: var(--MI_THEME-accent);
|
||||
border-radius: 0 999px 999px 0;
|
||||
transition: width 0.2s ease;
|
||||
|
||||
&.overallProgressError {
|
||||
background: var(--MI_THEME-warn);
|
||||
}
|
||||
}
|
||||
|
||||
.main {
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
|
@ -444,6 +406,12 @@ onMounted(() => {
|
|||
min-width: 0;
|
||||
}
|
||||
|
||||
@container (max-width: 500px) {
|
||||
.itemBody {
|
||||
font-size: 90%;
|
||||
}
|
||||
}
|
||||
|
||||
.itemInfo {
|
||||
opacity: 0.7;
|
||||
margin-top: 4px;
|
||||
|
@ -455,34 +423,4 @@ onMounted(() => {
|
|||
.itemIcon {
|
||||
width: 35px;
|
||||
}
|
||||
|
||||
@container (max-width: 500px) {
|
||||
.itemInner {
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.itemBody {
|
||||
font-size: 90%;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.itemActionWrapper {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
left: 8px;
|
||||
}
|
||||
|
||||
.itemInfo {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.itemIconWrapper {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
right: 8px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1247,12 +1247,6 @@ type DriveFilesFindRequest = operations['drive___files___find']['requestBody']['
|
|||
// @public (undocumented)
|
||||
type DriveFilesFindResponse = operations['drive___files___find']['responses']['200']['content']['application/json'];
|
||||
|
||||
// @public (undocumented)
|
||||
type DriveFilesMoveBulkRequest = operations['drive___files___move-bulk']['requestBody']['content']['application/json'];
|
||||
|
||||
// @public (undocumented)
|
||||
type DriveFilesMoveBulkResponse = operations['drive___files___move-bulk']['responses']['200']['content']['application/json'];
|
||||
|
||||
// @public (undocumented)
|
||||
type DriveFilesRequest = operations['drive___files']['requestBody']['content']['application/json'];
|
||||
|
||||
|
@ -1738,8 +1732,6 @@ declare namespace entities {
|
|||
DriveFilesFindResponse,
|
||||
DriveFilesFindByHashRequest,
|
||||
DriveFilesFindByHashResponse,
|
||||
DriveFilesMoveBulkRequest,
|
||||
DriveFilesMoveBulkResponse,
|
||||
DriveFilesShowRequest,
|
||||
DriveFilesShowResponse,
|
||||
DriveFilesUpdateRequest,
|
||||
|
|
|
@ -2073,17 +2073,6 @@ declare module '../api.js' {
|
|||
credential?: string | null,
|
||||
): Promise<SwitchCaseResponseType<E, P>>;
|
||||
|
||||
/**
|
||||
* No description provided.
|
||||
*
|
||||
* **Credential required**: *Yes* / **Permission**: *write:drive*
|
||||
*/
|
||||
request<E extends 'drive/files/move-bulk', P extends Endpoints[E]['req']>(
|
||||
endpoint: E,
|
||||
params: P,
|
||||
credential?: string | null,
|
||||
): Promise<SwitchCaseResponseType<E, P>>;
|
||||
|
||||
/**
|
||||
* Show the properties of a drive file.
|
||||
*
|
||||
|
|
|
@ -282,8 +282,6 @@ import type {
|
|||
DriveFilesFindResponse,
|
||||
DriveFilesFindByHashRequest,
|
||||
DriveFilesFindByHashResponse,
|
||||
DriveFilesMoveBulkRequest,
|
||||
DriveFilesMoveBulkResponse,
|
||||
DriveFilesShowRequest,
|
||||
DriveFilesShowResponse,
|
||||
DriveFilesUpdateRequest,
|
||||
|
@ -825,7 +823,6 @@ export type Endpoints = {
|
|||
'drive/files/delete': { req: DriveFilesDeleteRequest; res: EmptyResponse };
|
||||
'drive/files/find': { req: DriveFilesFindRequest; res: DriveFilesFindResponse };
|
||||
'drive/files/find-by-hash': { req: DriveFilesFindByHashRequest; res: DriveFilesFindByHashResponse };
|
||||
'drive/files/move-bulk': { req: DriveFilesMoveBulkRequest; res: DriveFilesMoveBulkResponse };
|
||||
'drive/files/show': { req: DriveFilesShowRequest; res: DriveFilesShowResponse };
|
||||
'drive/files/update': { req: DriveFilesUpdateRequest; res: DriveFilesUpdateResponse };
|
||||
'drive/files/upload-from-url': { req: DriveFilesUploadFromUrlRequest; res: EmptyResponse };
|
||||
|
|
|
@ -285,8 +285,6 @@ export type DriveFilesFindRequest = operations['drive___files___find']['requestB
|
|||
export type DriveFilesFindResponse = operations['drive___files___find']['responses']['200']['content']['application/json'];
|
||||
export type DriveFilesFindByHashRequest = operations['drive___files___find-by-hash']['requestBody']['content']['application/json'];
|
||||
export type DriveFilesFindByHashResponse = operations['drive___files___find-by-hash']['responses']['200']['content']['application/json'];
|
||||
export type DriveFilesMoveBulkRequest = operations['drive___files___move-bulk']['requestBody']['content']['application/json'];
|
||||
export type DriveFilesMoveBulkResponse = operations['drive___files___move-bulk']['responses']['200']['content']['application/json'];
|
||||
export type DriveFilesShowRequest = operations['drive___files___show']['requestBody']['content']['application/json'];
|
||||
export type DriveFilesShowResponse = operations['drive___files___show']['responses']['200']['content']['application/json'];
|
||||
export type DriveFilesUpdateRequest = operations['drive___files___update']['requestBody']['content']['application/json'];
|
||||
|
|
|
@ -1799,15 +1799,6 @@ export type paths = {
|
|||
*/
|
||||
post: operations['drive___files___find-by-hash'];
|
||||
};
|
||||
'/drive/files/move-bulk': {
|
||||
/**
|
||||
* drive/files/move-bulk
|
||||
* @description No description provided.
|
||||
*
|
||||
* **Credential required**: *Yes* / **Permission**: *write:drive*
|
||||
*/
|
||||
post: operations['drive___files___move-bulk'];
|
||||
};
|
||||
'/drive/files/show': {
|
||||
/**
|
||||
* drive/files/show
|
||||
|
@ -16854,61 +16845,6 @@ export type operations = {
|
|||
};
|
||||
};
|
||||
};
|
||||
/**
|
||||
* drive/files/move-bulk
|
||||
* @description No description provided.
|
||||
*
|
||||
* **Credential required**: *Yes* / **Permission**: *write:drive*
|
||||
*/
|
||||
'drive___files___move-bulk': {
|
||||
requestBody: {
|
||||
content: {
|
||||
'application/json': {
|
||||
fileIds: string[];
|
||||
/** Format: misskey:id */
|
||||
folderId?: string | null;
|
||||
};
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
/** @description OK (with results) */
|
||||
200: {
|
||||
content: {
|
||||
'application/json': unknown;
|
||||
};
|
||||
};
|
||||
/** @description Client error */
|
||||
400: {
|
||||
content: {
|
||||
'application/json': components['schemas']['Error'];
|
||||
};
|
||||
};
|
||||
/** @description Authentication error */
|
||||
401: {
|
||||
content: {
|
||||
'application/json': components['schemas']['Error'];
|
||||
};
|
||||
};
|
||||
/** @description Forbidden error */
|
||||
403: {
|
||||
content: {
|
||||
'application/json': components['schemas']['Error'];
|
||||
};
|
||||
};
|
||||
/** @description I'm Ai */
|
||||
418: {
|
||||
content: {
|
||||
'application/json': components['schemas']['Error'];
|
||||
};
|
||||
};
|
||||
/** @description Internal server error */
|
||||
500: {
|
||||
content: {
|
||||
'application/json': components['schemas']['Error'];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
/**
|
||||
* drive/files/show
|
||||
* @description Show the properties of a drive file.
|
||||
|
|
Loading…
Reference in New Issue