Desktop Hooks

Desktop-specific hooks for shortcuts, file drop, notifications, window state, and dirty state detection

useGlobalShortcut

Register global keyboard shortcuts with automatic cleanup on unmount.

import { useGlobalShortcut } from '@linch-tech/desktop-core';

function App() {
  useGlobalShortcut('CommandOrControl+K', () => {
    openSearchDialog();
  });
}

Signature

function useGlobalShortcut(
  shortcut: string,
  handler: () => void,
  enabled?: boolean
): void

Parameters

ParamTypeDefaultDescription
shortcutstring-Key combination, e.g. "CommandOrControl+K"
handler() => void-Callback when triggered
enabledbooleantrueWhether the shortcut is active

Requires @tauri-apps/plugin-global-shortcut (optional peerDependency)


useFileDrop

Listen for file drag-and-drop events and get dropped file paths.

import { useFileDrop } from '@linch-tech/desktop-core';

function DropZone() {
  const ref = useFileDrop<HTMLDivElement>((paths) => {
    console.log('Dropped files:', paths);
  });

  return <div ref={ref} className="drop-zone">Drop files here</div>;
}

Signature

function useFileDrop<T extends HTMLElement = HTMLElement>(
  handler: (paths: string[]) => void,
  enabled?: boolean
): RefObject<T | null>

Parameters

ParamTypeDefaultDescription
handler(paths: string[]) => void-Callback with file paths
enabledbooleantrueWhether the listener is active

useNotification

Desktop native notifications with permission management.

import { useNotification } from '@linch-tech/desktop-core';

function NotifyButton() {
  const { notify, isPermissionGranted, requestPermission } = useNotification();

  const handleClick = async () => {
    if (!isPermissionGranted) {
      await requestPermission();
    }
    await notify('Task Complete', 'Data processing has finished');
  };

  return <button onClick={handleClick}>Send Notification</button>;
}

Signature

function useNotification(): {
  notify: (title: string, body?: string, icon?: string) => Promise<void>;
  isPermissionGranted: boolean;
  requestPermission: () => Promise<boolean>;
}

Requires @tauri-apps/plugin-notification (optional peerDependency)


useWindowState

Persist and restore window position and size across restarts.

import { useWindowState } from '@linch-tech/desktop-core';

function App() {
  const { position, size, isMaximized } = useWindowState();

  // Window position/size is automatically saved to localStorage
  // and restored on next launch
}

Signature

function useWindowState(key?: string): {
  position: { x: number; y: number } | null;
  size: { width: number; height: number } | null;
  isMaximized: boolean;
  saveState: () => Promise<void>;
  restoreState: () => Promise<void>;
}

Parameters

ParamTypeDefaultDescription
keystring"window-state"localStorage key for persistence

useDirtyState

Track whether state has been modified from its initial value, useful for "unsaved changes" prompts.

import { useDirtyState } from '@linch-tech/desktop-core';

function Editor() {
  const { value, setValue, isDirty, reset } = useDirtyState({ title: '', content: '' });

  const handleSave = async () => {
    await saveToDatabase(value);
    reset(); // Reset to "clean" state after save
  };

  return (
    <div>
      <input value={value.title} onChange={(e) => setValue({ ...value, title: e.target.value })} />
      {isDirty && <span>* Unsaved</span>}
      <button onClick={handleSave} disabled={!isDirty}>Save</button>
    </div>
  );
}

Signature

function useDirtyState<T>(initialValue: T): {
  value: T;
  setValue: (value: T) => void;
  isDirty: boolean;
  reset: () => void;
  original: T;
}

Return Value

FieldTypeDescription
valueTCurrent value
setValue(value: T) => voidUpdate the value
isDirtybooleanWhether value differs from initial (deep comparison)
reset() => voidReset to initial value
originalTReference to the initial value