Skip to content

Commit

Permalink
Updates for Obsidian 1.6+
Browse files Browse the repository at this point in the history
- Restore view header icon for maximized panes
- Don't hotfix Obsidian theme adaptation on 1.6+ (Fix #60)
- Drop some code that was only needed for pre-1.0 Obsidian
  • Loading branch information
pjeby committed Jan 18, 2025
1 parent 313ef66 commit 100fb56
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 80 deletions.
2 changes: 1 addition & 1 deletion manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"id": "pane-relief",
"name": "Pane Relief",
"version": "0.5.6",
"version": "0.5.7",
"minAppVersion": "1.5.8",
"description": "Per-tab history, hotkeys for pane/tab movement, navigation, sliding workspace, and more",
"author": "PJ Eby",
Expand Down
76 changes: 8 additions & 68 deletions src/History.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import {HistoryState, Notice, requireApiVersion, TAbstractFile, WorkspaceLeaf} from 'obsidian';
import {around} from "monkey-around";
import {LayoutStorage, Service, windowEvent} from "@ophidian/core";
import { HistoryState, Notice, TAbstractFile, WorkspaceLeaf } from 'obsidian';
import { around } from "monkey-around";
import { LayoutStorage, Service } from "@ophidian/core";
import { leafName } from './pane-relief';
import { formatState } from './Navigator';

const HIST_ATTR = "pane-relief:history-v1";
const SERIAL_PROP = "pane-relief:history-v1";
export const hasTabHistory = requireApiVersion("0.16.3");

