summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/frontend/src/components/MkDrive.file.vue96
-rw-r--r--packages/frontend/src/pages/settings/drive-cleaner.vue167
-rw-r--r--packages/frontend/src/scripts/get-drive-file-menu.ts93
3 files changed, 162 insertions, 194 deletions
diff --git a/packages/frontend/src/components/MkDrive.file.vue b/packages/frontend/src/components/MkDrive.file.vue
index 8c17c0530a..ab408b5008 100644
--- a/packages/frontend/src/components/MkDrive.file.vue
+++ b/packages/frontend/src/components/MkDrive.file.vue
@@ -32,14 +32,14 @@
</template>
<script lang="ts" setup>
-import { computed, defineAsyncComponent, ref } from 'vue';
+import { computed, ref } from 'vue';
import * as Misskey from 'misskey-js';
-import copyToClipboard from '@/scripts/copy-to-clipboard';
import MkDriveFileThumbnail from '@/components/MkDriveFileThumbnail.vue';
import bytes from '@/filters/bytes';
import * as os from '@/os';
import { i18n } from '@/i18n';
import { $i } from '@/account';
+import { getDriveFileMenu } from '@/scripts/get-drive-file-menu';
const props = withDefaults(defineProps<{
file: Misskey.entities.DriveFile;
@@ -60,48 +60,16 @@ const isDragging = ref(false);
const title = computed(() => `${props.file.name}\n${props.file.type} ${bytes(props.file.size)}`);
-function getMenu() {
- return [{
- text: i18n.ts.rename,
- icon: 'ti ti-forms',
- action: rename,
- }, {
- text: props.file.isSensitive ? i18n.ts.unmarkAsSensitive : i18n.ts.markAsSensitive,
- icon: props.file.isSensitive ? 'ti ti-eye' : 'ti ti-eye-off',
- action: toggleSensitive,
- }, {
- text: i18n.ts.describeFile,
- icon: 'ti ti-text-caption',
- action: describe,
- }, null, {
- text: i18n.ts.copyUrl,
- icon: 'ti ti-link',
- action: copyUrl,
- }, {
- type: 'a',
- href: props.file.url,
- target: '_blank',
- text: i18n.ts.download,
- icon: 'ti ti-download',
- download: props.file.name,
- }, null, {
- text: i18n.ts.delete,
- icon: 'ti ti-trash',
- danger: true,
- action: deleteFile,
- }];
-}
-
function onClick(ev: MouseEvent) {
if (props.selectMode) {
emit('chosen', props.file);
} else {
- os.popupMenu(getMenu(), (ev.currentTarget ?? ev.target ?? undefined) as HTMLElement | undefined);
+ os.popupMenu(getDriveFileMenu(props.file), (ev.currentTarget ?? ev.target ?? undefined) as HTMLElement | undefined);
}
}
function onContextmenu(ev: MouseEvent) {
- os.contextMenu(getMenu(), ev);
+ os.contextMenu(getDriveFileMenu(props.file), ev);
}
function onDragstart(ev: DragEvent) {
@@ -118,62 +86,6 @@ function onDragend() {
isDragging.value = false;
emit('dragend');
}
-
-function rename() {
- os.inputText({
- title: i18n.ts.renameFile,
- placeholder: i18n.ts.inputNewFileName,
- default: props.file.name,
- }).then(({ canceled, result: name }) => {
- if (canceled) return;
- os.api('drive/files/update', {
- fileId: props.file.id,
- name: name,
- });
- });
-}
-
-function describe() {
- os.popup(defineAsyncComponent(() => import('@/components/MkFileCaptionEditWindow.vue')), {
- default: props.file.comment != null ? props.file.comment : '',
- file: props.file,
- }, {
- done: caption => {
- os.api('drive/files/update', {
- fileId: props.file.id,
- comment: caption.length === 0 ? null : caption,
- });
- },
- }, 'closed');
-}
-
-function toggleSensitive() {
- os.api('drive/files/update', {
- fileId: props.file.id,
- isSensitive: !props.file.isSensitive,
- });
-}
-
-function copyUrl() {
- copyToClipboard(props.file.url);
- os.success();
-}
-/*
-function addApp() {
- alert('not implemented yet');
-}
-*/
-async function deleteFile() {
- const { canceled } = await os.confirm({
- type: 'warning',
- text: i18n.t('driveFileDeleteConfirm', { name: props.file.name }),
- });
-
- if (canceled) return;
- os.api('drive/files/delete', {
- fileId: props.file.id,
- });
-}
</script>
<style lang="scss" scoped>
diff --git a/packages/frontend/src/pages/settings/drive-cleaner.vue b/packages/frontend/src/pages/settings/drive-cleaner.vue
index ce8ab214e4..2342280ca7 100644
--- a/packages/frontend/src/pages/settings/drive-cleaner.vue
+++ b/packages/frontend/src/pages/settings/drive-cleaner.vue
@@ -1,49 +1,44 @@
<template>
-<MkSelect v-model="sortModeSelect">
- <template #label>{{ i18n.ts.sort }}</template>
- <option v-for="x in sortOptions" :key="x.value" :value="x.value">{{ x.displayName }}</option>
-</MkSelect>
-<br>
-<div v-if="!fetching" class="_gap_m">
- <MkPagination v-slot="{items}" :pagination="pagination" class="driveitem list">
- <div
- v-for="file in items"
- :key="file.id"
- >
- <MkA
- v-tooltip.mfm="`${file.type}\n${bytes(file.size)}\n${dateString(file.createdAt)}`"
- class="_button"
- :to="`${file.url}`"
- behavior="browser"
- @contextmenu.stop="$event => onContextMenu($event, file.id)"
- >
- <div class="file">
- <div v-if="file.isSensitive" class="sensitive-label">{{ i18n.ts.sensitive }}</div>
- <MkDriveFileThumbnail class="thumbnail" :file="file" fit="contain"/>
- <div class="body">
- <div style="margin-bottom: 4px;">
- {{ file.name }}
- </div>
- <div>
- <span style="margin-right: 1em;">{{ file.type }}</span>
- <span>{{ bytes(file.size) }}</span>
- </div>
- <div>
- <span>{{ i18n.ts.registeredDate }}: <MkTime :time="file.createdAt" mode="detail"/></span>
- </div>
- <div v-if="sortModeSelect === 'sizeDesc'">
- <div class="uawsfosz">
- <div class="meter"><div :style="genUsageBar(file.size)"></div></div>
+<div class="_gaps">
+ <MkSelect v-model="sortModeSelect">
+ <template #label>{{ i18n.ts.sort }}</template>
+ <option v-for="x in sortOptions" :key="x.value" :value="x.value">{{ x.displayName }}</option>
+ </MkSelect>
+ <div v-if="!fetching">
+ <MkPagination v-slot="{items}" :pagination="pagination">
+ <div class="_gaps">
+ <div
+ v-for="file in items" :key="file.id"
+ class="_button"
+ @click="$event => onClick($event, file)"
+ @contextmenu.stop="$event => onContextMenu($event, file)"
+ >
+ <div :class="$style.file">
+ <div v-if="file.isSensitive" class="sensitive-label">{{ i18n.ts.sensitive }}</div>
+ <MkDriveFileThumbnail :class="$style.fileThumbnail" :file="file" fit="contain"/>
+ <div :class="$style.fileBody">
+ <div style="margin-bottom: 4px;">
+ {{ file.name }}
+ </div>
+ <div>
+ <span style="margin-right: 1em;">{{ file.type }}</span>
+ <span>{{ bytes(file.size) }}</span>
+ </div>
+ <div>
+ <span>{{ i18n.ts.registeredDate }}: <MkTime :time="file.createdAt" mode="detail"/></span>
+ </div>
+ <div v-if="sortModeSelect === 'sizeDesc'">
+ <div :class="$style.meter"><div :class="$style.meterValue" :style="genUsageBar(file.size)"></div></div>
</div>
</div>
</div>
</div>
- </MkA>
- </div>
- </MkPagination>
-</div>
-<div v-else class="gap_m">
- {{ i18n.ts.checking }} <MkEllipsis/>
+ </div>
+ </MkPagination>
+ </div>
+ <div v-else>
+ <MkLoading/>
+ </div>
</div>
</template>
@@ -58,6 +53,7 @@ import bytes from '@/filters/bytes';
import { dateString } from '@/filters/date';
import { definePageMetadata } from '@/scripts/page-metadata';
import MkSelect from '@/components/MkSelect.vue';
+import { getDriveFileMenu } from '@/scripts/get-drive-file-menu';
let sortMode = '+size';
const pagination = {
@@ -78,27 +74,22 @@ const sortModeSelect = ref('sizeDesc');
fetchDriveInfo();
-watch(fetching, () => {
- if (fetching.value) {
- fetchDriveInfo();
- }
-});
-
watch(sortModeSelect, () => {
switch (sortModeSelect.value) {
case 'sizeDesc':
sortMode = '+size';
- fetching.value = true;
+ fetchDriveInfo();
break;
case 'createdAtAsc':
sortMode = '-createdAt';
- fetching.value = true;
+ fetchDriveInfo();
break;
}
});
function fetchDriveInfo(): void {
+ fetching.value = true;
os.api('drive').then(info => {
capacity.value = info.capacity;
usage.value = info.usage;
@@ -113,30 +104,12 @@ function genUsageBar(fsize: number): object {
};
}
-function onContextMenu(ev: MouseEvent, fileId: string): void {
- const target = ev.target as HTMLElement;
- const items = [
- {
- text: i18n.ts.delete,
- icon: 'ti ti-trash-x',
- danger: true,
- action: async (): Promise<void> => {
- const res = await os.confirm({
- type: 'warning',
- title: i18n.ts.delete,
- text: i18n.ts.deleteConfirm,
- });
- if (!res.canceled) {
- await os.apiWithDialog('drive/files/delete', { fileId: fileId });
- fetching.value = true;
- }
- },
- },
- ];
- ev.preventDefault();
- os.popupMenu(items, target, {
- viaKeyboard: false,
- });
+function onClick(ev: MouseEvent, file) {
+ os.popupMenu(getDriveFileMenu(file), (ev.currentTarget ?? ev.target ?? undefined) as HTMLElement | undefined);
+}
+
+function onContextMenu(ev: MouseEvent, file): void {
+ os.contextMenu(getDriveFileMenu(file), ev);
}
definePageMetadata({
@@ -145,49 +118,39 @@ definePageMetadata({
});
</script>
-<style lang="scss" scoped>
-
-@use "sass:math";
-
+<style lang="scss" module>
.file {
display: flex;
width: 100%;
box-sizing: border-box;
text-align: left;
align-items: center;
- margin-bottom: 16px;
&:hover {
color: var(--accent);
}
+}
- > .thumbnail {
- width: 128px;
- height: 128px;
- }
-
- > .body {
- margin-left: 0.3em;
- padding: 8px;
- flex: 1;
+.fileThumbnail {
+ width: 100px;
+ height: 100px;
+}
- @media (max-width: 500px) {
- font-size: 14px;
- }
- }
+.fileBody {
+ margin-left: 0.3em;
+ padding: 8px;
+ flex: 1;
}
-.uawsfosz {
- > .meter {
- $size: 12px;
- background: rgba(0, 0, 0, 0.1);
- border-radius: math.div($size, 2);
- overflow: hidden;
+.meter {
+ margin-top: 8px;
+ height: 12px;
+ background: rgba(0, 0, 0, 0.1);
+ overflow: clip;
+ border-radius: 999px;
+}
- > div {
- height: $size;
- border-radius: math.div($size, 2);
- }
- }
+.meterValue {
+ height: 100%;
}
</style>
diff --git a/packages/frontend/src/scripts/get-drive-file-menu.ts b/packages/frontend/src/scripts/get-drive-file-menu.ts
new file mode 100644
index 0000000000..56ab516038
--- /dev/null
+++ b/packages/frontend/src/scripts/get-drive-file-menu.ts
@@ -0,0 +1,93 @@
+import * as Misskey from 'misskey-js';
+import { defineAsyncComponent } from 'vue';
+import { i18n } from '@/i18n';
+import copyToClipboard from '@/scripts/copy-to-clipboard';
+import * as os from '@/os';
+
+function rename(file: Misskey.entities.DriveFile) {
+ os.inputText({
+ title: i18n.ts.renameFile,
+ placeholder: i18n.ts.inputNewFileName,
+ default: file.name,
+ }).then(({ canceled, result: name }) => {
+ if (canceled) return;
+ os.api('drive/files/update', {
+ fileId: file.id,
+ name: name,
+ });
+ });
+}
+
+function describe(file: Misskey.entities.DriveFile) {
+ os.popup(defineAsyncComponent(() => import('@/components/MkFileCaptionEditWindow.vue')), {
+ default: file.comment != null ? file.comment : '',
+ file: file,
+ }, {
+ done: caption => {
+ os.api('drive/files/update', {
+ fileId: file.id,
+ comment: caption.length === 0 ? null : caption,
+ });
+ },
+ }, 'closed');
+}
+
+function toggleSensitive(file: Misskey.entities.DriveFile) {
+ os.api('drive/files/update', {
+ fileId: file.id,
+ isSensitive: !file.isSensitive,
+ });
+}
+
+function copyUrl(file: Misskey.entities.DriveFile) {
+ copyToClipboard(file.url);
+ os.success();
+}
+/*
+function addApp() {
+ alert('not implemented yet');
+}
+*/
+async function deleteFile(file: Misskey.entities.DriveFile) {
+ const { canceled } = await os.confirm({
+ type: 'warning',
+ text: i18n.t('driveFileDeleteConfirm', { name: file.name }),
+ });
+
+ if (canceled) return;
+ os.api('drive/files/delete', {
+ fileId: file.id,
+ });
+}
+
+export function getDriveFileMenu(file: Misskey.entities.DriveFile) {
+ return [{
+ text: i18n.ts.rename,
+ icon: 'ti ti-forms',
+ action: rename,
+ }, {
+ text: file.isSensitive ? i18n.ts.unmarkAsSensitive : i18n.ts.markAsSensitive,
+ icon: file.isSensitive ? 'ti ti-eye' : 'ti ti-eye-off',
+ action: toggleSensitive,
+ }, {
+ text: i18n.ts.describeFile,
+ icon: 'ti ti-text-caption',
+ action: describe,
+ }, null, {
+ text: i18n.ts.copyUrl,
+ icon: 'ti ti-link',
+ action: copyUrl,
+ }, {
+ type: 'a',
+ href: file.url,
+ target: '_blank',
+ text: i18n.ts.download,
+ icon: 'ti ti-download',
+ download: file.name,
+ }, null, {
+ text: i18n.ts.delete,
+ icon: 'ti ti-trash',
+ danger: true,
+ action: deleteFile,
+ }];
+}