mirror of
https://github.com/grub-basket/SP.git
synced 2026-07-22 07:46:27 +00:00
0.133.0: closing a Stashpad-opened tab returns to the tab you came from (search results + aggregate/trash views)
This commit is contained in:
parent
c2a3567e34
commit
b5afc87d38
8 changed files with 150 additions and 140 deletions
146
main.js
146
main.js
File diff suppressed because one or more lines are too long
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"id": "stashpad",
|
||||
"name": "Stashpad",
|
||||
"version": "0.132.0",
|
||||
"version": "0.133.0",
|
||||
"minAppVersion": "1.13.0",
|
||||
"description": "A chat-style, nested-notes workspace: rapid capture, outliner navigation, fast search, tasks, and per-folder templates, with one-click Open Knowledge Format (OKF) export for LLMs and agents.",
|
||||
"author": "Human",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "stashpad-obsidian",
|
||||
"version": "0.132.0",
|
||||
"version": "0.133.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "node esbuild.config.mjs",
|
||||
|
|
|
|||
17
release-notes/0.133.0.md
Normal file
17
release-notes/0.133.0.md
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# 0.133.0 — Closing a Stashpad-opened tab returns you to the tab you came from
|
||||
|
||||
Opening a note in the editor already returned focus to the originating Stashpad
|
||||
tab when that editor tab was closed. This release makes the same behavior
|
||||
universal: **search results and the aggregate views now do it too.**
|
||||
|
||||
- **Search results** — opening a search hit in a new tab and then closing it now
|
||||
returns you to the tab you searched from, instead of Obsidian's default of
|
||||
jumping to the tab on the right.
|
||||
- **Aggregate views** — the same return-to-origin behavior on close for the
|
||||
**All encrypted**, **All archived**, and **All tasks** views, plus the **Trash**
|
||||
view. Works whether the view was opened from a Stashpad tab or the command
|
||||
palette.
|
||||
|
||||
Internally, the return-to-origin logic (previously duplicated across the
|
||||
editor-open, new-Stashpad-tab, and folder-open paths) is now a single shared
|
||||
helper, so every current and future tab-opener behaves consistently.
|
||||
|
|
@ -3,6 +3,7 @@ import type StashpadPlugin from "./main";
|
|||
import { STASHPAD_AGGREGATE_VIEW_TYPE } from "./types";
|
||||
import { renderTaskTriage, defaultTaskTriageState, type TaskTriageState } from "./task-render";
|
||||
import { renderAggModeBar, type AggMode } from "./agg-modes";
|
||||
import { returnToOriginOnClose } from "./leaf-return";
|
||||
|
||||
// Obsidian types `moment` as a namespace (not callable); cast to a callable.
|
||||
const momentFn = moment as unknown as (...args: unknown[]) => { fromNow: () => string };
|
||||
|
|
@ -256,7 +257,11 @@ export async function openAggregateView(plugin: StashpadPlugin, mode: AggregateM
|
|||
const existing = workspace.getLeavesOfType(STASHPAD_AGGREGATE_VIEW_TYPE)
|
||||
.find((l) => (l.view as StashpadAggregateView)?.getState?.().mode === mode);
|
||||
if (existing) { workspace.revealLeaf(existing); return; }
|
||||
// 0.133.0: remember the tab we opened from so closing this aggregate view
|
||||
// returns there, not to the tab on the right.
|
||||
const originLeaf = workspace.getMostRecentLeaf();
|
||||
const leaf = workspace.getLeaf("tab");
|
||||
await leaf.setViewState({ type: STASHPAD_AGGREGATE_VIEW_TYPE, active: true, state: { mode } });
|
||||
workspace.revealLeaf(leaf);
|
||||
returnToOriginOnClose(workspace, leaf, originLeaf);
|
||||
}
|
||||
|
|
|
|||
36
src/leaf-return.ts
Normal file
36
src/leaf-return.ts
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
import type { Workspace, WorkspaceLeaf, EventRef } from "obsidian";
|
||||
|
||||
/** Restore focus to `originLeaf` when `newLeaf` closes, instead of letting
|
||||
* Obsidian fall back to the tab on the right. One-shot: the listener detaches
|
||||
* itself the moment the spawned leaf is gone.
|
||||
*
|
||||
* Shared by every Stashpad new-tab opener — edit-in-editor, "open in new
|
||||
* Stashpad tab", search-in-context, and the aggregate / trash / archive /
|
||||
* tasks views — so "close this tab, land back where I came from" is universal.
|
||||
*
|
||||
* No-ops when there's no distinct origin (origin missing, or identical to the
|
||||
* spawned leaf) — e.g. an aggregate view opened from the command palette with
|
||||
* nothing else in the main area. In that case Obsidian's default stands. */
|
||||
export function returnToOriginOnClose(
|
||||
ws: Workspace,
|
||||
newLeaf: WorkspaceLeaf,
|
||||
originLeaf: WorkspaceLeaf | null,
|
||||
): void {
|
||||
if (!originLeaf || originLeaf === newLeaf) return;
|
||||
const isOpen = (target: WorkspaceLeaf): boolean => {
|
||||
let found = false;
|
||||
ws.iterateAllLeaves((l) => { if (l === target) found = true; });
|
||||
return found;
|
||||
};
|
||||
const off: EventRef = ws.on("active-leaf-change", () => {
|
||||
// Spawned tab still around (user just switched away from it) — leave it.
|
||||
if (isOpen(newLeaf)) return;
|
||||
// Spawned tab closed. Detach this listener and, if the origin tab is still
|
||||
// open, make it active instead of whatever Obsidian picked (the right tab).
|
||||
ws.offref(off);
|
||||
if (isOpen(originLeaf)) {
|
||||
ws.setActiveLeaf(originLeaf, { focus: true });
|
||||
ws.revealLeaf(originLeaf);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@ import { STASHPAD_TRASH_VIEW_TYPE } from "./types";
|
|||
import { ConfirmModal } from "./modals";
|
||||
import type { DeletedMeta } from "./encryption-ops";
|
||||
import { renderAggModeBar, type AggMode } from "./agg-modes";
|
||||
import { returnToOriginOnClose } from "./leaf-return";
|
||||
|
||||
// Obsidian types `moment` as the namespace (not callable); cast to a callable.
|
||||
const momentFn = moment as unknown as (...args: unknown[]) => { fromNow: () => string };
|
||||
|
|
@ -288,7 +289,10 @@ export async function openTrashView(plugin: StashpadPlugin): Promise<void> {
|
|||
const { workspace } = plugin.app;
|
||||
const existing = workspace.getLeavesOfType(STASHPAD_TRASH_VIEW_TYPE);
|
||||
if (existing.length > 0) { workspace.revealLeaf(existing[0]); return; }
|
||||
// 0.133.0: closing the trash view returns to the tab it was opened from.
|
||||
const originLeaf = workspace.getMostRecentLeaf();
|
||||
const leaf = workspace.getLeaf("tab");
|
||||
await leaf.setViewState({ type: STASHPAD_TRASH_VIEW_TYPE, active: true });
|
||||
workspace.revealLeaf(leaf);
|
||||
returnToOriginOnClose(workspace, leaf, originLeaf);
|
||||
}
|
||||
|
|
|
|||
78
src/view.ts
78
src/view.ts
|
|
@ -28,6 +28,7 @@ import { matchBinding, humanCombo } from "./view-keys";
|
|||
import { AuthorshipTracker } from "./authorship-tracker";
|
||||
import { ViewDnD } from "./view-dnd";
|
||||
import { NoteBodyRenderer } from "./note-body-renderer";
|
||||
import { returnToOriginOnClose } from "./leaf-return";
|
||||
import { computeSortedIds } from "./view-sort";
|
||||
import {
|
||||
SHEET_KEY,
|
||||
|
|
@ -8966,27 +8967,9 @@ export class StashpadView extends ItemView {
|
|||
});
|
||||
ws.setActiveLeaf(leaf, { focus: true });
|
||||
ws.revealLeaf(leaf);
|
||||
// 0.57.5: same return-to-origin one-shot as openFolderInNewTab /
|
||||
// openFileAtEnd — when this spawned tab closes, the originating
|
||||
// Stashpad tab regains focus.
|
||||
const off = ws.on("active-leaf-change", () => {
|
||||
const stillOpen = (() => {
|
||||
let found = false;
|
||||
ws.iterateAllLeaves((l) => { if (l === leaf) found = true; });
|
||||
return found;
|
||||
})();
|
||||
if (stillOpen) return;
|
||||
ws.offref(off);
|
||||
const originStillOpen = (() => {
|
||||
let found = false;
|
||||
ws.iterateAllLeaves((l) => { if (l === originLeaf) found = true; });
|
||||
return found;
|
||||
})();
|
||||
if (originStillOpen) {
|
||||
ws.setActiveLeaf(originLeaf, { focus: true });
|
||||
ws.revealLeaf(originLeaf);
|
||||
}
|
||||
});
|
||||
// 0.57.5: when this spawned tab closes, the originating Stashpad tab
|
||||
// regains focus (see returnToOriginOnClose — shared by every opener).
|
||||
returnToOriginOnClose(ws, leaf, originLeaf);
|
||||
}
|
||||
|
||||
/** Open a Stashpad folder's home in a new tab (any folder, not just
|
||||
|
|
@ -9006,6 +8989,7 @@ export class StashpadView extends ItemView {
|
|||
if (!cleaned || !noteId) return;
|
||||
const settingsFolder = (this.plugin.settings.folder || "Stashpad").trim().replace(/^\/+|\/+$/g, "") || "Stashpad";
|
||||
const ws = this.app.workspace;
|
||||
const originLeaf = this.leaf;
|
||||
const leaf = ws.getLeaf("tab");
|
||||
await leaf.setViewState({
|
||||
type: STASHPAD_VIEW_TYPE,
|
||||
|
|
@ -9020,6 +9004,9 @@ export class StashpadView extends ItemView {
|
|||
});
|
||||
ws.setActiveLeaf(leaf, { focus: true });
|
||||
ws.revealLeaf(leaf);
|
||||
// 0.133.0: closing the search-opened tab returns to the tab you searched
|
||||
// from, not the tab to the right.
|
||||
returnToOriginOnClose(ws, leaf, originLeaf);
|
||||
}
|
||||
|
||||
private async openFolderInNewTab(folder: string): Promise<void> {
|
||||
|
|
@ -9041,27 +9028,8 @@ export class StashpadView extends ItemView {
|
|||
});
|
||||
ws.setActiveLeaf(leaf, { focus: true });
|
||||
ws.revealLeaf(leaf);
|
||||
|
||||
// One-shot: when the spawned leaf closes, restore focus to the
|
||||
// originating Stashpad tab.
|
||||
const off = ws.on("active-leaf-change", () => {
|
||||
const stillOpen = (() => {
|
||||
let found = false;
|
||||
ws.iterateAllLeaves((l) => { if (l === leaf) found = true; });
|
||||
return found;
|
||||
})();
|
||||
if (stillOpen) return;
|
||||
ws.offref(off);
|
||||
const originStillOpen = (() => {
|
||||
let found = false;
|
||||
ws.iterateAllLeaves((l) => { if (l === originLeaf) found = true; });
|
||||
return found;
|
||||
})();
|
||||
if (originStillOpen) {
|
||||
ws.setActiveLeaf(originLeaf, { focus: true });
|
||||
ws.revealLeaf(originLeaf);
|
||||
}
|
||||
});
|
||||
// When the spawned leaf closes, restore focus to the originating tab.
|
||||
returnToOriginOnClose(ws, leaf, originLeaf);
|
||||
}
|
||||
|
||||
// --- Open shortcuts ---
|
||||
|
|
@ -9103,29 +9071,9 @@ export class StashpadView extends ItemView {
|
|||
ws.setActiveLeaf(leaf, { focus: true });
|
||||
ws.revealLeaf(leaf);
|
||||
|
||||
// One-shot listener: when the active leaf changes AND our edit leaf is
|
||||
// no longer in the workspace (closed), reveal the originating Stashpad
|
||||
// leaf instead of whatever Obsidian picked.
|
||||
const off = ws.on("active-leaf-change", () => {
|
||||
const stillOpen = (() => {
|
||||
let found = false;
|
||||
ws.iterateAllLeaves((l) => { if (l === leaf) found = true; });
|
||||
return found;
|
||||
})();
|
||||
if (stillOpen) return;
|
||||
// Edit leaf is gone. Detach this listener and (if the origin leaf
|
||||
// is still around) make it active.
|
||||
ws.offref(off);
|
||||
const originStillOpen = (() => {
|
||||
let found = false;
|
||||
ws.iterateAllLeaves((l) => { if (l === originLeaf) found = true; });
|
||||
return found;
|
||||
})();
|
||||
if (originStillOpen) {
|
||||
ws.setActiveLeaf(originLeaf, { focus: true });
|
||||
ws.revealLeaf(originLeaf);
|
||||
}
|
||||
});
|
||||
// When the edit tab closes, reveal the originating Stashpad leaf instead
|
||||
// of whatever Obsidian picked (the tab to the right).
|
||||
returnToOriginOnClose(ws, leaf, originLeaf);
|
||||
|
||||
const view: any = leaf.view;
|
||||
const editor: any = view?.editor;
|
||||
|
|
|
|||
Loading…
Reference in a new issue