Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 61 additions & 7 deletions client/platform/desktop/frontend/components/Recent.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<script lang="ts">
import { join } from 'path';
import { defineComponent, ref } from '@vue/composition-api';
import { computed, defineComponent, ref } from '@vue/composition-api';

import { DatasetType } from 'dive-common/apispec';

Expand All @@ -17,6 +17,8 @@ export default defineComponent({
},
setup(_, { root }) {
const snackbar = ref(false);
const pageSize = 12; // Default 12 looks good on default width/height of window
const limit = ref(pageSize);
const errorText = ref('');
async function open(dstype: DatasetType) {
const ret = await openFromDisk(dstype);
Expand All @@ -40,11 +42,28 @@ export default defineComponent({
}
}

const paginatedRecents = computed(() => recents.value.slice(0, limit.value));
const totalRecents = computed(() => recents.value.length);

function toggleMore() {
if (limit.value < recents.value.length) {
limit.value = recents.value.length;
} else {
limit.value = pageSize;
}
}

return {
// methods
open,
recents,
join,
setOrGetConversionJob,
toggleMore,
// state
pageSize,
limit,
paginatedRecents,
totalRecents,
snackbar,
errorText,
};
Expand Down Expand Up @@ -125,11 +144,20 @@ export default defineComponent({
class="px-4 py-2 my-4"
min-width="100%"
>
<h2 class="text-h4 font-weight-light mb-2">
<h2
v-if="totalRecents > 0"
class="text-h4 font-weight-light mb-2"
>
Recent
</h2>
<h2
v-else
class="text-h4 font-weight-light mb-2"
>
Open images or video to get started
</h2>
<div
v-for="recent in recents"
v-for="recent in paginatedRecents"
:key="recent.id"
class="pa-1"
>
Expand All @@ -141,9 +169,7 @@ export default defineComponent({
{{
(recent.type === 'video')
? 'mdi-file-video'
: (recent.originalImageFiles.length > 1)
? 'mdi-image-multiple'
: 'mdi-image'
: 'mdi-image-multiple'
}}
</v-icon>
<span v-if="setOrGetConversionJob(recent.id)">
Expand All @@ -169,6 +195,34 @@ export default defineComponent({
</span>
</h3>
</div>
<div
v-if="pageSize < totalRecents"
class="mx-1"
>
<v-divider class="my-2" />
<h3
class="text-body-1"
style="cursor: pointer;"
@click="toggleMore"
>
<v-icon
class="pr-2"
color="primary lighten-3"
>
{{ (limit === totalRecents) ? 'mdi-chevron-up' : 'mdi-chevron-down' }}
</v-icon>
<span
class="primary--text text--lighten-3"
>
<span v-if="limit < totalRecents">
Show {{ totalRecents - pageSize }} more
</span>
<span v-else>
Show less
</span>
</span>
</h3>
</div>
</v-card>
</v-row>
</v-col>
Expand Down
41 changes: 34 additions & 7 deletions client/platform/desktop/frontend/store/dataset.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,50 @@
import Vue from 'vue';
import Install, { ref, computed } from '@vue/composition-api';
import { JsonMeta } from 'platform/desktop/constants';
import { DatasetType } from 'dive-common/apispec';

const RecentsKey = 'desktop.recent';

// TODO remove this: this won't be necessary in Vue 3
Vue.use(Install);

const datasets = ref({} as Record<string, JsonMeta>);
/**
* JsonMetaCache is a subset of JsonMeta
* cached in localStorage for quickly listing
* known datasets
*/
interface JsonMetaCache {
version: number;
type: DatasetType;
id: string;
fps: number;
name: string;
createdAt: string;
originalBasePath: string;
}

const datasets = ref({} as Record<string, JsonMetaCache>);

const recents = computed(() => {
const list = Object.values(datasets.value)
.sort((a, b) => Date.parse(a.createdAt) - Date.parse(b.createdAt))
.slice(0, 20);
.sort((a, b) => Date.parse(b.createdAt) - Date.parse(a.createdAt));
return list;
});

/**
* Load recent datasets from localstorage
* Load recent datasets from localstorage.
*
* Note that the localStorage copy is just a cache and not a source of truth.
* The real dataset JsonMeta must be loaded from disk through the
* loadMetadata() backend method.
*/
function load(): JsonMeta[] {
function load(): JsonMetaCache[] {
try {
const arr = window.localStorage.getItem(RecentsKey);
if (arr) {
const maybeArr = JSON.parse(arr);
if (maybeArr.length) {
maybeArr.forEach((meta: JsonMeta) => (
maybeArr.forEach((meta: JsonMetaCache) => (
Vue.set(datasets.value, meta.id, meta)
));
return maybeArr;
Expand All @@ -42,7 +61,15 @@ function load(): JsonMeta[] {
* @param id dataset id path
*/
function setRecents(meta: JsonMeta) {
Vue.set(datasets.value, meta.id, meta);
Vue.set(datasets.value, meta.id, {
version: meta.version,
type: meta.type,
id: meta.id,
fps: meta.fps,
name: meta.name,
createdAt: meta.createdAt,
originalBasePath: meta.originalBasePath,
});
const values = Object.values(datasets.value);
window.localStorage.setItem(RecentsKey, JSON.stringify(values));
}
Expand Down
8 changes: 3 additions & 5 deletions client/platform/desktop/frontend/store/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,12 @@ import * as api from 'platform/desktop/frontend/api';
import * as common from 'platform/desktop/backend/native/common';

import { settings } from './settings';
import { load, setRecents, clearRecents } from './dataset';
import { load, setRecents } from './dataset';

/* Run forward migrations on any client-side data stores */
export async function migrate() {
const datasets = await load();
if (datasets.length && typeof datasets[0] === 'string') {
clearRecents();
}
/* No migrations yet */
await load();
}

/**
Expand Down