mirror of
https://gitlab.com/ArkHost/HelixNotes.git
synced 2026-07-24 07:45:57 +02:00
feat(editor): resizable outline panel (#161)
Add a drag handle to resize the outline panel and persist its width in vault state (outline_width). Outline text now scales with the editor font size. Reviewed-on: https://codeberg.org/ArkHost/HelixNotes/pulls/161
This commit is contained in:
@@ -197,6 +197,10 @@ fn default_true() -> bool {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn default_outline_width() -> f64 {
|
||||||
|
220.0
|
||||||
|
}
|
||||||
|
|
||||||
fn default_pdf_height() -> u32 {
|
fn default_pdf_height() -> u32 {
|
||||||
600
|
600
|
||||||
}
|
}
|
||||||
@@ -298,6 +302,8 @@ pub struct VaultState {
|
|||||||
pub last_open_note: Option<String>,
|
pub last_open_note: Option<String>,
|
||||||
pub sidebar_width: f64,
|
pub sidebar_width: f64,
|
||||||
pub notelist_width: f64,
|
pub notelist_width: f64,
|
||||||
|
#[serde(default = "default_outline_width")]
|
||||||
|
pub outline_width: f64,
|
||||||
pub sidebar_collapsed: bool,
|
pub sidebar_collapsed: bool,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub notelist_collapsed: bool,
|
pub notelist_collapsed: bool,
|
||||||
@@ -333,6 +339,7 @@ impl Default for VaultState {
|
|||||||
last_open_note: None,
|
last_open_note: None,
|
||||||
sidebar_width: 220.0,
|
sidebar_width: 220.0,
|
||||||
notelist_width: 280.0,
|
notelist_width: 280.0,
|
||||||
|
outline_width: default_outline_width(),
|
||||||
sidebar_collapsed: false,
|
sidebar_collapsed: false,
|
||||||
notelist_collapsed: false,
|
notelist_collapsed: false,
|
||||||
collapsed_notebooks: Vec::new(),
|
collapsed_notebooks: Vec::new(),
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
import {
|
import {
|
||||||
sidebarWidth,
|
sidebarWidth,
|
||||||
notelistWidth,
|
notelistWidth,
|
||||||
|
outlineWidth,
|
||||||
sidebarCollapsed,
|
sidebarCollapsed,
|
||||||
notelistCollapsed,
|
notelistCollapsed,
|
||||||
collapsedNotebooks,
|
collapsedNotebooks,
|
||||||
@@ -201,6 +202,7 @@
|
|||||||
last_open_note: $activeNotePath,
|
last_open_note: $activeNotePath,
|
||||||
sidebar_width: $sidebarWidth,
|
sidebar_width: $sidebarWidth,
|
||||||
notelist_width: $notelistWidth,
|
notelist_width: $notelistWidth,
|
||||||
|
outline_width: $outlineWidth,
|
||||||
sidebar_collapsed: $sidebarCollapsed,
|
sidebar_collapsed: $sidebarCollapsed,
|
||||||
notelist_collapsed: $notelistCollapsed,
|
notelist_collapsed: $notelistCollapsed,
|
||||||
collapsed_notebooks: $collapsedNotebooks,
|
collapsed_notebooks: $collapsedNotebooks,
|
||||||
@@ -534,6 +536,7 @@
|
|||||||
$effect(() => {
|
$effect(() => {
|
||||||
$sidebarCollapsed;
|
$sidebarCollapsed;
|
||||||
$notelistCollapsed;
|
$notelistCollapsed;
|
||||||
|
$outlineWidth;
|
||||||
persistState();
|
persistState();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -573,6 +576,7 @@
|
|||||||
const state = await loadVaultState();
|
const state = await loadVaultState();
|
||||||
$sidebarWidth = state.sidebar_width;
|
$sidebarWidth = state.sidebar_width;
|
||||||
$notelistWidth = state.notelist_width;
|
$notelistWidth = state.notelist_width;
|
||||||
|
if (typeof state.outline_width === 'number') $outlineWidth = state.outline_width;
|
||||||
$sidebarCollapsed = state.sidebar_collapsed;
|
$sidebarCollapsed = state.sidebar_collapsed;
|
||||||
$notelistCollapsed = state.notelist_collapsed ?? false;
|
$notelistCollapsed = state.notelist_collapsed ?? false;
|
||||||
$collapsedNotebooks = state.collapsed_notebooks ?? [];
|
$collapsedNotebooks = state.collapsed_notebooks ?? [];
|
||||||
|
|||||||
@@ -39,7 +39,7 @@
|
|||||||
import { readFile } from '@tauri-apps/plugin-fs';
|
import { readFile } from '@tauri-apps/plugin-fs';
|
||||||
import { openFile, openUrl, copyFileTo, copyImageToClipboard as copyImageToClipboardCmd, writeBytesTo, copyPngToClipboard } from '$lib/api';
|
import { openFile, openUrl, copyFileTo, copyImageToClipboard as copyImageToClipboardCmd, writeBytesTo, copyPngToClipboard } from '$lib/api';
|
||||||
import { save as saveDialog } from '@tauri-apps/plugin-dialog';
|
import { save as saveDialog } from '@tauri-apps/plugin-dialog';
|
||||||
import { activeNote, activeNotePath, appConfig, editorDirty, sourceMode, focusMode, readOnly, quickAccessPaths, notes, navHistory, canGoBack, canGoForward, viewerNote, notebooks } from '$lib/stores/app';
|
import { activeNote, activeNotePath, appConfig, editorDirty, sourceMode, focusMode, readOnly, quickAccessPaths, notes, navHistory, canGoBack, canGoForward, viewerNote, notebooks, outlineWidth } from '$lib/stores/app';
|
||||||
import { saveNote, saveImage, saveAttachment, readClipboardImage, addQuickAccess, removeQuickAccess, getQuickAccess, getNoteVersions, getNoteVersionContent, createVersion, aiAsk, getAllNoteTitles, readNote, renameNote } from '$lib/api';
|
import { saveNote, saveImage, saveAttachment, readClipboardImage, addQuickAccess, removeQuickAccess, getQuickAccess, getNoteVersions, getNoteVersionContent, createVersion, aiAsk, getAllNoteTitles, readNote, renameNote } from '$lib/api';
|
||||||
import type { VersionEntry, AiStreamEvent, NoteTitleEntry } from '$lib/types';
|
import type { VersionEntry, AiStreamEvent, NoteTitleEntry } from '$lib/types';
|
||||||
import { listen } from '@tauri-apps/api/event';
|
import { listen } from '@tauri-apps/api/event';
|
||||||
@@ -50,6 +50,7 @@
|
|||||||
import GraphView from './GraphView.svelte';
|
import GraphView from './GraphView.svelte';
|
||||||
import TagSuggestInput from './TagSuggestInput.svelte';
|
import TagSuggestInput from './TagSuggestInput.svelte';
|
||||||
import { isMobile, isAndroid } from '$lib/platform';
|
import { isMobile, isAndroid } from '$lib/platform';
|
||||||
|
import ResizeHandle from './ResizeHandle.svelte';
|
||||||
|
|
||||||
const modKey = navigator.platform.startsWith('Mac') ? '⌘' : 'Ctrl';
|
const modKey = navigator.platform.startsWith('Mac') ? '⌘' : 'Ctrl';
|
||||||
|
|
||||||
@@ -178,6 +179,10 @@
|
|||||||
outlineHeadings = headings;
|
outlineHeadings = headings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleOutlineResize(delta: number) {
|
||||||
|
$outlineWidth = Math.max(160, Math.min(500, $outlineWidth - delta));
|
||||||
|
}
|
||||||
|
|
||||||
function scrollToHeading(pos: number) {
|
function scrollToHeading(pos: number) {
|
||||||
if (!editor) return;
|
if (!editor) return;
|
||||||
editor.commands.setTextSelection(pos + 1);
|
editor.commands.setTextSelection(pos + 1);
|
||||||
@@ -5502,7 +5507,8 @@
|
|||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
{#if showOutline}
|
{#if showOutline}
|
||||||
<div class="outline-panel">
|
<ResizeHandle onResize={handleOutlineResize} />
|
||||||
|
<div class="outline-panel" style="width: {$outlineWidth}px">
|
||||||
<div class="outline-header">
|
<div class="outline-header">
|
||||||
<h3>Outline</h3>
|
<h3>Outline</h3>
|
||||||
<button class="outline-close" onclick={() => { showOutline = false; }}>
|
<button class="outline-close" onclick={() => { showOutline = false; }}>
|
||||||
@@ -7475,7 +7481,7 @@
|
|||||||
|
|
||||||
.outline-empty {
|
.outline-empty {
|
||||||
padding: 16px 14px;
|
padding: 16px 14px;
|
||||||
font-size: 12px;
|
font-size: var(--editor-font-size, 14px);
|
||||||
color: var(--text-tertiary);
|
color: var(--text-tertiary);
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
}
|
}
|
||||||
@@ -7493,7 +7499,7 @@
|
|||||||
background: none;
|
background: none;
|
||||||
border: none;
|
border: none;
|
||||||
padding: 4px 14px;
|
padding: 4px 14px;
|
||||||
font-size: 12px;
|
font-size: var(--editor-font-size, 14px);
|
||||||
color: var(--text-secondary);
|
color: var(--text-secondary);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ export const sidebarCollapsed = writable(false);
|
|||||||
export const notelistCollapsed = writable(false);
|
export const notelistCollapsed = writable(false);
|
||||||
export const sidebarWidth = writable(220);
|
export const sidebarWidth = writable(220);
|
||||||
export const notelistWidth = writable(280);
|
export const notelistWidth = writable(280);
|
||||||
|
export const outlineWidth = writable(220);
|
||||||
export const searchQuery = writable("");
|
export const searchQuery = writable("");
|
||||||
export const showCommandPalette = writable(false);
|
export const showCommandPalette = writable(false);
|
||||||
export const showSearch = writable(false);
|
export const showSearch = writable(false);
|
||||||
@@ -227,6 +228,7 @@ export const vaultState = derived(
|
|||||||
activeNotePath,
|
activeNotePath,
|
||||||
sidebarWidth,
|
sidebarWidth,
|
||||||
notelistWidth,
|
notelistWidth,
|
||||||
|
outlineWidth,
|
||||||
sidebarCollapsed,
|
sidebarCollapsed,
|
||||||
notelistCollapsed,
|
notelistCollapsed,
|
||||||
collapsedNotebooks,
|
collapsedNotebooks,
|
||||||
@@ -238,6 +240,7 @@ export const vaultState = derived(
|
|||||||
$activeNotePath,
|
$activeNotePath,
|
||||||
$sidebarWidth,
|
$sidebarWidth,
|
||||||
$notelistWidth,
|
$notelistWidth,
|
||||||
|
$outlineWidth,
|
||||||
$sidebarCollapsed,
|
$sidebarCollapsed,
|
||||||
$notelistCollapsed,
|
$notelistCollapsed,
|
||||||
$collapsedNotebooks,
|
$collapsedNotebooks,
|
||||||
@@ -249,6 +252,7 @@ export const vaultState = derived(
|
|||||||
last_open_note: $activeNotePath,
|
last_open_note: $activeNotePath,
|
||||||
sidebar_width: $sidebarWidth,
|
sidebar_width: $sidebarWidth,
|
||||||
notelist_width: $notelistWidth,
|
notelist_width: $notelistWidth,
|
||||||
|
outline_width: $outlineWidth,
|
||||||
sidebar_collapsed: $sidebarCollapsed,
|
sidebar_collapsed: $sidebarCollapsed,
|
||||||
notelist_collapsed: $notelistCollapsed,
|
notelist_collapsed: $notelistCollapsed,
|
||||||
collapsed_notebooks: $collapsedNotebooks,
|
collapsed_notebooks: $collapsedNotebooks,
|
||||||
|
|||||||
@@ -129,6 +129,7 @@ export interface VaultState {
|
|||||||
last_open_note: string | null;
|
last_open_note: string | null;
|
||||||
sidebar_width: number;
|
sidebar_width: number;
|
||||||
notelist_width: number;
|
notelist_width: number;
|
||||||
|
outline_width?: number;
|
||||||
sidebar_collapsed: boolean;
|
sidebar_collapsed: boolean;
|
||||||
notelist_collapsed: boolean;
|
notelist_collapsed: boolean;
|
||||||
collapsed_notebooks: string[];
|
collapsed_notebooks: string[];
|
||||||
|
|||||||
Reference in New Issue
Block a user