Merge branch 'drive-api-combined'

Reviewed-on: FoundKeyGang/FoundKey#297
This commit is contained in:
Johann150 2023-03-13 19:30:24 +01:00
commit d6837814d9
Signed by untrusted user: Johann150
GPG key ID: 9EE6577A2A06F8F1
10 changed files with 241 additions and 234 deletions

View file

@ -104,6 +104,7 @@ import * as ep___clips_show from './endpoints/clips/show.js';
import * as ep___clips_update from './endpoints/clips/update.js'; import * as ep___clips_update from './endpoints/clips/update.js';
import * as ep___drive from './endpoints/drive.js'; import * as ep___drive from './endpoints/drive.js';
import * as ep___drive_files from './endpoints/drive/files.js'; import * as ep___drive_files from './endpoints/drive/files.js';
import * as ep___drive_show from './endpoints/drive/show.js';
import * as ep___drive_files_attachedNotes from './endpoints/drive/files/attached-notes.js'; import * as ep___drive_files_attachedNotes from './endpoints/drive/files/attached-notes.js';
import * as ep___drive_files_checkExistence from './endpoints/drive/files/check-existence.js'; import * as ep___drive_files_checkExistence from './endpoints/drive/files/check-existence.js';
import * as ep___drive_files_create from './endpoints/drive/files/create.js'; import * as ep___drive_files_create from './endpoints/drive/files/create.js';
@ -400,6 +401,7 @@ const eps = [
['clips/update', ep___clips_update], ['clips/update', ep___clips_update],
['drive', ep___drive], ['drive', ep___drive],
['drive/files', ep___drive_files], ['drive/files', ep___drive_files],
['drive/show', ep___drive_show],
['drive/files/attached-notes', ep___drive_files_attachedNotes], ['drive/files/attached-notes', ep___drive_files_attachedNotes],
['drive/files/check-existence', ep___drive_files_checkExistence], ['drive/files/check-existence', ep___drive_files_checkExistence],
['drive/files/create', ep___drive_files_create], ['drive/files/create', ep___drive_files_create],

View file

@ -0,0 +1,70 @@
import { DriveFiles, DriveFolders } from '@/models/index.js';
import define from '../../define.js';
import { makePaginationQuery } from '../../common/make-pagination-query.js';
export const meta = {
tags: ['drive'],
description: "Lists all folders and files in the authenticated user's drive. Folders are always listed first. The limit, if specified, is applied over the total number of elements.",
requireCredential: true,
kind: 'read:drive',
res: {
type: 'array',
optional: false, nullable: false,
items: {
oneOf: [{
type: 'object',
optional: false, nullable: false,
ref: 'DriveFile',
}, {
type: 'object',
optional: false, nullable: false,
ref: 'DriveFolder',
}],
},
},
} as const;
export const paramDef = {
type: 'object',
properties: {
limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 },
sinceId: { type: 'string', format: 'misskey:id' },
untilId: { type: 'string', format: 'misskey:id' },
folderId: { type: 'string', format: 'misskey:id', nullable: true, default: null },
},
required: [],
} as const;
// eslint-disable-next-line import/no-default-export
export default define(meta, paramDef, async (ps, user) => {
const foldersQuery = makePaginationQuery(DriveFolders.createQueryBuilder('folder'), ps.sinceId, ps.untilId)
.andWhere('folder.userId = :userId', { userId: user.id });
const filesQuery = makePaginationQuery(DriveFiles.createQueryBuilder('file'), ps.sinceId, ps.untilId)
.andWhere('file.userId = :userId', { userId: user.id });
if (ps.folderId) {
foldersQuery.andWhere('folder.parentId = :parentId', { parentId: ps.folderId });
filesQuery.andWhere('file.folderId = :folderId', { folderId: ps.folderId });
} else {
foldersQuery.andWhere('folder.parentId IS NULL');
filesQuery.andWhere('file.folderId IS NULL');
}
const folders = await foldersQuery.take(ps.limit).getMany();
const [files, ...packedFolders] = await Promise.all([
filesQuery.take(ps.limit - folders.length).getMany(),
...(folders.map(folder => DriveFolders.pack(folder))),
]);
const packedFiles = await DriveFiles.packMany(files, { detail: false, self: true });
return [
...packedFolders,
...packedFiles,
];
});

