misskey/packages/frontend/src/pages/settings/drive-cleaner.vue
2023-03-22 09:09:43 +09:00

157 lines
3.8 KiB
Vue

<template>
<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>
</div>
</MkPagination>
</div>
<div v-else>
<MkLoading/>
</div>
</div>
</template>
<script setup lang="ts">
import { computed, ref, watch } from 'vue';
import tinycolor from 'tinycolor2';
import * as os from '@/os';
import MkPagination from '@/components/MkPagination.vue';
import MkDriveFileThumbnail from '@/components/MkDriveFileThumbnail.vue';
import { i18n } from '@/i18n';
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 = ref('+size');
const pagination = {
endpoint: 'drive/files' as const,
limit: 10,
params: computed(() => ({ sort: sortMode.value })),
};
const sortOptions = [
{ value: 'sizeDesc', displayName: i18n.ts._drivecleaner.orderBySizeDesc },
{ value: 'createdAtAsc', displayName: i18n.ts._drivecleaner.orderByCreatedAtAsc },
];
const capacity = ref<number>(0);
const usage = ref<number>(0);
const fetching = ref(true);
const sortModeSelect = ref('sizeDesc');
fetchDriveInfo();
watch(sortModeSelect, () => {
switch (sortModeSelect.value) {
case 'sizeDesc':
sortMode.value = '+size';
fetchDriveInfo();
break;
case 'createdAtAsc':
sortMode.value = '-createdAt';
fetchDriveInfo();
break;
}
});
function fetchDriveInfo(): void {
fetching.value = true;
os.api('drive').then(info => {
capacity.value = info.capacity;
usage.value = info.usage;
fetching.value = false;
});
}
function genUsageBar(fsize: number): object {
return {
width: `${fsize / usage.value * 100}%`,
background: tinycolor({ h: 180 - (fsize / usage.value * 180), s: 0.7, l: 0.5 }),
};
}
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({
title: i18n.ts.drivecleaner,
icon: 'ti ti-trash',
});
</script>
<style lang="scss" module>
.file {
display: flex;
width: 100%;
box-sizing: border-box;
text-align: left;
align-items: center;
&:hover {
color: var(--accent);
}
}
.fileThumbnail {
width: 100px;
height: 100px;
}
.fileBody {
margin-left: 0.3em;
padding: 8px;
flex: 1;
}
.meter {
margin-top: 8px;
height: 12px;
background: rgba(0, 0, 0, 0.1);
overflow: clip;
border-radius: 999px;
}
.meterValue {
height: 100%;
}
</style>