Skip to content

Commit

Permalink
workaround for #35
Browse files Browse the repository at this point in the history
  • Loading branch information
oxdc committed Sep 16, 2024
1 parent 90158ad commit 267ceb4
Show file tree
Hide file tree
Showing 12 changed files with 98 additions and 40 deletions.
2 changes: 1 addition & 1 deletion src/components/Group.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export const Group = ({ type, children, group }: GroupProps) => {
const toggleCollapsed = () => setIsCollapsed(!isCollapsed);
const toggleHidden = () => {
if (isSidebar) return;
if (group) toggleHiddenGroup(group.id, !isHidden);
if (group) toggleHiddenGroup(app, group.id, !isHidden);
workspace.trigger("vertical-tabs:update-toggle");
};
useEffect(() => {
Expand Down
53 changes: 35 additions & 18 deletions src/components/NavigationContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,24 @@ import {
useSensor,
useSensors,
} from "@dnd-kit/core";
import { useApp } from "src/models/PluginContext";
import { useApp, useSettings } from "src/models/PluginContext";
import { useState } from "react";
import { CssClasses, toClassName } from "src/utils/CssClasses";
import { SortableContext } from "@dnd-kit/sortable";
import { createPortal } from "react-dom";
import * as VT from "src/models/VTWorkspace";
import { moveTab, moveTabToEnd, moveTabToNewGroup } from "src/services/MoveTab";
import {
isSelfContainedInGroup,
moveTab,
moveTabToEnd,
moveTabToNewGroup,
} from "src/services/MoveTab";
import { TabSlot } from "./TabSlot";
import { GroupSlot } from "./GroupSlot";

export const NavigationContent = () => {
const { groupIDs, content, swapGroup } = useTabCache();
const excludeSelf = useSettings.use.excludeSelf();
const app = useApp();
const sensors = useSensors(
useSensor(PointerSensor, {
Expand Down Expand Up @@ -96,6 +102,13 @@ export const NavigationContent = () => {
return content.get(groupID);
};

const hasOnlySelf = (groupID: VT.Identifier): boolean => {
return (
isSelfContainedInGroup(app, groupID) &&
content.get(groupID).leafIDs.length == 1
);
};

return (
<div className={toClassName(rootContainerClasses)}>
<div className={toClassName(containerClasses)}>
Expand All @@ -106,22 +119,26 @@ export const NavigationContent = () => {
onDragEnd={handleDragEnd}
>
<SortableContext items={getGroupIDs()}>
{groupIDs.map((groupID) => (
<Group
key={groupID}
type={entryOf(groupID).groupType}
group={entryOf(groupID).group}
>
<SortableContext items={getLeaveIDs(groupID)}>
{entryOf(groupID).leaves.map((leaf) => (
<Tab key={leaf.id} leaf={leaf} />
))}
{isDragging && !isDraggingGroup && (
<TabSlot groupID={groupID} />
)}
</SortableContext>
</Group>
))}
{groupIDs.map((groupID) =>
hasOnlySelf(groupID) && excludeSelf ? null : (
<Group
key={groupID}
type={entryOf(groupID).groupType}
group={entryOf(groupID).group}
>
<SortableContext
items={getLeaveIDs(groupID)}
>
{entryOf(groupID).leaves.map((leaf) => (
<Tab key={leaf.id} leaf={leaf} />
))}
{isDragging && !isDraggingGroup && (
<TabSlot groupID={groupID} />
)}
</SortableContext>
</Group>
)
)}
<GroupSlot />
</SortableContext>
{createPortal(<DragOverlay />, document.body)}
Expand Down
2 changes: 2 additions & 0 deletions src/components/NavigationTreeItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ interface NavigationTreeItemProps {
title: string | React.ReactNode;
icon: string;
isTab: boolean;
isSelf?: boolean;
isTabSlot?: boolean;
isGroupSlot?: boolean;
isActive?: boolean;
Expand Down Expand Up @@ -49,6 +50,7 @@ export const NavigationTreeItem = (props: NavigationTreeItemProps) => {
const itemElClasses: CssClasses = {
"tree-item": true,
"is-tab": props.isTab,
"is-self": props.isTab && props.isSelf,
"is-group": !props.isTab,
"is-pinned": props.isPinned,
"is-collapsed": props.isCollapsed,
Expand Down
6 changes: 5 additions & 1 deletion src/components/Tab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
} from "src/services/CloseTabs";
import { useTabCache } from "src/models/TabCache";
import { useViewState } from "src/models/ViewState";
import { VIEW_TYPE } from "src/navigation";

interface TabProps {
leaf: VT.WorkspaceLeaf;
Expand Down Expand Up @@ -55,7 +56,7 @@ export const Tab = ({ leaf }: TabProps) => {
const workspace = plugin.app.workspace as VT.Workspace;
workspace.setActiveLeaf(leaf, { focus: true });
workspace.onLayoutChange();
toggleHiddenGroup(leaf.parent.id, false);
toggleHiddenGroup(plugin.app, leaf.parent.id, false);
lockFocusOnLeaf(plugin.app, leaf);
};

Expand Down Expand Up @@ -147,10 +148,13 @@ export const Tab = ({ leaf }: TabProps) => {
isActive: leaf.tabHeaderEl?.classList.contains("is-active"),
};

const isSelf = leaf.getViewState().type === VIEW_TYPE;

return (
<NavigationTreeItem
id={leaf.id}
isTab={true}
isSelf={isSelf}
isPinned={isPinned}
isHighlighted={lastActiveLeaf?.id === leaf.id}
{...props}
Expand Down
2 changes: 1 addition & 1 deletion src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export default class ObsidianVerticalTabs extends Plugin {
async updateViewStates() {
this.toggle("vt-hide-sidebars", this.settings.hideSidebars);
this.toggle("vt-show-active-tabs", this.settings.showActiveTabs);
this.toggle("vt-exclude-self", this.settings.sidebarExcludeSelf);
this.toggle("vt-exclude-self", this.settings.excludeSelf);
this.toggle("vt-zen-mode", this.settings.zenMode);
}
}
3 changes: 3 additions & 0 deletions src/models/PluginContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
} from "./PluginSettings";
import { create } from "zustand";
import { createSelectors } from "./Selectors";
import { moveSelfToDefaultLocation } from "src/services/MoveTab";

export type SettingsContext = [Settings, (mutator: SettingsMutator) => void];

Expand Down Expand Up @@ -74,6 +75,8 @@ export const useSettingsBase = create<Settings & SettingsActions>(
},
toggleZenMode() {
get().setSettings({ zenMode: !get().zenMode });
const { plugin } = get();
if (plugin) moveSelfToDefaultLocation(plugin.app);
},
})
);
Expand Down
4 changes: 2 additions & 2 deletions src/models/PluginSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@ interface ObsidianVerticalTabsSettings {
showActiveTabs: boolean;
hideSidebars: boolean;
sidebarTabTypes: string[] | null;
sidebarExcludeSelf: boolean;
excludeSelf: boolean;
zenMode: boolean;
}

export const DEFAULT_SETTINGS: ObsidianVerticalTabsSettings = {
showActiveTabs: true,
hideSidebars: true,
sidebarTabTypes: ["markdown"],
sidebarExcludeSelf: true,
excludeSelf: true,
zenMode: false,
};

Expand Down
4 changes: 4 additions & 0 deletions src/models/VTWorkspace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,7 @@ export interface WorkspaceLeaf extends Obsidian.WorkspaceLeaf {
tabHeaderEl?: HTMLElement;
tabHeaderInnerTitleEl?: HTMLElement;
}

export interface WorkspaceSidedock extends Obsidian.WorkspaceSidedock {
children: WorkspaceParent[];
}
9 changes: 7 additions & 2 deletions src/models/ViewState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ import {
insertLeftSidebarToggle,
insertRightSidebarToggle,
} from "src/services/SidebarToggles";
import {
isSelfContainedInGroup,
moveSelfToDefaultLocation,
} from "src/services/MoveTab";

export const DEFAULT_GROUP_TITLE = "Grouped tabs";
const factory = () => DEFAULT_GROUP_TITLE;
Expand All @@ -36,7 +40,7 @@ interface ViewState {
pinningEvents: PinningEvents;
clear: () => void;
setGroupTitle: (id: VT.Identifier, name: string) => void;
toggleHiddenGroup: (id: VT.Identifier, isHidden: boolean) => void;
toggleHiddenGroup: (app: App, id: VT.Identifier, isHidden: boolean) => void;
setLatestActiveLeaf: (
plugin: ObsidianVerticalTabs,
leaf?: VT.WorkspaceLeaf | null
Expand Down Expand Up @@ -127,9 +131,10 @@ export const useViewState = create<ViewState>()((set, get) => ({
saveViewState(state.groupTitles);
return state;
}),
toggleHiddenGroup: (id: VT.Identifier, isHidden: boolean) => {
toggleHiddenGroup: (app: App, id: VT.Identifier, isHidden: boolean) => {
if (isHidden) {
set((state) => ({ hiddenGroups: [...state.hiddenGroups, id] }));
if (isSelfContainedInGroup(app, id)) moveSelfToDefaultLocation(app);
} else {
set((state) => ({
hiddenGroups: state.hiddenGroups.filter((gid) => gid !== id),
Expand Down
29 changes: 28 additions & 1 deletion src/services/MoveTab.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { App } from "obsidian";
import { App, WorkspaceMobileDrawer, WorkspaceSidedock } from "obsidian";
import * as VT from "../models/VTWorkspace";
import { VIEW_TYPE } from "src/navigation";

function removeChild(parent: VT.WorkspaceParent, index: number) {
parent.children.splice(index, 1);
Expand Down Expand Up @@ -66,3 +67,29 @@ export async function moveTabToNewGroup(app: App, sourceID: VT.Identifier) {
await app.workspace.duplicateLeaf(sourceLeaf, "split", preferredDirection);
sourceLeaf.detach();
}

export function isSelfContainedInGroup(
app: App,
groupID: VT.Identifier
): boolean {
const leaves = app.workspace.getLeavesOfType(VIEW_TYPE);
if (leaves.length === 0) return false;
const self = leaves[0] as VT.WorkspaceLeaf;
return self.parent?.id === groupID;
}

export async function moveSelfToDefaultLocation(app: App) {
const workspace = app.workspace as VT.Workspace;
const leaves = workspace.getLeavesOfType(VIEW_TYPE);
if (leaves.length === 0) return;
const self = leaves[0] as VT.WorkspaceLeaf;
const leftSidebar = workspace.leftSplit;
if (leftSidebar instanceof WorkspaceSidedock) {
const container = leftSidebar as VT.WorkspaceSidedock;
const parent = container.children[0] as VT.WorkspaceParent;
moveTabToEnd(app, self.id, parent);
} else if (leftSidebar instanceof WorkspaceMobileDrawer) {
const parent = leftSidebar.parent as VT.WorkspaceParent;
moveTabToEnd(app, self.id, parent);
}
}
6 changes: 0 additions & 6 deletions src/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,6 @@ body.vt-hide-sidebars
display: none;
}

body.vt-exclude-self
.obsidian-vertical-tabs-container
.tree-item.is-tab[data-type="vertical-tabs"] {
display: none;
}

.obsidian-vertical-tabs-container .tab-slot {
height: 30px;
background-color: var(--background-modifier-border);
Expand Down
18 changes: 10 additions & 8 deletions src/styles/Tab.scss
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
.obsidian-vertical-tabs-container {
.tree-item {
&.is-tab {
&.is-highlighted .tree-item-self {
background-color: var(--background-modifier-active-hover);
}
}
}
.obsidian-vertical-tabs-container
.tree-item.is-tab.is-highlighted
.tree-item-self {
background-color: var(--background-modifier-active-hover);
}

body.vt-exclude-self
.obsidian-vertical-tabs-container
.tree-item.is-tab.is-self {
display: none;
}

0 comments on commit 267ceb4

Please sign in to comment.