wip
This commit is contained in:
parent
f25bc9bd95
commit
c98d72e6e1
|
@ -69,25 +69,28 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<MkButton v-if="foldersPaginator.canFetchOlder" ref="moreFolders" @click="foldersPaginator.fetchOlder()">{{ i18n.ts.loadMore }}</MkButton>
|
<MkButton v-if="foldersPaginator.canFetchOlder" ref="moreFolders" @click="foldersPaginator.fetchOlder()">{{ i18n.ts.loadMore }}</MkButton>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-show="filesPaginator.items.value.length > 0" ref="filesContainer" :class="$style.files">
|
<div v-show="filesPaginator.items.value.length > 0" ref="filesContainer">
|
||||||
<div v-for="(file, i) in filesPaginator.items.value" :key="file.id">
|
<MkStickyContainer v-for="(item, i) in filesTimeline" :key="item.date.toISOString()">
|
||||||
<div v-if="i > 0 && isSeparatorNeeded(filesPaginator.items.value[i -1].createdAt, file.createdAt)" :class="$style.date">
|
<template #header>
|
||||||
<span><i class="ti ti-chevron-up"></i> {{ getSeparatorInfo(filesPaginator.items.value[i -1].createdAt, file.createdAt).prevText }}</span>
|
<div :class="$style.date">
|
||||||
<span style="height: 1em; width: 1px; background: var(--MI_THEME-divider);"></span>
|
<span><i class="ti ti-chevron-down"></i> {{ item.date.getFullYear() }}/{{ item.date.getMonth() + 1 }}/{{ item.date.getDate() }}</span>
|
||||||
<span>{{ getSeparatorInfo(filesPaginator.items.value[i -1].createdAt, file.createdAt).nextText }} <i class="ti ti-chevron-down"></i></span>
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<div :class="$style.files">
|
||||||
|
<XFile
|
||||||
|
v-for="file in item.items" :key="file.id"
|
||||||
|
:class="$style.file"
|
||||||
|
:file="file"
|
||||||
|
:folder="folder"
|
||||||
|
:selectMode="select === 'file'"
|
||||||
|
:isSelected="selectedFiles.some(x => x.id === file.id)"
|
||||||
|
@chosen="chooseFile"
|
||||||
|
@dragstart="isDragSource = true"
|
||||||
|
@dragend="isDragSource = false"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<XFile
|
</MkStickyContainer>
|
||||||
v-else
|
|
||||||
:class="$style.file"
|
|
||||||
:file="file"
|
|
||||||
:folder="folder"
|
|
||||||
:selectMode="select === 'file'"
|
|
||||||
:isSelected="selectedFiles.some(x => x.id === file.id)"
|
|
||||||
@chosen="chooseFile"
|
|
||||||
@dragstart="isDragSource = true"
|
|
||||||
@dragend="isDragSource = false"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<MkButton v-show="filesPaginator.canFetchOlder" ref="loadMoreFiles" @click="filesPaginator.fetchOlder()">{{ i18n.ts.loadMore }}</MkButton>
|
<MkButton v-show="filesPaginator.canFetchOlder" ref="loadMoreFiles" @click="filesPaginator.fetchOlder()">{{ i18n.ts.loadMore }}</MkButton>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -121,7 +124,7 @@ import { claimAchievement } from '@/utility/achievements.js';
|
||||||
import { prefer } from '@/preferences.js';
|
import { prefer } from '@/preferences.js';
|
||||||
import { chooseFileFromPc } from '@/utility/select-file.js';
|
import { chooseFileFromPc } from '@/utility/select-file.js';
|
||||||
import { store } from '@/store.js';
|
import { store } from '@/store.js';
|
||||||
import { isSeparatorNeeded, getSeparatorInfo } from '@/utility/timeline-date-separate.js';
|
import { isSeparatorNeeded, getSeparatorInfo, makeDateGroupedTimelineComputedRef } from '@/utility/timeline-date-separate.js';
|
||||||
import { usePagination } from '@/composables/use-pagination.js';
|
import { usePagination } from '@/composables/use-pagination.js';
|
||||||
|
|
||||||
const props = withDefaults(defineProps<{
|
const props = withDefaults(defineProps<{
|
||||||
|
@ -183,6 +186,8 @@ const foldersPaginator = usePagination({
|
||||||
autoInit: false,
|
autoInit: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const filesTimeline = makeDateGroupedTimelineComputedRef(filesPaginator.items, 'month');
|
||||||
|
|
||||||
watch(folder, () => emit('cd', folder.value));
|
watch(folder, () => emit('cd', folder.value));
|
||||||
watch(sortModeSelect, () => {
|
watch(sortModeSelect, () => {
|
||||||
initialize();
|
initialize();
|
||||||
|
@ -725,22 +730,9 @@ onBeforeUnmount(() => {
|
||||||
|
|
||||||
.folders,
|
.folders,
|
||||||
.files {
|
.files {
|
||||||
display: flex;
|
display: grid;
|
||||||
flex-wrap: wrap;
|
grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
|
||||||
}
|
grid-gap: 12px;
|
||||||
|
|
||||||
.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 {
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
import type { Ref } from 'vue';
|
import type { Ref, ShallowRef } from 'vue';
|
||||||
|
|
||||||
export function getDateText(dateInstance: Date) {
|
export function getDateText(dateInstance: Date) {
|
||||||
const date = dateInstance.getDate();
|
const date = dateInstance.getDate();
|
||||||
|
@ -12,19 +12,6 @@ export function getDateText(dateInstance: Date) {
|
||||||
return `${month.toString()}/${date.toString()}`;
|
return `${month.toString()}/${date.toString()}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type DateSeparetedTimelineItem<T> = {
|
|
||||||
id: string;
|
|
||||||
type: 'item';
|
|
||||||
data: T;
|
|
||||||
} | {
|
|
||||||
id: string;
|
|
||||||
type: 'date';
|
|
||||||
prev: Date;
|
|
||||||
prevText: string;
|
|
||||||
next: Date;
|
|
||||||
nextText: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO: いちいちDateインスタンス作成するのは無駄感あるから文字列のまま解析したい
|
// TODO: いちいちDateインスタンス作成するのは無駄感あるから文字列のまま解析したい
|
||||||
export function isSeparatorNeeded(
|
export function isSeparatorNeeded(
|
||||||
prev: string | null,
|
prev: string | null,
|
||||||
|
@ -56,7 +43,20 @@ export function getSeparatorInfo(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function makeDateSeparatedTimelineComputedRef<T extends { id: string; createdAt: string; }>(items: Ref<T[]>) {
|
export type DateSeparetedTimelineItem<T> = {
|
||||||
|
id: string;
|
||||||
|
type: 'item';
|
||||||
|
data: T;
|
||||||
|
} | {
|
||||||
|
id: string;
|
||||||
|
type: 'date';
|
||||||
|
prev: Date;
|
||||||
|
prevText: string;
|
||||||
|
next: Date;
|
||||||
|
nextText: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function makeDateSeparatedTimelineComputedRef<T extends { id: string; createdAt: string; }>(items: Ref<T[]> | ShallowRef<T[]>) {
|
||||||
return computed<DateSeparetedTimelineItem<T>[]>(() => {
|
return computed<DateSeparetedTimelineItem<T>[]>(() => {
|
||||||
const tl: DateSeparetedTimelineItem<T>[] = [];
|
const tl: DateSeparetedTimelineItem<T>[] = [];
|
||||||
for (let i = 0; i < items.value.length; i++) {
|
for (let i = 0; i < items.value.length; i++) {
|
||||||
|
@ -92,3 +92,35 @@ export function makeDateSeparatedTimelineComputedRef<T extends { id: string; cre
|
||||||
return tl;
|
return tl;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type DateGroupedTimelineItem<T> = {
|
||||||
|
date: Date;
|
||||||
|
items: T[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export function makeDateGroupedTimelineComputedRef<T extends { id: string; createdAt: string; }>(items: Ref<T[]> | ShallowRef<T[]>, span: 'day' | 'month' = 'day') {
|
||||||
|
return computed<DateGroupedTimelineItem<T>[]>(() => {
|
||||||
|
const tl: DateGroupedTimelineItem<T>[] = [];
|
||||||
|
for (let i = 0; i < items.value.length; i++) {
|
||||||
|
const item = items.value[i];
|
||||||
|
const date = new Date(item.createdAt);
|
||||||
|
const nextDate = items.value[i + 1] ? new Date(items.value[i + 1].createdAt) : null;
|
||||||
|
|
||||||
|
if (tl.length === 0 || (
|
||||||
|
span === 'day' && tl[tl.length - 1].date.getTime() !== date.getTime()
|
||||||
|
) || (
|
||||||
|
span === 'month' && (
|
||||||
|
tl[tl.length - 1].date.getFullYear() !== date.getFullYear() ||
|
||||||
|
tl[tl.length - 1].date.getMonth() !== date.getMonth()
|
||||||
|
)
|
||||||
|
)) {
|
||||||
|
tl.push({
|
||||||
|
date,
|
||||||
|
items: [],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
tl[tl.length - 1].items.push(item);
|
||||||
|
}
|
||||||
|
return tl;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue