diff --git a/src/components/pages/ItemsView.vue b/src/components/pages/ItemsView.vue index f272c17..1eee032 100644 --- a/src/components/pages/ItemsView.vue +++ b/src/components/pages/ItemsView.vue @@ -27,18 +27,16 @@ diff --git a/src/components/pages/Source.vue b/src/components/pages/Source.vue new file mode 100644 index 0000000..04f860c --- /dev/null +++ b/src/components/pages/Source.vue @@ -0,0 +1,84 @@ + + + diff --git a/src/main.ts b/src/main.ts index 33ce528..0359ca7 100644 --- a/src/main.ts +++ b/src/main.ts @@ -6,12 +6,14 @@ import App from "./App.vue"; import Todo from "./components/pages/Todo.vue"; import Snoozed from "./components/pages/Snoozed.vue"; import LowPriority from "./components/pages/LowPriority.vue"; +import Source from "./components/pages/Source.vue"; const routes: RouteRecordRaw[] = [ { path: '/', component: Todo, name: 'home' }, { path: '/todo/:source(\\d+)?/:sourceItem(\\d+)?/:thread(\\d+)?', component: Todo, name: 'todo' }, { path: '/snoozed/:source(\\d+)?/:sourceItem(\\d+)?/:thread(\\d+)?', component: Snoozed, name: 'snoozed' }, { path: '/low/:source(\\d+)?/:sourceItem(\\d+)?/:thread(\\d+)?', component: LowPriority, name: 'low' }, + { path: '/source/:source(\\d+)/:sourceItem(\\d+)?/:thread(\\d+)?', component: Source, name: 'source' }, ]; const router = createRouter({ diff --git a/src/utils.ts b/src/utils.ts index 16a00f3..52d01e7 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,3 +1,7 @@ +import { Ref, computed, ref, watch } from "vue"; +import { RouteLocationNormalizedLoaded, Router, useRoute, useRouter } from "vue-router"; +import { ThreadRef, sources } from "./state"; + // Modified from https://www.basedash.com/blog/how-to-merge-two-sorted-lists-in-javascript export function mergeSortedLists(arr1: Array, arr2: Array): Array { const merged: Array = []; @@ -15,3 +19,71 @@ export function mergeSortedLists(arr1: Array, arr2: Array): Array { // Append any remaining elements from arr1 or arr2 return [...merged, ...arr1.slice(i), ...arr2.slice(j)]; } + +export function deArray(value: T | T[]): T { + return Array.isArray(value) ? value[0] : value; +} + +export function setupSelectedThread(baseUrl: Ref, route: RouteLocationNormalizedLoaded, router: Router) { + const showThread = ref(false); + const selectedItem = ref(); + const snoozingItem = ref(); + const snoozing = ref(false); + watch([() => route.params.source, () => route.params.sourceItem, () => route.params.thread], ([source, sourceItem, thread]) => { + const sourceInt = parseInt(Array.isArray(source) ? source[0] : source); + const sourceItemInt = parseInt(Array.isArray(sourceItem) ? sourceItem[0] : sourceItem); + const threadInt = parseInt(Array.isArray(thread) ? thread[0] : thread); + if (!isNaN(sourceInt) && !isNaN(sourceItemInt) && !isNaN(threadInt)) { + selectedItem.value = { source: sourceInt, sourceItem: sourceItemInt, thread: threadInt }; + showThread.value = true; + } else { + // Intentionally leave selectedItem so animations look right + showThread.value = false; + } + }, { immediate: true }); + + const threadTitle = computed(() => { + const selected = selectedItem.value; + if (selected == null) { + return ""; + } + return sources.value[selected.source].items[selected.sourceItem].threads[selected.thread].title; + }); + + function selectItem(source: number, sourceItem: number, thread: number) { + const p = route.params; + const sourceInt = parseInt(Array.isArray(p.source) ? p.source[0] : p.source); + const sourceItemInt = parseInt(Array.isArray(p.sourceItem) ? p.sourceItem[0] : p.sourceItem); + const threadInt = parseInt(Array.isArray(p.thread) ? p.thread[0] : p.thread); + if (source === sourceInt && sourceItem === sourceItemInt && thread === threadInt) { + close(); + return false; + } + router.push(`${baseUrl.value}/${source}/${sourceItem}/${thread}`); + return true; + } + + function snoozeItem(source: number, sourceItem: number, thread: number) { + snoozingItem.value = { source, sourceItem, thread }; + snoozing.value = true; + } + + function close() { + console.log("closing thread") + router.push(baseUrl.value); + snoozing.value = false; + } + + function stopSnoozing() { + if (snoozingItem.value?.source === selectedItem.value?.source && + snoozingItem.value?.sourceItem === selectedItem.value?.sourceItem && + (snoozingItem.value?.thread === -1 || snoozingItem.value?.thread === selectedItem.value?.thread) + ) { + close(); + } else { + snoozing.value = false; + } + } + + return { showThread, selectedItem, snoozingItem, snoozing, threadTitle, selectItem, snoozeItem, close, stopSnoozing }; +}