diff --git a/manifest.json b/manifest.json index 160a9e1..9063476 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "id": "vault-explorer", "name": "Vault Explorer", - "version": "1.0.1", + "version": "1.1.0", "minAppVersion": "1.4.13", "description": "Explore your vault in visual format", "author": "DecafDev", diff --git a/package.json b/package.json index 7084481..54607f0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "obsidian-vault-explorer", - "version": "1.0.1", + "version": "1.1.0", "description": "Explore your vault in visual format", "main": "main.js", "scripts": { diff --git a/src/constants.ts b/src/constants.ts index 4d158e0..51021a6 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -1,6 +1,6 @@ import { LOG_LEVEL_WARN } from "./logger/constants"; import { generateUUID } from "./svelte/shared/services/uuid"; -import { VaultExplorerPluginSettings } from "./types"; +import { VaultExplorerPluginSettings, ViewType } from "./types"; export const VAULT_EXPLORER_VIEW = "vault-explorer"; @@ -34,7 +34,10 @@ export const DEFAULT_SETTINGS: VaultExplorerPluginSettings = { ] } }, - currentView: "grid", + views: { + currentView: ViewType.GRID, + order: [ViewType.GRID, ViewType.LIST] + }, pageSize: 50, pluginVersion: null } diff --git a/src/main.ts b/src/main.ts index 8497c3c..23ee8a2 100644 --- a/src/main.ts +++ b/src/main.ts @@ -3,7 +3,7 @@ import { Plugin, TAbstractFile, TFile, TFolder } from 'obsidian'; import VaultExplorerView from './obsidian/vault-explorer-view'; import VaultExplorerSettingsTab from './obsidian/vault-explorer-settings-tab'; -import { VaultExplorerPluginSettings } from './types'; +import { VaultExplorerPluginSettings, ViewType } from './types'; import { DEFAULT_SETTINGS, VAULT_EXPLORER_VIEW } from './constants'; import _ from 'lodash'; import EventManager from './event/event-manager'; @@ -13,6 +13,7 @@ import { VaultExplorerPluginSettings_0_5_5 } from './types/types-0.5.5'; import Logger from 'js-logger'; import { formatMessageForLogger, stringToLogLevel } from './logger'; import { LOG_LEVEL_WARN } from './logger/constants'; +import { VaultExplorerPluginSettings_1_0_1 } from './types/types-1.0.1'; export default class VaultExplorerPlugin extends Plugin { settings: VaultExplorerPluginSettings = DEFAULT_SETTINGS; @@ -139,7 +140,7 @@ export default class VaultExplorerPlugin extends Plugin { if (isVersionLessThan(settingsVersion, "1.0.0")) { console.log("Upgrading settings from version 0.5.5 to 1.0.0"); const typedData = (data as unknown) as VaultExplorerPluginSettings_0_5_5; - const newData: VaultExplorerPluginSettings = { + const newData: VaultExplorerPluginSettings_1_0_1 = { ...typedData, logLevel: LOG_LEVEL_WARN, filters: { @@ -160,6 +161,19 @@ export default class VaultExplorerPlugin extends Plugin { } data = newData as unknown as Record; } + + if (isVersionLessThan(settingsVersion, "1.1.0")) { + console.log("Upgrading settings from version 1.0.1 to 1.1.0"); + const typedData = (data as unknown) as VaultExplorerPluginSettings_1_0_1; + const newData: VaultExplorerPluginSettings = { + ...typedData, + views: { + currentView: typedData.currentView as unknown as ViewType, + order: [ViewType.GRID, ViewType.LIST] + } + } + data = newData as unknown as Record; + } } } diff --git a/src/svelte/app/index.svelte b/src/svelte/app/index.svelte index 7045a4b..17caa06 100644 --- a/src/svelte/app/index.svelte +++ b/src/svelte/app/index.svelte @@ -8,10 +8,10 @@ import { FrontMatterCache, Menu, TFile, TFolder } from "obsidian"; import PropertiesFilterModal from "src/obsidian/properties-filter-modal"; import { - CurrentView, PropertyFilterGroup, SortFilter, TimestampFilter, + ViewType, } from "src/types"; import store from "../shared/services/store"; import VaultExplorerPlugin from "src/main"; @@ -32,6 +32,7 @@ import { onMount } from "svelte"; import EventManager from "src/event/event-manager"; import GroupTagList from "./components/group-tag-list.svelte"; + import { getDisplayNameForViewType } from "./services/display-name"; let plugin: VaultExplorerPlugin; @@ -62,7 +63,8 @@ let sortFilter: SortFilter = "file-name-asc"; let timestampFilter: TimestampFilter = "all"; let onlyFavorites: boolean = false; - let currentView: CurrentView = "grid"; + let viewOrder: ViewType[] = []; + let currentView: ViewType = ViewType.GRID; let propertyFilterGroups: PropertyFilterGroup[] = []; let selectedPropertyFilterGroupId: string = ""; @@ -104,7 +106,8 @@ sortFilter = plugin.settings.filters.sort; timestampFilter = plugin.settings.filters.timestamp; onlyFavorites = plugin.settings.filters.onlyFavorites; - currentView = plugin.settings.currentView; + currentView = plugin.settings.views.currentView; + viewOrder = plugin.settings.views.order; propertyFilterGroups = plugin.settings.filters.properties.groups; selectedPropertyFilterGroupId = plugin.settings.filters.properties.selectedGroupId; @@ -329,6 +332,7 @@ timestampFilter, onlyFavorites, currentView, + viewOrder, propertyFilterGroups, selectedPropertyFilterGroupId, saveSettings(); @@ -339,7 +343,8 @@ plugin.settings.filters.sort = sortFilter; plugin.settings.filters.timestamp = timestampFilter; plugin.settings.filters.onlyFavorites = onlyFavorites; - plugin.settings.currentView = currentView; + plugin.settings.views.order = viewOrder; + plugin.settings.views.currentView = currentView; plugin.settings.filters.properties.groups = propertyFilterGroups; plugin.settings.filters.properties.selectedGroupId = selectedPropertyFilterGroupId; @@ -358,6 +363,37 @@ propertyFilterGroups = newGroups; } + function handleViewDragOver(e: CustomEvent) { + const { nativeEvent } = e.detail; + nativeEvent.preventDefault(); + } + + function handleViewDragStart(e: CustomEvent, id: string) { + const { nativeEvent } = e.detail; + nativeEvent.dataTransfer.setData("text", id); + nativeEvent.dataTransfer.effectAllowed = "move"; + } + + function handleViewDrop(e: CustomEvent, id: string) { + const { nativeEvent } = e.detail; + const dragId = nativeEvent.dataTransfer.getData("text"); + nativeEvent.dataTransfer.dropEffect = "move"; + + const draggedIndex = viewOrder.findIndex((view) => view === dragId); + const dragged = viewOrder.find((view) => view === dragId); + + const droppedIndex = viewOrder.findIndex((view) => view === id); + const dropped = viewOrder.find((view) => view === id); + + if (!dragged || !dropped || draggedIndex === -1 || droppedIndex === -1) + return; + + let newViewOrder = [...viewOrder]; + newViewOrder[draggedIndex] = dropped; + newViewOrder[droppedIndex] = dragged; + viewOrder = newViewOrder; + } + function handleGroupDrop(e: CustomEvent) { const { id, nativeEvent } = e.detail; const dragId = nativeEvent.dataTransfer.getData("text"); @@ -605,9 +641,21 @@ - - (currentView = "grid")}>Grid - (currentView = "list")}>List + view === currentView, + )} + > + {#each viewOrder as view} + (currentView = view)} + on:dragstart={(e) => handleViewDragStart(e, view)} + on:dragover={handleViewDragOver} + on:drop={(e) => handleViewDrop(e, view)} + >{getDisplayNameForViewType(view)} + {/each} diff --git a/src/svelte/app/services/display-name.ts b/src/svelte/app/services/display-name.ts new file mode 100644 index 0000000..861b940 --- /dev/null +++ b/src/svelte/app/services/display-name.ts @@ -0,0 +1,12 @@ +import { ViewType } from "src/types"; + +export const getDisplayNameForViewType = (viewType: ViewType) => { + switch (viewType) { + case ViewType.GRID: + return "Grid"; + case ViewType.LIST: + return "List"; + default: + throw new Error(`Unhandled view type: ${viewType}`); + } +} diff --git a/src/svelte/shared/components/tab.svelte b/src/svelte/shared/components/tab.svelte index 80c18be..5c43721 100644 --- a/src/svelte/shared/components/tab.svelte +++ b/src/svelte/shared/components/tab.svelte @@ -2,6 +2,8 @@ import { createEventDispatcher, getContext } from "svelte"; const dispatch = createEventDispatcher(); + export let draggable = false; + const id = generateUUID(); const selectedTab = getContext("selectedTab") as Writable; const registerTab = getContext("registerTab") as (id: string) => void; @@ -22,6 +24,18 @@ }; }); + function handleDragStart(event: Event) { + dispatch("dragstart", { nativeEvent: event }); + } + + function handleDragOver(event: Event) { + dispatch("dragover", { nativeEvent: event }); + } + + function handleDrop(event: Event) { + dispatch("drop", { nativeEvent: event }); + } + function handleClick(event: Event) { selectedTab.set(id); dispatch("click", { nativeEvent: event }); @@ -47,11 +61,22 @@ } - +
(e.key === "Enter" || e.key === " ") && handleClick(e)} +> + +