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 @@
+
+
+
+
{{ source.name }}
+
∅
+
- selectItem(item.sourceItem, thread)"
+ @snoozeItem="thread => snoozeItem(sourceId, item.sourceItem, thread)"
+ @deselect="close" />
+
+
+
+ {{ threadTitle }}
+
+
+
+
+
+
+
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 };
+}