Swipe up at bottom of note to run any command, works similar to the mobile Quick Action

Save this as a .js file and point CodeScript ToolKit to it as your “Startup script path.” It’ll make it so you have another mobile Quick Action, essentially. Instead of swiping down when scrolled to the top of a note like the regular mobile Quick Action, you activate this one by swiping up when scrolled to the bottom of a note[1].

Change const COMMAND_ID = "markdown:toggle-preview"; to whatever you want.

To get the command IDs for every command palette command, run
console.log(Object.keys(app.commands.commands))
in Obsidian’s DevTools console
OR
put this in some note. It’ll output without needing to open DevTools. Uses CodeScript Toolkit

```code-button
---
caption: 'All command IDs'
---
console.log(Object.keys(app.commands.commands))
```

JS

exports.invoke = async (app) => {
	const thingsToHookInto = [app?.workspace, app?.workspace?.rootSplit, app?.workspace?.activeLeaf];
	const COMMAND_ID = "markdown:toggle-preview";

	function installSwipeUpHook(thing) {
		const proto = Object.getPrototypeOf(thing);
		if (!proto || typeof proto.trigger !== "function" || proto.__swipe_up_hooked) return;

		const origTrigger = proto.trigger;
		proto.trigger = function (eventName, data) {
			try {
				if (eventName === "swipe" && data?.direction === "y" && data.points === 1) {
					const isUp = data.startY && data.y && data.y < data.startY;
					if (isUp && thing.rootSplit?.containerEl?.contains(data.targetEl)) {
						handleSwipeUp(data);
						return;
					}
				}
			} catch (err) {
				console.error(err);
			}
			return origTrigger.apply(this, arguments);
		};

		proto.__swipe_up_hooked = true;
	}

	function handleSwipeUp(e) {
		const cmd = app.commands.findCommand(COMMAND_ID);
		if (!cmd) return;

		const el = document.body.createDiv({
			cls: "pull-action pull-down-action",
			text: cmd.name,
		});

		el.style.top = "auto";
		el.style.bottom = "0";
		el.style.margin = "0 auto var(--safe-area-inset-bottom) auto";

		const h = el.offsetHeight;
		let progress = 0;
		let activated = false;

		e.registerCallback({
			move: (_, y) => {
				progress = Math.clamp((e.startY - y) / h, 0, 1);
				const fullyPulled = progress === 1;

				el.toggleClass("mod-activated", fullyPulled);
				el.style.transform = `translateY(${progress * -h}px)`;

				if (fullyPulled && !activated) {
					navigator.vibrate?.(100);
					activated = true;
				}

				if (!fullyPulled && activated) {
					activated = false;
				}
			},
			cancel: () => el.detach(),
			finish: () => {
				el.detach();
				if (progress === 1) {
					app.commands.executeCommandById(COMMAND_ID);
				}
			},
		});
	}

	if (app.isMobile && !window.__swipe_up_hook_installed) {
		for (const thing of thingsToHookInto) installSwipeUpHook(thing);
		window.__swipe_up_hook_installed = true;
	}
}

  1. Tangentially related to [Mobile] Dynamic mobile pulldown action using CodeScript Toolkit - Share & showcase - Obsidian Forum. ↩︎

1 Like