mirror of
https://github.com/Psychotoxical/psysonic.git
synced 2026-07-22 07:15:47 +00:00
refactor(folder-browser): G.87 — extract column component + 3 hooks (cluster, multi-commit) (#654)
* refactor(folder-browser): G.87.1 — extract helpers + types Move ColumnKind / NavPos / Column types + entryToAlbumIfPresent / entryToTrack mappers + isFolderBrowserArrowKey / folderBrowserHasKeyModifiers key-event helpers into src/utils/folderBrowserHelpers.ts. Pure code move. * refactor(folder-browser): G.87.2 — extract FolderBrowserColumn component * refactor(folder-browser): G.87.3 — extract useFolderBrowserNowPlayingPath hook * refactor(folder-browser): G.87.4 — extract useFolderBrowserScrolling hook * refactor(folder-browser): G.87.5 — extract useFolderBrowserKeyboardNav hook
This commit is contained in:
committed by
GitHub
parent
c8e130ecea
commit
d4d3b0e53f
@@ -0,0 +1,85 @@
|
||||
import type React from 'react';
|
||||
import type { SubsonicAlbum, SubsonicDirectoryEntry } from '../api/subsonicTypes';
|
||||
import type { Track } from '../store/playerStoreTypes';
|
||||
|
||||
export type ColumnKind = 'roots' | 'indexes' | 'directory';
|
||||
export type NavPos = { colIndex: number; rowIndex: number };
|
||||
|
||||
export type Column = {
|
||||
id: string;
|
||||
name: string;
|
||||
items: SubsonicDirectoryEntry[];
|
||||
selectedId: string | null;
|
||||
loading: boolean;
|
||||
error: boolean;
|
||||
kind: ColumnKind;
|
||||
};
|
||||
|
||||
/** getMusicDirectory: `albumId` or `album` + row `id` (Navidrome). */
|
||||
export function entryToAlbumIfPresent(item: SubsonicDirectoryEntry): SubsonicAlbum | null {
|
||||
if (!item.isDir) return null;
|
||||
const albumId = item.albumId ?? (item.album ? item.id : undefined);
|
||||
if (!albumId) return null;
|
||||
return {
|
||||
id: albumId,
|
||||
name: item.album ?? item.title,
|
||||
artist: item.artist ?? '',
|
||||
artistId: item.artistId ?? '',
|
||||
coverArt: item.coverArt,
|
||||
year: item.year,
|
||||
genre: item.genre,
|
||||
starred: item.starred,
|
||||
userRating: item.userRating,
|
||||
songCount: 0,
|
||||
duration: 0,
|
||||
};
|
||||
}
|
||||
|
||||
export function entryToTrack(e: SubsonicDirectoryEntry): Track {
|
||||
return {
|
||||
id: e.id,
|
||||
title: e.title,
|
||||
artist: e.artist ?? '',
|
||||
album: e.album ?? '',
|
||||
albumId: e.albumId ?? '',
|
||||
artistId: e.artistId,
|
||||
coverArt: e.coverArt,
|
||||
duration: e.duration ?? 0,
|
||||
track: e.track,
|
||||
year: e.year,
|
||||
bitRate: e.bitRate,
|
||||
suffix: e.suffix,
|
||||
genre: e.genre,
|
||||
starred: e.starred,
|
||||
userRating: e.userRating,
|
||||
};
|
||||
}
|
||||
|
||||
export function isFolderBrowserArrowKey(e: React.KeyboardEvent): boolean {
|
||||
return (
|
||||
e.key === 'ArrowUp' ||
|
||||
e.key === 'ArrowDown' ||
|
||||
e.key === 'ArrowLeft' ||
|
||||
e.key === 'ArrowRight' ||
|
||||
e.code === 'ArrowUp' ||
|
||||
e.code === 'ArrowDown' ||
|
||||
e.code === 'ArrowLeft' ||
|
||||
e.code === 'ArrowRight'
|
||||
);
|
||||
}
|
||||
|
||||
/** Modifiers from native event + getModifierState (WebKit/WebView can miss flags on the synthetic event). */
|
||||
export function folderBrowserHasKeyModifiers(e: React.KeyboardEvent): boolean {
|
||||
const n = e.nativeEvent;
|
||||
if (n.ctrlKey || n.altKey || n.shiftKey || n.metaKey) return true;
|
||||
if (typeof n.getModifierState === 'function') {
|
||||
return (
|
||||
n.getModifierState('Control') ||
|
||||
n.getModifierState('Alt') ||
|
||||
n.getModifierState('Shift') ||
|
||||
n.getModifierState('Meta') ||
|
||||
n.getModifierState('OS')
|
||||
);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
Reference in New Issue
Block a user