declare module "obsidian" {
interface Workspace {
Expand Down Expand Up @@ -162,7 +161,6 @@ export class History {

pos: number
stack: HistoryEntry[]
hadTabs = hasTabHistory;

constructor(public leaf?: WorkspaceLeaf, {pos, stack}: SerializableHistory = {pos:0, stack:[]}) {
if (leaf) leaf[HIST_ATTR] = this; // prevent recursive lookups
Expand All @@ -173,7 +171,7 @@ export class History {

saveToNative(): this {
const nativeHistory = this.leaf?.history;
if (!nativeHistory || !hasTabHistory) return this;
if (!nativeHistory) return this;
const stack = this.stack.map(entry => entry.asNative);
nativeHistory.deserialize({
backHistory: stack.slice(this.pos+1).reverse(),
Expand All @@ -184,7 +182,7 @@ export class History {

loadFromNative(): this {
const history = this.leaf?.history;
if (!history || !hasTabHistory) return this;
if (!history) return this;
const stack: typeof history.backHistory = [].concat(
history.forwardHistory.slice().filter(s => s),
{state: {}, eState: {}},
Expand Down Expand Up @@ -232,7 +230,7 @@ export class History {
// prevent wraparound
const newPos = Math.max(0, Math.min(this.pos - by, this.stack.length - 1));
if (force || newPos !== this.pos) {
if (this.leaf.history && hasTabHistory) {
if (this.leaf.history) {
this.pos = newPos;
this.leaf.history.go(by);
} else this.goto(newPos);
Expand Down Expand Up @@ -280,7 +278,7 @@ export class HistoryManager extends Service {
}
}));

if (hasTabHistory) {
if (true) {
// Forward native tab history events to our own implementation
this.register(around(WorkspaceLeaf.prototype, {
trigger(old) { return function trigger(name, ...data) {
Expand All @@ -294,65 +292,7 @@ export class HistoryManager extends Service {
}));

// Incorporate any prior history state (e.g. on plugin update)
if (app.workspace.layoutReady) app.workspace.iterateAllLeaves(leaf => { History.forLeaf(leaf); })

// Skip most actual history replacement if native history is tab-based
return;
app.workspace.onLayoutReady(() => app.workspace.iterateAllLeaves(leaf => { leaf.trigger("history-change") }))
}

// Monkeypatch: check for popstate events (to suppress them)
this.register(around(WorkspaceLeaf.prototype, {
setViewState(old) { return function setViewState(vs, es){
if (vs.popstate && window.event?.type === "popstate") {
return Promise.resolve();
}
return old.call(this, vs, es);
}}
}));

this.register(around(app.workspace, {
// Monkeypatch: keep Obsidian from pushing history in setActiveLeaf
setActiveLeaf(old) { return function setActiveLeaf(leaf, ...etc: any[]) {
const unsub = around(this, {
recordHistory(old) { return function (leaf: WorkspaceLeaf, _push: boolean, ...args: any[]) {
// Always update state in place
return old.call(this, leaf, false, ...args);
}; }
});
try {
return old.call(this, leaf, ...etc);
} finally {
unsub();
}
}},
}));

function isSyntheticHistoryEvent(button: number) {
return !!windowEvent((_, event) => {
if (event.type === "mousedown" && (event as MouseEvent).button === button) {
event.preventDefault();
event.stopImmediatePropagation();
return true;
}
});
}

// Proxy the window history with a wrapper that delegates to the active leaf's History object,
const realHistory = window.history;
this.register(() => (window as any).history = realHistory);
Object.defineProperty(window, "history", { enumerable: true, configurable: true, writable: true, value: {
get state() { return History.current().state; },
get length() { return History.current().length; },

back() { if (!isSyntheticHistoryEvent(3)) this.go(-1); },
forward() { if (!isSyntheticHistoryEvent(4)) this.go( 1); },
go(by: number) { History.current().go(by); },

replaceState(state: PushState, title: string, url: string){ History.current().replaceState(state, title, url); },
pushState(state: PushState, title: string, url: string) { History.current().pushState(state, title, url); },

get scrollRestoration() { return realHistory.scrollRestoration; },
set scrollRestoration(val) { realHistory.scrollRestoration = val; },
}});
}
}
12 changes: 7 additions & 5 deletions src/Navigator.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {Menu, Keymap, Component, WorkspaceLeaf, TFile, MenuItem, requireApiVersion, WorkspaceTabs, debounce} from 'obsidian';
import {domLeaves, hasTabHistory, History, HistoryEntry} from "./History";
import {domLeaves, History, HistoryEntry} from "./History";
import {PerWindowComponent} from "@ophidian/core";
import {around} from 'monkey-around';

Expand Down Expand Up @@ -40,7 +40,7 @@ declare module "obsidian" {
}

const adaptTheme = debounce(() => {
if (app.vault.getConfig("theme") === "system") app.adaptToSystemTheme();
if (app.vault.getConfig("theme") === "system") app.adaptToSystemTheme?.();
}, 200, true);

interface FileInfo {
Expand Down Expand Up @@ -152,7 +152,9 @@ export class Navigation extends PerWindowComponent {
return false;
}

this.registerDomEvent(this.win.matchMedia("(prefers-color-scheme: dark)") as any, "change", adaptTheme);
// Workaround for https://forum.obsidian.md/t/detached-window-doesnt-change-color-scheme-automatically/42642/10
// (which was fixed in Obsidian 1.6)
requireApiVersion("1.6.0") || this.registerDomEvent(this.win.matchMedia("(prefers-color-scheme: dark)") as any, "change", adaptTheme);

app.workspace.onLayoutReady(() => {
this.addChild(this.back = new Navigator(this, "back", -1));
Expand Down Expand Up @@ -196,7 +198,7 @@ export class Navigation extends PerWindowComponent {
if (back) this.back.updateDisplay(history, back);

// Add labels for 0.16.3 Tab headers
if (hasTabHistory) {
if (true) {
const actions = leaf.containerEl.find(".view-header > .view-header-nav-buttons");
const fwd = actions?.find('button:last-child');
const back = actions?.find('button:first-child');
Expand Down Expand Up @@ -343,7 +345,7 @@ export class Navigator extends Component {
i.setIcon(info.icon).setTitle(prefix + info.title).onClick(e => {
// Check for ctrl/cmd/middle button and split leaf + copy history
if (Keymap.isModEvent(e)) {
if (hasTabHistory && history.leaf) {
if (history.leaf) {
// Use the new duplication API because native history doesn't store current state
app.workspace.duplicateLeaf(history.leaf, Keymap.isModEvent(e)).then(leaf => {
History.forLeaf(leaf).go((idx+1) * dir, true);
Expand Down
32 changes: 30 additions & 2 deletions src/maximizing.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Service, toggleClass } from "@ophidian/core";
import { around } from "monkey-around";
import { debounce, requireApiVersion, WorkspaceLeaf, WorkspaceTabs } from "obsidian";
import { debounce, requireApiVersion, WorkspaceLeaf, WorkspaceTabs, ItemView, setIcon, setTooltip, View } from "obsidian";
import { isMain } from "./focus-lock";

declare module "obsidian" {
Expand Down Expand Up @@ -73,6 +73,23 @@ export class Maximizer extends Service {
}
}));
})

// Restore pre-1.6 view header icons so you can drag maximized views
this.register(around(ItemView.prototype, {
load(old) {
return function(this: View) {
if (!this.iconEl) {
const iconEl = this.iconEl = this.headerEl.createDiv("clickable-icon view-header-icon")
this.headerEl.prepend(iconEl)
iconEl.draggable = true
iconEl.addEventListener("dragstart", e => { this.app.workspace.onDragLeaf(e, this.leaf) })
setIcon(iconEl, this.getIcon())
setTooltip(iconEl, "Drag to rearrange")
}
return old.call(this)
}
}
}))
}

onunload() {
Expand Down Expand Up @@ -169,4 +186,15 @@ export class Maximizer extends Service {
return el?.matchParent(".workspace, .hover-popover > .popover-content > .workspace-split");
}

}
}

declare module "obsidian" {
interface Workspace {
onDragLeaf(event: MouseEvent, leaf: WorkspaceLeaf): void;
}
interface View {
iconEl: HTMLElement;
headerEl: HTMLElement;
}
export function setTooltip(el: HTMLElement, tooltip: string, options?: TooltipOptions): void;
}
17 changes: 15 additions & 2 deletions src/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,19 @@ body > .popover.hover-popover .workspace-split.should-maximize
}
}

/* Restore 1.5.x view header icons (for maximized views) */
.view-header .view-header-icon {
display: none;
padding: var(--size-2-2);
margin-right: var(--size-2-3);
color: var(--text-muted);
align-self: center;
cursor: grab;
}
.view-header .view-header-icon:active {
cursor: grabbing;
}

#pr-maximize-sb-toggle {
display: none;
position: fixed;
Expand Down Expand Up @@ -288,7 +301,7 @@ body.pane-relief-pane-numbering {
/* Number panes in their headers */
.workspace-split .workspace-leaf .view-header-icon { min-width: fit-content; display: inherit; }
.workspace-split .workspace-leaf .view-header-icon::before,
.workspace-split .workspace-leaf .view-header-left .view-header-nav-buttons::before
.workspace-split .workspace-leaf .view-header-left:first-child .view-header-nav-buttons::before
{
content: "";
display: inline-flex;
Expand All @@ -297,7 +310,7 @@ body.pane-relief-pane-numbering {
bottom: var(--pr-pane-number-bottom);
}
.workspace-split .workspace-leaf.has-pane-relief-label .view-header-icon::before,
.workspace-split .workspace-leaf.has-pane-relief-label .view-header-left .view-header-nav-buttons::before
.workspace-split .workspace-leaf.has-pane-relief-label .view-header-left:first-child .view-header-nav-buttons::before
{
counter-reset: pane-number var(--pane-relief-label);
content: counter(pane-number);
Expand Down
3 changes: 1 addition & 2 deletions versions.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
{
"0.5.6": "1.5.8",
"0.5.5": "1.5.8",
"0.5.7": "1.5.8",
"0.5.2": "1.3.5",
"0.5.1": "1.2.8",
"0.4.2": "0.15.9",
Expand Down

0 comments on commit 100fb56

Please sign in to comment.