View file

@ -52,7 +52,7 @@ const props = withDefaults(defineProps<{
}); });
const emit = defineEmits<{ const emit = defineEmits<{
(ev: 'chosen', r: foundkey.entities.DriveFile): void; (ev: 'chosen', r: foundkey.entities.DriveFile, extendSelection: boolean): void;
(ev: 'dragstart'): void; (ev: 'dragstart'): void;
(ev: 'dragend'): void; (ev: 'dragend'): void;
}>(); }>();
@ -95,9 +95,7 @@ function getMenu(): MenuItem[] {
function onClick(ev: MouseEvent): void { function onClick(ev: MouseEvent): void {
if (props.selectMode) { if (props.selectMode) {
emit('chosen', props.file); emit('chosen', props.file, ev.ctrlKey);
} else {
os.popupMenu(getMenu(), (ev.currentTarget ?? ev.target ?? undefined) as HTMLElement | undefined);
} }
} }
@ -330,7 +328,7 @@ async function deleteFile(): Promise<void> {
overflow: hidden; overflow: hidden;
> .ext { > .ext {
opacity: 0.5; opacity: 0.7;
} }
} }
} }

View file

@ -1,10 +1,10 @@
<template> <template>
<div <div
class="rghtznwe" class="rghtznwe"
:class="{ draghover }" :class="{ draghover, isSelected }"
draggable="true" draggable="true"
:title="title" :title="title"
@click="onClick" @click="selected"
@contextmenu.stop="onContextmenu" @contextmenu.stop="onContextmenu"
@mouseover="onMouseover" @mouseover="onMouseover"
@mouseout="onMouseout" @mouseout="onMouseout"
@ -15,15 +15,16 @@
@dragstart="onDragstart" @dragstart="onDragstart"
@dragend="onDragend" @dragend="onDragend"
> >
<div class="thumbnail" @click.stop="emit('move', folder)">
<i class="fas fa-folder-open fa-fw hover"></i>
<i class="fas fa-folder fa-fw"></i>
</div>
<p class="name"> <p class="name">
<template v-if="hover"><i class="fas fa-folder-open fa-fw"></i></template>
<template v-if="!hover"><i class="fas fa-folder fa-fw"></i></template>
{{ folder.name }} {{ folder.name }}
</p> </p>
<p v-if="defaultStore.state.uploadFolder == folder.id" class="upload"> <p v-if="defaultStore.state.uploadFolder == folder.id" class="upload">
{{ i18n.ts.uploadFolder }} {{ i18n.ts.uploadFolder }}
</p> </p>
<button v-if="selectMode" class="checkbox _button" :class="{ checked: isSelected }" @click.prevent.stop="checkboxClicked"></button>
</div> </div>
</template> </template>
@ -44,7 +45,7 @@ const props = withDefaults(defineProps<{
}); });
const emit = defineEmits<{ const emit = defineEmits<{
(ev: 'chosen', v: foundkey.entities.DriveFolder): void; (ev: 'chosen', v: foundkey.entities.DriveFolder, extendSelection: boolean): void;
(ev: 'move', v: foundkey.entities.DriveFolder): void; (ev: 'move', v: foundkey.entities.DriveFolder): void;
(ev: 'upload', file: File, folder: foundkey.entities.DriveFolder); (ev: 'upload', file: File, folder: foundkey.entities.DriveFolder);
(ev: 'removeFile', v: foundkey.entities.DriveFile['id']): void; (ev: 'removeFile', v: foundkey.entities.DriveFile['id']): void;
@ -59,20 +60,10 @@ const isDragging = ref(false);
const title = computed(() => props.folder.name); const title = computed(() => props.folder.name);
function checkboxClicked() { function selected(ev: MouseEvent) {
emit('chosen', props.folder); if (props.selectMode) {
emit('chosen', props.folder, ev.ctrlKey);
} }
function onClick() {
emit('move', props.folder);
}
function onMouseover() {
hover.value = true;
}
function onMouseout() {
hover.value = false;
} }
function onDragover(ev: DragEvent) { function onDragover(ev: DragEvent) {
@ -260,30 +251,34 @@ function onContextmenu(ev: MouseEvent) {
.rghtznwe { .rghtznwe {
position: relative; position: relative;
padding: 8px; padding: 8px;
height: 64px; min-height: 180px;
background: var(--driveFolderBg); border-radius: 8px;
border-radius: 4px;
&, * { &, * {
cursor: pointer; cursor: pointer;
} }
*:not(.checkbox) { > .thumbnail {
width: 110px;
height: 110px;
margin: auto;
/* same style as drive-file-thumbnail.vue */
position: relative;
display: flex;
background: var(--panel);
border-radius: 8px;
overflow: clip;
> i {
pointer-events: none; pointer-events: none;
margin: auto;
font-size: 33px;
color: #777;
} }
> .checkbox { &:not(:hover) > i.hover,
position: absolute; &:hover > i:not(.hover) { display: none; }
bottom: 8px;
right: 8px;
width: 16px;
height: 16px;
background: #fff;
border: solid 1px #000;
&.checked {
background: var(--accent);
}
} }
&.draghover { &.draghover {
@ -300,23 +295,37 @@ function onContextmenu(ev: MouseEvent) {
} }
} }
> .name { &.isSelected {
margin: 0; background: var(--accent);
font-size: 0.9em;
color: var(--desktopDriveFolderFg);
> i { &:hover {
margin-right: 4px; background: var(--accentLighten);
margin-left: 2px;
text-align: left;
} }
> .name {
color: #fff;
}
> .thumbnail {
color: #fff;
}
}
> .name {
display: block;
margin: 4px 0 0 0;
font-size: 0.8em;
text-align: center;
word-break: break-all;
color: var(--fg);
overflow: hidden;
} }
> .upload { > .upload {
margin: 4px 4px; margin: 4px 4px;
font-size: 0.8em; font-size: 0.8em;
text-align: right; text-align: center;
color: var(--desktopDriveFolderFg); opacity: 0.7;
} }
} }
</style> </style>

View file

@ -35,31 +35,37 @@
@drop.prevent.stop="onDrop" @drop.prevent.stop="onDrop"
@contextmenu.stop="onContextmenu" @contextmenu.stop="onContextmenu"
> >
<div ref="contents" class="contents">
<MkPagination <MkPagination
ref="foldersPaginationElem" ref="paginationElem"
:pagination="foldersPagination" :pagination="pagination"
class="folders" class="contents"
@loaded="foldersLoading = false"
> >
<template #empty> <template #empty>
<!-- <p v-if="folder == null" class="empty"><strong>{{ i18n.ts.emptyDrive }}</strong></p>
Don't display anything here if there are no folders, <p v-else class="empty">{{ i18n.ts.emptyFolder }}</p>
there is a separate check if both paginations are empty.
-->
{{ null }}
</template> </template>
<template #default="{ items: folders }"> <template #default="{ items }">
<XFolder <template v-for="(f, i) in items">
v-for="(f, i) in folders" <XFile
v-if="'size' in f"
:key="f.id"
v-anim="i"
:file="f"
:select-mode="select !== 'folder'"
:is-selected="selected.some(x => x.id === f.id)"
@chosen="choose"
@dragstart="isDragSource = true"
@dragend="isDragSource = false"
/>
<XFolder
v-else
:key="f.id" :key="f.id"
v-anim="i" v-anim="i"
class="folder"
:folder="f" :folder="f"
:select-mode="select === 'folder'" :select-mode="select !== 'file'"
:is-selected="selectedFolders.some(x => x.id === f.id)" :is-selected="selected.some(x => x.id === f.id)"
@chosen="chooseFolder" @chosen="choose"
@move="move" @move="move"
@upload="upload" @upload="upload"
@removeFile="removeFile" @removeFile="removeFile"
@ -67,46 +73,9 @@
@dragstart="isDragSource = true" @dragstart="isDragSource = true"
@dragend="isDragSource = false" @dragend="isDragSource = false"
/> />
<!-- SEE: https://stackoverflow.com/questions/18744164/flex-box-align-last-row-to-grid --> </template>
<div v-for="(n, i) in 16" :key="i" class="padding"></div>
</template> </template>
</MkPagination> </MkPagination>
<MkPagination
ref="filesPaginationElem"
:pagination="filesPagination"
class="files"
@loaded="filesLoading = false"
>
<template #empty>
<!--
Don't display anything here if there are no files,
there is a separate check if both paginations are empty.
-->
{{ null }}
</template>
<template #default="{ items: files }">
<XFile
v-for="(file, i) in files"
:key="file.id"
v-anim="i"
class="file"
:file="file"
:select-mode="select === 'file'"
:is-selected="selectedFiles.some(x => x.id === file.id)"
@chosen="chooseFile"
@dragstart="isDragSource = true"
@dragend="isDragSource = false"
/>
<!-- SEE: https://stackoverflow.com/questions/18744164/flex-box-align-last-row-to-grid -->
<div v-for="(n, i) in 16" :key="i" class="padding"></div>
</template>
</MkPagination>
<div v-if="empty" class="empty">
<p v-if="folder == null"><strong>{{ i18n.ts.emptyDrive }}</strong></p>
<p v-else>{{ i18n.ts.emptyFolder }}</p>
</div>
</div>
</div> </div>
<div v-if="draghover" class="dropzone"></div> <div v-if="draghover" class="dropzone"></div>
<input ref="fileInput" type="file" accept="*/*" multiple tabindex="-1" @change="onChangeFileInput"/> <input ref="fileInput" type="file" accept="*/*" multiple tabindex="-1" @change="onChangeFileInput"/>
@ -129,7 +98,6 @@ import { uploadFile, uploads } from '@/scripts/upload';
const props = withDefaults(defineProps<{ const props = withDefaults(defineProps<{
initialFolder?: foundkey.entities.DriveFolder; initialFolder?: foundkey.entities.DriveFolder;
type?: string;
multiple?: boolean; multiple?: boolean;
select?: 'file' | 'folder' | null; select?: 'file' | 'folder' | null;
}>(), { }>(), {
@ -139,19 +107,13 @@ const props = withDefaults(defineProps<{
const emit = defineEmits<{ const emit = defineEmits<{
(ev: 'selected', v: foundkey.entities.DriveFile | foundkey.entities.DriveFolder): void; (ev: 'selected', v: foundkey.entities.DriveFile | foundkey.entities.DriveFolder): void;
(ev: 'change-selection', v: foundkey.entities.DriveFile[] | foundkey.entities.DriveFolder[]): void; (ev: 'change-selection', v: Array<foundkey.entities.DriveFile | foundkey.entities.DriveFolder>): void;
(ev: 'move-root'): void; (ev: 'move-root'): void;
(ev: 'cd', v: foundkey.entities.DriveFolder | null): void; (ev: 'cd', v: foundkey.entities.DriveFolder | null): void;
(ev: 'open-folder', v: foundkey.entities.DriveFolder): void; (ev: 'open-folder', v: foundkey.entities.DriveFolder): void;
}>(); }>();
let foldersPaginationElem = $ref<InstanceType<typeof MkPagination>>(); let paginationElem = $ref<InstanceType<typeof MkPagination>>();
let filesPaginationElem = $ref<InstanceType<typeof MkPagination>>();
let foldersLoading = $ref<boolean>(true);
let filesLoading = $ref<boolean>(true);
const empty = $computed(() => !foldersLoading && !filesLoading
&& foldersPaginationElem?.items.length === 0 && filesPaginationElem?.items.length === 0);
let fileInput = $ref<HTMLInputElement>(); let fileInput = $ref<HTMLInputElement>();
@ -160,8 +122,7 @@ const connection = stream.useChannel('drive');
let folder = $ref<foundkey.entities.DriveFolder | null>(null); let folder = $ref<foundkey.entities.DriveFolder | null>(null);
let hierarchyFolders = $ref<foundkey.entities.DriveFolder[]>([]); let hierarchyFolders = $ref<foundkey.entities.DriveFolder[]>([]);
let selectedFiles = $ref<foundkey.entities.DriveFile[]>([]); let selected = $ref<Array<foundkey.entities.DriveFile | foundkey.entities.DriveFolder>>([]);
let selectedFolders = $ref<foundkey.entities.DriveFolder[]>([]);
let keepOriginal = $ref<boolean>(defaultStore.state.keepOriginalUploading); let keepOriginal = $ref<boolean>(defaultStore.state.keepOriginalUploading);
// //
@ -171,7 +132,14 @@ let draghover = $ref(false);
// () // ()
let isDragSource = $ref(false); let isDragSource = $ref(false);
watch($$(folder), () => emit('cd', folder)); watch($$(folder), () => {
emit('cd', folder)
if (props.select === 'folder') {
// convenience: entering a folder selects it
selected = [folder];
emit('change-selection', selected);
}
});
function onStreamDriveFileCreated(file: foundkey.entities.DriveFile) { function onStreamDriveFileCreated(file: foundkey.entities.DriveFile) {
addFile(file, true); addFile(file, true);
@ -210,9 +178,8 @@ function onStreamDriveFolderDeleted(folderId: string) {
function onDragover(ev: DragEvent): any { function onDragover(ev: DragEvent): any {
if (!ev.dataTransfer) return; if (!ev.dataTransfer) return;
//
if (isDragSource) { if (isDragSource) {
// // We are the drag source, do not allow to drop.
ev.dataTransfer.dropEffect = 'none'; ev.dataTransfer.dropEffect = 'none';
return; return;
} }
@ -257,17 +224,16 @@ function onDrop(ev: DragEvent): any {
if (!ev.dataTransfer) return; if (!ev.dataTransfer) return;
// const driveFile = ev.dataTransfer.getData(_DATA_TRANSFER_DRIVE_FILE_);
const driveFolder = ev.dataTransfer.getData(_DATA_TRANSFER_DRIVE_FOLDER_);
if (ev.dataTransfer.files.length > 0) { if (ev.dataTransfer.files.length > 0) {
// dropping operating system files
for (const file of Array.from(ev.dataTransfer.files)) { for (const file of Array.from(ev.dataTransfer.files)) {
upload(file, folder); upload(file, folder);
} }
return; } else if (driveFile != null && driveFile !== '') {
} // dropping drive files
//#region
const driveFile = ev.dataTransfer.getData(_DATA_TRANSFER_DRIVE_FILE_);
if (driveFile != null && driveFile !== '') {
const file = JSON.parse(driveFile); const file = JSON.parse(driveFile);
// cannot move file within parent folder // cannot move file within parent folder
@ -278,18 +244,14 @@ function onDrop(ev: DragEvent): any {
fileId: file.id, fileId: file.id,
folderId: folder?.id ?? null, folderId: folder?.id ?? null,
}); });
} } else if (driveFolder != null && driveFolder !== '') {
//#endregion // dropping drive folders
//#region
const driveFolder = ev.dataTransfer.getData(_DATA_TRANSFER_DRIVE_FOLDER_);
if (driveFolder != null && driveFolder !== '') {
const droppedFolder = JSON.parse(driveFolder); const droppedFolder = JSON.parse(driveFolder);
// cannot move folder into itself // cannot move folder into itself
if (droppedFolder.id === folder?.id) return false; if (droppedFolder.id === folder?.id) return false;
// cannot move folder within parent folder // cannot move folder within parent folder
if (foldersPaginationElem.items.some(f => f.id === droppedFolder.id)) return false; if (folder.id === droppedFolder.parentId) return false;
removeFolder(droppedFolder.id); removeFolder(droppedFolder.id);
os.api('drive/folders/update', { os.api('drive/folders/update', {
@ -311,7 +273,6 @@ function onDrop(ev: DragEvent): any {
} }
}); });
} }
//#endregion
} }
function selectLocalFile() { function selectLocalFile() {
@ -346,8 +307,6 @@ function createFolder() {
os.api('drive/folders/create', { os.api('drive/folders/create', {
name, name,
parentId: folder?.id ?? undefined, parentId: folder?.id ?? undefined,
}).then(createdFolder => {
addFolder(createdFolder, true);
}); });
}); });
} }
@ -404,49 +363,52 @@ function upload(file: File, folderToUpload?: foundkey.entities.DriveFolder | nul
uploadFile(file, folderToUpload?.id ?? null, undefined, keepOriginal); uploadFile(file, folderToUpload?.id ?? null, undefined, keepOriginal);
} }
function chooseFile(file: foundkey.entities.DriveFile) { function choose(choice: foundkey.entities.DriveFile | foundkey.entities.DriveFolder, extendSelection: boolean) {
const isAlreadySelected = selectedFiles.some(f => f.id === file.id); const alreadySelected = selectedFiles.some(f => f.id === file.id);
if (props.multiple) {
if (isAlreadySelected) {
selectedFiles = selectedFiles.filter(f => f.id !== file.id);
} else {
selectedFiles.push(file);
}
emit('change-selection', selectedFiles);
} else {
if (isAlreadySelected) {
emit('selected', file);
} else {
selectedFiles = [file];
emit('change-selection', [file]);
}
}
}
function chooseFolder(folderToChoose: foundkey.entities.DriveFolder) { const action = (() => {
const isAlreadySelected = selectedFolders.some(f => f.id === folderToChoose.id); if (props.select != null) {
if (props.multiple) { // file picker mode, extendSelection is disregarded
if (isAlreadySelected) { if (props.multiple && alreadySelected) {
selectedFolders = selectedFolders.filter(f => f.id !== folderToChoose.id); return 'remove';
} else if (props.multiple) {
return 'add';
} else if (!props.multiple && alreadySelected) {
return 'emit';
} else { } else {
selectedFolders.push(folderToChoose); return 'set';
} }
emit('change-selection', selectedFolders);
} else { } else {
if (isAlreadySelected) { // explorer mode, props.multiple is disregarded
emit('selected', folderToChoose); if (extendSelection && alreadySelected) {
} else { return 'remove';
selectedFolders = [folderToChoose]; } else if (extendSelection) {
emit('change-selection', [folderToChoose]); return 'add';
} else if (!alreadySelected) {
return 'set';
} }
// already selected && ! extend selection is a noop
} }
})();
switch (action) {
case 'emit':
emit('selected', choice);
return; // don't emit the change-selection event
case 'add':
selected.push(choice);
break;
case 'set':
selected = [choice];
break;
case 'remove':
selected = selected.filter(f => f.id !== choice.id);
break;
}
emit('change-selection', selected);
} }
function move(target?: string | foundkey.entities.DriveFolder) { function move(target?: string | foundkey.entities.DriveFolder) {
// reset loading state
foldersLoading = true;
filesLoading = true;
if (!target) { if (!target) {
goRoot(); goRoot();
return; return;
@ -475,13 +437,13 @@ function addFolder(folderToAdd: foundkey.entities.DriveFolder, unshift = false)
const current = folder?.id ?? null; const current = folder?.id ?? null;
if (current !== folderToAdd.parentId) return; if (current !== folderToAdd.parentId) return;
const exist = foldersPaginationElem.items.some(f => f.id === folderToAdd.id); const exist = paginationElem.items.some(f => f.id === folderToAdd.id);
if (exist) { if (exist) {
foldersPaginationElem.updateItem(folderToAdd.id, () => folderToAdd); paginationElem.updateItem(folderToAdd.id, () => folderToAdd);
} else if (unshift) { } else if (unshift) {
foldersPaginationElem.prepend(folderToAdd); paginationElem.prepend(folderToAdd);
} else { } else {
foldersPaginationElem.append(folderToAdd); paginationElem.append(folderToAdd);
} }
} }
@ -489,24 +451,24 @@ function addFile(fileToAdd: foundkey.entities.DriveFile, unshift = false) {
const current = folder?.id ?? null; const current = folder?.id ?? null;
if (current !== fileToAdd.folderId) return; if (current !== fileToAdd.folderId) return;
const exist = filesPaginationElem.items.some(f => f.id === fileToAdd.id); const exist = paginationElem.items.some(f => f.id === fileToAdd.id);
if (exist) { if (exist) {
filesPaginationElem.updateItem(fileToAdd.id, () => fileToAdd); paginationElem.updateItem(fileToAdd.id, () => fileToAdd);
} else if (unshift) { } else if (unshift) {
filesPaginationElem.prepend(fileToAdd); paginationElem.prepend(fileToAdd);
} else { } else {
filesPaginationElem.append(fileToAdd); paginationElem.append(fileToAdd);
} }
} }
function removeFolder(folderToRemove: foundkey.entities.DriveFolder | string): void { function removeFolder(folderToRemove: foundkey.entities.DriveFolder | string): void {
const folderIdToRemove = typeof folderToRemove === 'object' ? folderToRemove.id : folderToRemove; const folderIdToRemove = typeof folderToRemove === 'object' ? folderToRemove.id : folderToRemove;
foldersPaginationElem.removeItem(item => item.id === folderIdToRemove); paginationElem.removeItem(item => item.id === folderIdToRemove);
} }
function removeFile(fileToRemove: foundkey.entities.DriveFile | string): void { function removeFile(fileToRemove: foundkey.entities.DriveFile | string): void {
const fileIdToRemove = typeof fileToRemove === 'object' ? fileToRemove.id : fileToRemove; const fileIdToRemove = typeof fileToRemove === 'object' ? fileToRemove.id : fileToRemove;
filesPaginationElem.removeItem(item => item.id === fileIdToRemove); paginationElem.removeItem(item => item.id === fileIdToRemove);
} }
function goRoot() { function goRoot() {
@ -518,23 +480,14 @@ function goRoot() {
emit('move-root'); emit('move-root');
} }
const foldersPagination = { const pagination = {
endpoint: 'drive/folders' as const, endpoint: 'drive/show' as const,
limit: 30, limit: 30,
params: computed(() => ({ params: computed(() => ({
folderId: folder?.id ?? null, folderId: folder?.id ?? null,
})), })),
}; };
const filesPagination = {
endpoint: 'drive/files' as const,
limit: 30,
params: computed(() => ({
folderId: folder?.id ?? null,
type: props.type,
})),
};
function getMenu() { function getMenu() {
return [{ return [{
type: 'switch', type: 'switch',
@ -678,25 +631,9 @@ onBeforeUnmount(() => {
} }
> .contents { > .contents {
display: grid;
> .folders, grid-template-columns: repeat(5, 1fr);
> .files { gap: .5em;
display: flex;
flex-wrap: wrap;
> .folder,
> .file {
flex-grow: 1;
width: 128px;
margin: 4px;
box-sizing: border-box;
}
> .padding {
flex-grow: 1;
pointer-events: none;
width: 128px + 8px;
}
} }
> .empty { > .empty {
@ -704,13 +641,9 @@ onBeforeUnmount(() => {
text-align: center; text-align: center;
pointer-events: none; pointer-events: none;
opacity: 0.5; opacity: 0.5;
> p {
margin: 0; margin: 0;
} }
} }
}
}
> .dropzone { > .dropzone {
position: absolute; position: absolute;

View file

@ -64,7 +64,6 @@
inputBorder: 'rgba(255, 255, 255, 0.1)', inputBorder: 'rgba(255, 255, 255, 0.1)',
inputBorderHover: 'rgba(255, 255, 255, 0.2)', inputBorderHover: 'rgba(255, 255, 255, 0.2)',
listItemHoverBg: 'rgba(255, 255, 255, 0.03)', listItemHoverBg: 'rgba(255, 255, 255, 0.03)',
driveFolderBg: ':alpha<0.3<@accent',
wallpaperOverlay: 'rgba(0, 0, 0, 0.5)', wallpaperOverlay: 'rgba(0, 0, 0, 0.5)',
badge: '#31b1ce', badge: '#31b1ce',
messageBg: '@bg', messageBg: '@bg',

View file

@ -64,7 +64,6 @@
inputBorder: 'rgba(0, 0, 0, 0.1)', inputBorder: 'rgba(0, 0, 0, 0.1)',
inputBorderHover: 'rgba(0, 0, 0, 0.2)', inputBorderHover: 'rgba(0, 0, 0, 0.2)',
listItemHoverBg: 'rgba(0, 0, 0, 0.03)', listItemHoverBg: 'rgba(0, 0, 0, 0.03)',
driveFolderBg: ':alpha<0.3<@accent',
wallpaperOverlay: 'rgba(255, 255, 255, 0.5)', wallpaperOverlay: 'rgba(255, 255, 255, 0.5)',
badge: '#31b1ce', badge: '#31b1ce',
messageBg: '@bg', messageBg: '@bg',

View file

@ -46,7 +46,6 @@
buttonHoverBg: 'rgba(255, 255, 255, 0.1)', buttonHoverBg: 'rgba(255, 255, 255, 0.1)',
buttonGradateA: '@accent', buttonGradateA: '@accent',
buttonGradateB: ':hue<-20<@accent', buttonGradateB: ':hue<-20<@accent',
driveFolderBg: ':alpha<0.3<@accent',
fgHighlighted: ':lighten<3<@fg', fgHighlighted: ':lighten<3<@fg',
panelHeaderBg: ':lighten<3<@panel', panelHeaderBg: ':lighten<3<@panel',
panelHeaderFg: '@fg', panelHeaderFg: '@fg',

View file

@ -66,7 +66,6 @@
navIndicator: '@indicator', navIndicator: '@indicator',
accentLighten: ':lighten<10<@accent', accentLighten: ':lighten<10<@accent',
buttonHoverBg: 'rgba(255, 255, 255, 0.1)', buttonHoverBg: 'rgba(255, 255, 255, 0.1)',
driveFolderBg: ':alpha<0.3<@accent',
fgHighlighted: ':lighten<3<@fg', fgHighlighted: ':lighten<3<@fg',
fgTransparent: ':alpha<0.5<@fg', fgTransparent: ':alpha<0.5<@fg',
panelHeaderBg: ':lighten<3<@panel', panelHeaderBg: ':lighten<3<@panel',

View file

@ -47,7 +47,6 @@
navIndicator: '@accent', navIndicator: '@accent',
accentLighten: ':lighten<10<@accent', accentLighten: ':lighten<10<@accent',
buttonHoverBg: 'rgba(0, 0, 0, 0.1)', buttonHoverBg: 'rgba(0, 0, 0, 0.1)',
driveFolderBg: ':alpha<0.3<@accent',
fgHighlighted: ':darken<3<@fg', fgHighlighted: ':darken<3<@fg',
fgTransparent: ':alpha<0.5<@fg', fgTransparent: ':alpha<0.5<@fg',
panelHeaderBg: ':lighten<3<@panel', panelHeaderBg: ':lighten<3<@panel',