Skip to content

Commit

Permalink
auto scroll to view cuw
Browse files Browse the repository at this point in the history
  • Loading branch information
oxdc committed Jan 15, 2025
1 parent e9d9b17 commit 6f40b33
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 4 deletions.
11 changes: 10 additions & 1 deletion src/components/NavigationContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { NavigationContent } from "./NavigationContent";
import { NavigationHeader } from "./NavigationHeader";
import { REFRESH_TIMEOUT, useTabCache } from "src/models/TabCache";
import {
REFRESH_TIMEOUT,
REFRESH_TIMEOUT_LONG,
useTabCache,
} from "src/models/TabCache";
import { usePlugin, useSettings } from "src/models/PluginContext";
import { useEffect, useRef } from "react";
import { useViewState } from "src/models/ViewState";
Expand Down Expand Up @@ -41,6 +45,7 @@ export const NavigationContainer = () => {
decreaseViewCueOffset,
modifyViewCueCallback,
resetViewCueCallback,
scorllToViewCueFirstTab,
} = useViewState();
const { loadSettings, toggleZenMode, updateEphemeralTabs } = useSettings();

Expand Down Expand Up @@ -161,6 +166,10 @@ export const NavigationContainer = () => {
if (ref.current) {
ref.current.toggleClass("tab-index-view-cue", true);
}
setTimeout(
() => scorllToViewCueFirstTab(app),
REFRESH_TIMEOUT_LONG
);
}
});
plugin.registerDomEvent(window, "keyup", () => {
Expand Down
10 changes: 9 additions & 1 deletion src/components/Tab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
closeTabsToTopInGroup,
} from "src/services/CloseTabs";
import { REFRESH_TIMEOUT, useTabCache } from "src/models/TabCache";
import { useViewState } from "src/models/ViewState";
import { useViewState, VIEW_CUE_PREV } from "src/models/ViewState";
import { DeduplicatedTitle } from "src/services/DeduplicateTitle";
import {
createBookmarkForLeaf,
Expand Down Expand Up @@ -44,6 +44,7 @@ export const Tab = ({ leaf, index, isLast }: TabProps) => {
toggleHiddenGroup,
hookLatestActiveTab,
mapViewCueIndex,
registerViewCueTab,
} = useViewState();
const [isPinned, setIsPinned] = useState(
leaf.getViewState().pinned ?? false
Expand Down Expand Up @@ -444,6 +445,13 @@ export const Tab = ({ leaf, index, isLast }: TabProps) => {

const viewCueIndex = mapViewCueIndex(index, isLast);

useEffect(() => {
const isFirstTab =
viewCueIndex === VIEW_CUE_PREV ||
(viewCueIndex === index && index === 1);
registerViewCueTab(leaf, ref.current, isFirstTab);
}, [viewCueIndex, ref]);

const previewTab = (
event: React.MouseEvent<HTMLDivElement, MouseEvent>
) => {
Expand Down
56 changes: 54 additions & 2 deletions src/models/ViewState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,13 @@ export type ViewCueIndex = number | string | undefined;
export const MIN_INDEX_KEY = 1;
export const MAX_INDEX_KEY = 8;
export const LAST_INDEX_KEY = 9;
export const VIEW_CUE_NEXT = "→";
export const VIEW_CUE_PREV = "←";
export type ViewCueNativeCallback = CommandCheckCallback;
export type ViewCueNativeCallbackMap = Map<number, ViewCueNativeCallback>;
export type ViewCueFirstTabs = DefaultRecord<Identifier, HTMLElement | null>;
export const createNewViewCueFirstTabs = () =>
new DefaultRecord(() => null) as ViewCueFirstTabs;

interface ViewState {
groupTitles: GroupTitles;
Expand All @@ -67,6 +72,7 @@ interface ViewState {
hasCtrlKeyPressed: boolean;
viewCueOffset: number;
viewCueNativeCallbacks: ViewCueNativeCallbackMap;
viewCueFirstTabs: ViewCueFirstTabs;
clear: () => void;
setGroupTitle: (id: Identifier, name: string) => void;
toggleCollapsedGroup: (id: Identifier, isCollapsed: boolean) => void;
Expand Down Expand Up @@ -133,6 +139,12 @@ interface ViewState {
) => boolean | void;
modifyViewCueCallback: (app: App) => void;
resetViewCueCallback: (app: App) => void;
registerViewCueTab: (
leaf: WorkspaceLeaf,
tab: HTMLElement | null,
isFirst: boolean
) => void;
scorllToViewCueFirstTab: (app: App) => void;
}

const saveViewState = (titles: GroupTitles) => {
Expand Down Expand Up @@ -222,6 +234,7 @@ export const useViewState = create<ViewState>()((set, get) => ({
hasCtrlKeyPressed: false,
viewCueOffset: 0,
viewCueNativeCallbacks: new Map(),
viewCueFirstTabs: createNewViewCueFirstTabs(),
leftButtonClone: null,
rightButtonClone: null,
topLeftContainer: null,
Expand Down Expand Up @@ -566,9 +579,9 @@ export const useViewState = create<ViewState>()((set, get) => ({
} else if (isLast) {
return LAST_INDEX_KEY;
} else if (userIndex === MAX_INDEX_KEY + 1) {
return "→";
return VIEW_CUE_NEXT;
} else if (userIndex === MIN_INDEX_KEY - 1) {
return "←";
return VIEW_CUE_PREV;
}
},
convertBackToRealIndex(
Expand Down Expand Up @@ -632,4 +645,43 @@ export const useViewState = create<ViewState>()((set, get) => ({
}
}
},
registerViewCueTab(
leaf: WorkspaceLeaf,
tab: HTMLElement | null,
isFirst: boolean
) {
const { viewCueFirstTabs } = get();
if (isFirst && tab) viewCueFirstTabs.set(leaf.id, tab);
else viewCueFirstTabs.delete(leaf.id);
set({ viewCueFirstTabs });
},
scorllToViewCueFirstTab(app: App) {
const { latestActiveLeaf, viewCueFirstTabs } = get();
let targetTab: HTMLElement | null = null;
if (!latestActiveLeaf && viewCueFirstTabs.size === 1) {
// If latestActiveLeaf is not set and viewCueFirstTabs has only one entry,
// we should scroll to that tab
targetTab = viewCueFirstTabs.values().next().value;
} else if (latestActiveLeaf) {
// If latestActiveLeaf is set, we should scroll to the tab that has the
// same parent as the latestActiveLeaf
const activeGroup = latestActiveLeaf.parent;
if (!activeGroup) return;
for (const [id, tab] of viewCueFirstTabs) {
const leaf = app.workspace.getLeafById(id);
if (!leaf || !tab || !leaf.parent) continue;
if (activeGroup.id === leaf.parent.id) {
targetTab = tab;
break;
}
}
}
if (targetTab) {
targetTab.scrollIntoView({
behavior: "smooth",
block: "start",
inline: "nearest",
});
}
},
}));

0 comments on commit 6f40b33

Please sign in to comment.