From 8ab64b170a8e2755a59d88b4f832279936b9ca07 Mon Sep 17 00:00:00 2001 From: Andras Schmelczer Date: Fri, 3 Jan 2025 23:26:55 +0000 Subject: [PATCH] Improve history view UX --- plugin/src/styles.scss | 34 ++++++--- plugin/src/views/history-view.ts | 119 ++++++++++++++++++++++--------- 2 files changed, 110 insertions(+), 43 deletions(-) diff --git a/plugin/src/styles.scss b/plugin/src/styles.scss index de36c52..1de9a20 100644 --- a/plugin/src/styles.scss +++ b/plugin/src/styles.scss @@ -5,7 +5,7 @@ padding: var(--size-2-1) var(--size-4-1); border-radius: var(--radius-s); background-color: var(--color-base-30); - font-family: var(--font-monospace-default); + font-family: var(--font-monospace); font-weight: var(--bold-weight); font-size: var(--font-ui-small); @@ -85,7 +85,7 @@ } .log-message { - font: var(--font-monospace-theme); + font: var(--font-monospace); &.DEBUG { color: var(--color-base-50); @@ -105,10 +105,15 @@ } .history-card { - padding: var(--size-4-4) var(--size-4-6); + padding: var(--size-4-4); margin: var(--size-4-2); background-color: var(--color-base-00); border-radius: var(--radius-l); + container-type: inline-size; + + &.clickable { + cursor: pointer; + } &.success { background-color: rgba(var(--color-green-rgb), 0.2); @@ -118,29 +123,36 @@ background-color: rgba(var(--color-red-rgb), 0.2); } - * { - margin: 0; - padding: 0; - } - .history-card-header { display: flex; justify-content: space-between; align-items: center; - margin-bottom: var(--size-4-4); + margin-bottom: var(--size-4-2); + gap: var(--size-4-2); + + @container (max-width: 300px) { + flex-direction: column; + align-items: flex-start; + } .history-card-title { - font: var(--font-monospace-theme); + font: var(--font-monospace); + display: flex; + gap: var(--size-4-2); + word-break: break-all; + margin: 0; } .history-card-timestamp { font-size: var(--font-ui-small); - color: var(--color-base-70); + font-style: italic; + color: var(--italic-color); } } .history-card-message { font-size: var(--font-ui-medium); color: var(--color-base-70); + margin: 0; } } diff --git a/plugin/src/views/history-view.ts b/plugin/src/views/history-view.ts index 97c1ea3..1ce3036 100644 --- a/plugin/src/views/history-view.ts +++ b/plugin/src/views/history-view.ts @@ -1,6 +1,6 @@ -import type { WorkspaceLeaf } from "obsidian"; -import { ItemView } from "obsidian"; -import type { SyncHistory} from "src/tracing/sync-history"; +import type { IconName, WorkspaceLeaf } from "obsidian"; +import { ItemView, setIcon } from "obsidian"; +import type { HistoryEntry, SyncHistory } from "src/tracing/sync-history"; import { SyncType } from "src/tracing/sync-history"; import { SyncSource, SyncStatus } from "src/tracing/sync-history"; import { intlFormatDistance } from "date-fns"; @@ -25,32 +25,51 @@ export class HistoryView extends ItemView { }); } - private static formatSyncType(type: SyncType | undefined): string { + private static getSyncTypeIcon(type: SyncType | undefined): IconName { switch (type) { case SyncType.CREATE: - return "👶 "; + return "file-plus"; case SyncType.DELETE: - return "🗑️ "; + return "trash-2"; case SyncType.UPDATE: - return "✍️ "; + return "file-pen-line"; case undefined: default: return ""; } } - private static formatSource(source: SyncSource | undefined): string { + private static getSyncSourceIcon(source: SyncSource | undefined): IconName { switch (source) { case SyncSource.PUSH: - return " ⤴️"; + return "upload"; case SyncSource.PULL: - return " ⤵️"; + return "download"; case undefined: default: return ""; } } + private static renderSyncItemTitle( + element: HTMLElement, + entry: HistoryEntry + ): void { + const syncTypeIcon = HistoryView.getSyncTypeIcon(entry.type); + if (syncTypeIcon) { + setIcon(element.createDiv(), syncTypeIcon); + } + + element.createEl("span", { + text: entry.relativePath, + }); + + const syncSourceIcon = HistoryView.getSyncSourceIcon(entry.source); + if (syncSourceIcon) { + setIcon(element.createDiv(), syncSourceIcon); + } + } + public getViewType(): string { return HistoryView.TYPE; } @@ -76,34 +95,70 @@ export class HistoryView extends ItemView { container.empty(); container.createEl("h4", { text: "VaultLink History" }); - this.history + const entries = this.history .getEntries() .reverse() .filter( (entry) => entry.status !== SyncStatus.NO_OP || this.database.getSettings().displayNoopSyncEvents - ) - .forEach((entry) => { - const card = container.createDiv({ + ); + + entries.forEach((entry) => { + container.createDiv( + { cls: ["history-card", entry.status.toLocaleLowerCase()], - }); - const header = card.createDiv({ cls: "history-card-header" }); - header.createEl("h5", { - text: - HistoryView.formatSyncType(entry.type) + - entry.relativePath + - HistoryView.formatSource(entry.source), - cls: "history-card-title", - }); - header.createSpan({ - text: intlFormatDistance(entry.timestamp, new Date()), - cls: "history-card-timestamp", - }); - card.createEl("p", { - text: entry.message, - cls: "history-card-message", - }); - }); + }, + (card) => { + if ( + this.app.vault.getFileByPath(entry.relativePath) !== + null + ) { + card.addEventListener("click", () => { + void this.app.workspace.openLinkText( + entry.relativePath, + entry.relativePath, + false + ); + }); + + card.addClass("clickable"); + } + + card.createDiv( + { + cls: "history-card-header", + }, + (header) => { + header.createEl( + "h5", + { + cls: "history-card-title", + }, + (title) => { + HistoryView.renderSyncItemTitle( + title, + entry + ); + } + ); + + header.createSpan({ + text: intlFormatDistance( + entry.timestamp, + new Date() + ), + cls: "history-card-timestamp", + }); + } + ); + + card.createEl("p", { + text: `${entry.message}.`, + cls: "history-card-message", + }); + } + ); + }); } }