From 8571e1ad9be63f97d5da31794a57f49205cd5a29 Mon Sep 17 00:00:00 2001 From: Kevin Frei Date: Sat, 13 Jul 2024 18:24:11 -0700 Subject: [PATCH] No more enums (#84) * Proof of concept for the no-more-TS-enums thing * Migrated a couple more shared enums * No more enums at all --- electron/CommsSetup.ts | 10 +- electron/SendToUI.ts | 4 +- electron/Transcoding.ts | 35 ++- modules/shared/src/shared.ts | 368 ++++++++++++++++-------------- src/Jotai/CurrentView.ts | 6 +- src/Jotai/KeyBuffer.ts | 4 +- src/Recoil/ReadOnly.ts | 6 +- src/Recoil/TranscodeState.ts | 29 ++- src/UI/App.tsx | 6 +- src/UI/MenuHandler.ts | 4 +- src/UI/MenuHelpers.ts | 4 +- src/UI/Sidebar.tsx | 26 ++- src/UI/Views/Selector.tsx | 12 +- src/UI/Views/Settings.tsx | 8 +- src/UI/Views/Tools/Transcoder.tsx | 24 +- 15 files changed, 292 insertions(+), 254 deletions(-) diff --git a/electron/CommsSetup.ts b/electron/CommsSetup.ts index 1d1fbd8e..04e0072f 100644 --- a/electron/CommsSetup.ts +++ b/electron/CommsSetup.ts @@ -1,6 +1,6 @@ import { IsOnlyMetadata } from '@freik/audiodb'; import { Comms, Shell } from '@freik/electron-main'; -import { IpcId, isIgnoreItemFn, isXcodeInfo } from '@freik/emp-shared'; +import { IpcId, isIgnoreItem, isXcodeInfo } from '@freik/emp-shared'; import { MakeLog } from '@freik/logger'; import { MediaKey } from '@freik/media-core'; import { @@ -184,10 +184,6 @@ export function CommsSetup(): void { // Ignore list stuff: Comms.registerChannel(IpcId.GetIgnoreList, GetIgnoreList, isVoid); - Comms.registerChannel(IpcId.AddIgnoreItem, AddIgnoreItem, isIgnoreItemFn); - Comms.registerChannel( - IpcId.RemoveIgnoreItem, - RemoveIgnoreItem, - isIgnoreItemFn, - ); + Comms.registerChannel(IpcId.AddIgnoreItem, AddIgnoreItem, isIgnoreItem); + Comms.registerChannel(IpcId.RemoveIgnoreItem, RemoveIgnoreItem, isIgnoreItem); } diff --git a/electron/SendToUI.ts b/electron/SendToUI.ts index da94852c..e644a657 100644 --- a/electron/SendToUI.ts +++ b/electron/SendToUI.ts @@ -1,12 +1,12 @@ import { Comms } from '@freik/electron-main'; -import { IpcId } from '@freik/emp-shared'; +import { IpcIdEnum } from '@freik/emp-shared'; import { MakeLog } from '@freik/logger'; const { log } = MakeLog('EMP:main:SendToUI'); // This is for one-way comms to the UI process -export function SendToUI(name: IpcId, data: T) { +export function SendToUI(name: IpcIdEnum, data: T) { const obj: { [key: string]: T } = {}; obj[name] = data; log(`Sending ${name} with data:`); diff --git a/electron/Transcoding.ts b/electron/Transcoding.ts index 42ca3459..df94f3aa 100644 --- a/electron/Transcoding.ts +++ b/electron/Transcoding.ts @@ -1,7 +1,7 @@ import { IpcId, TranscodeInfo, - TranscodeSourceType, + TranscodeSource, TranscodeState, } from '@freik/emp-shared'; import { MakeLog } from '@freik/logger'; @@ -44,23 +44,22 @@ function reQuote(str: string): { [key: string]: string } { return JSON.parse(res) as { [key: string]: string }; } -/// vvvv Hurray for a Typescript compiler bug - -enum XcodeResCode { - alreadyExists, - mediaInfoFailure, - encodeFailure, - unknownError, - alreadyLowBitRate, - success, -} +const XcodeResCode = Object.freeze({ + alreadyExists: 0, + mediaInfoFailure: 1, + encodeFailure: 2, + unknownError: 3, + alreadyLowBitRate: 4, + success: 5, +} as const); +type XcodeResCodeEnum = (typeof XcodeResCode)[keyof typeof XcodeResCode]; type TranscodeResult = { - code: XcodeResCode; + code: XcodeResCodeEnum; message: string; }; -const tr = (code: XcodeResCode, message: string) => ({ code, message }); +const tr = (code: XcodeResCodeEnum, message: string) => ({ code, message }); let bitrate = 163840; export async function toMp4Async( @@ -246,7 +245,7 @@ async function getFullSongPathFromSettings( settings: TranscodeInfo, file: string, ): Promise<[string, string] | void> { - if (settings.source.type === TranscodeSourceType.Disk) { + if (settings.source.type === TranscodeSource.Disk) { const srcdir = settings.source.loc; if (!path.normalize(file).startsWith(srcdir)) { reportFailure(file, `${file} doesn't match ${srcdir}`); @@ -505,13 +504,13 @@ export async function startTranscode(settings: TranscodeInfo): Promise { startStatusReporting(); try { const workQueue: string[] = []; - if (settings.source.type === TranscodeSourceType.Disk) { + if (settings.source.type === TranscodeSource.Disk) { await ScanSourceFromDisk(settings, workQueue); } else { // TODO: Handle artwork for this stuff const db = await GetAudioDB(); switch (settings.source.type) { - case TranscodeSourceType.Album: { + case TranscodeSource.Album: { const album = db.getAlbum(settings.source.loc); if (album) { workQueue.push(...album.songs); @@ -519,7 +518,7 @@ export async function startTranscode(settings: TranscodeInfo): Promise { // TODO: Report no such album break; } - case TranscodeSourceType.Artist: { + case TranscodeSource.Artist: { const artist = db.getArtist(settings.source.loc); if (artist) { workQueue.push(...artist.songs); @@ -527,7 +526,7 @@ export async function startTranscode(settings: TranscodeInfo): Promise { // TODO: Report no such album break; } - case TranscodeSourceType.Playlist: + case TranscodeSource.Playlist: workQueue.push(...(await LoadPlaylist(settings.source.loc))); break; } diff --git a/modules/shared/src/shared.ts b/modules/shared/src/shared.ts index 3dde8e0a..0026b6b8 100644 --- a/modules/shared/src/shared.ts +++ b/modules/shared/src/shared.ts @@ -1,172 +1,213 @@ import { chkArrayOf, chkObjectOfType, + isArray, isBoolean, isNumber, isString, typecheck, } from '@freik/typechk'; -export enum IpcId { - ClearHates = 'clear-hates', - ClearLikes = 'clear-likes', - ClearLocalOverrides = 'clear-local-overrides', - DeletePlaylist = 'delete-playlist', - FlushImageCache = 'flush-image-cache', - FlushMetadataCache = 'flush-metadata-cache', - GetHates = 'get-hates', - GetLikes = 'get-likes', - GetMediaInfo = 'media-info', - GetMusicDatabase = 'get-music-database', - GetPlaylists = 'get-playlists', - LoadPlaylists = 'load-playlists', - ManualRescan = 'manual-rescan', - MenuAction = 'menuAction', - MusicDBUpdate = 'music-database-update', - RenamePlaylist = 'rename-playlist', - SavePlaylist = 'save-playlist', - Search = 'search', - SetHates = 'set-hates', - SetLikes = 'set-likes', - SetMediaInfo = 'set-media-info', - SetPlaylists = 'set-playlists', - SetSaveMenu = 'set-save-menu', - ShowFile = 'show-file', - ShowLocFromKey = 'show-location-from-key', - ShowMenu = 'show-menu', - SubstrSearch = 'subsearch', - TranscodingUpdate = 'get-xcode-update', - TranscodingBegin = 'start-xcode', - UploadImage = 'upload-image', - MinimizeWindow = 'minimize-window', - MaximizeWindow = 'maximize-window', - RestoreWindow = 'restore-window', - CloseWindow = 'close-window', - GetPicUri = 'get-pic-uri', - GetIgnoreList = 'get-ignore-list', - AddIgnoreItem = 'add-ignore-item', - RemoveIgnoreItem = 'del-ignore-item', - PushIgnoreList = 'push-ignore-list', - IgnoreListId = 'ignore-list', - RescanInProgress = 'rescan-in-progress', +/** + * Type check to validate that obj is a valid constant allowed in + * the Typescript 'string constant' type provided + * @param {unknown} obj + * @returns {obj_is} + */ +export function chkValidConst( + typearray: readonly T[] | Set, +): typecheck { + return (obj: unknown): obj is T => + isArray(typearray) + ? typearray.includes(obj as unknown as T) + : (typearray as Set).has(obj as unknown as T); } -export enum Keys { - AddFileLocation = 'O', - Albums = '2', - Artists = '3', - Backward10s = '[', - Find = 'F', - Forward10s = ']', - NextTrack = 'Right', - NowPlaying = '1', - Play = 'P', - Playlists = '5', - PreviousTrack = 'Left', - Repeat = 'T', - SavePlaylist = 'S', - Settings = ',', - Shuffle = 'R', - Songs = '4', - ToggleMiniPlayer = '9', - Tools = 'L', +/** + * Type check to validate that obj is a valid constant allowed in + * the Typescript 'string constant' type provided + * @param {unknown} obj + * @returns {obj_is} + */ +export function isValidConst( + typearray: readonly T[] | Set, + obj: unknown, +): obj is T { + return chkValidConst(typearray)(obj); } +export const IpcId = Object.freeze({ + ClearHates: 'clear-hates', + ClearLikes: 'clear-likes', + ClearLocalOverrides: 'clear-local-overrides', + DeletePlaylist: 'delete-playlist', + FlushImageCache: 'flush-image-cache', + FlushMetadataCache: 'flush-metadata-cache', + GetHates: 'get-hates', + GetLikes: 'get-likes', + GetMediaInfo: 'media-info', + GetMusicDatabase: 'get-music-database', + GetPlaylists: 'get-playlists', + LoadPlaylists: 'load-playlists', + ManualRescan: 'manual-rescan', + MenuAction: 'menuAction', + MusicDBUpdate: 'music-database-update', + RenamePlaylist: 'rename-playlist', + SavePlaylist: 'save-playlist', + Search: 'search', + SetHates: 'set-hates', + SetLikes: 'set-likes', + SetMediaInfo: 'set-media-info', + SetPlaylists: 'set-playlists', + SetSaveMenu: 'set-save-menu', + ShowFile: 'show-file', + ShowLocFromKey: 'show-location-from-key', + ShowMenu: 'show-menu', + SubstrSearch: 'subsearch', + TranscodingUpdate: 'get-xcode-update', + TranscodingBegin: 'start-xcode', + UploadImage: 'upload-image', + MinimizeWindow: 'minimize-window', + MaximizeWindow: 'maximize-window', + RestoreWindow: 'restore-window', + CloseWindow: 'close-window', + GetPicUri: 'get-pic-uri', + GetIgnoreList: 'get-ignore-list', + AddIgnoreItem: 'add-ignore-item', + RemoveIgnoreItem: 'del-ignore-item', + PushIgnoreList: 'push-ignore-list', + IgnoreListId: 'ignore-list', + RescanInProgress: 'rescan-in-progress', +} as const); +export type IpcIdEnum = (typeof IpcId)[keyof typeof IpcId]; + +export const Keys = Object.freeze({ + AddFileLocation: 'O', + Albums: '2', + Artists: '3', + Backward10s: '[', + Find: 'F', + Forward10s: ']', + NextTrack: 'Right', + NowPlaying: '1', + Play: 'P', + Playlists: '5', + PreviousTrack: 'Left', + Repeat: 'T', + SavePlaylist: 'S', + Settings: ',', + Shuffle: 'R', + Songs: '4', + ToggleMiniPlayer: '9', + Tools: 'L', +} as const); +export type KeysEnum = (typeof Keys)[keyof typeof Keys]; + // TODO: This stuff let's me localize my strings eventually -export enum StrId { +export const StrId = Object.freeze({ // MediaInfo.tsx strings - Mono = 'mono', - Stereo = 'stereo', - Quadrophonic = 'quadrophonic', - Channels = ' channels', - BitDepth = 'bit', - FilePath = 'File Path', - Duration = 'Duration:', - MDHeaderField = 'Field', - MDHeaderValue = 'Value', - FilesSelected = 'Files Selected', - RawMetadata = 'Raw Metadata', + Mono: 'mono', + Stereo: 'stereo', + Quadrophonic: 'quadrophonic', + Channels: ' channels', + BitDepth: 'bit', + FilePath: 'File Path', + Duration: 'Duration:', + MDHeaderField: 'Field', + MDHeaderValue: 'Value', + FilesSelected: 'Files Selected', + RawMetadata: 'Raw Metadata', // Metadata Editor - ChooseCoverArt = 'Select Cover Art Image', - ImageName = 'Images', - ErrNotSingleAndNotMultiple = 'Not Single and not Multiple (This is a bug!)', - ErrSingleAndMultiple = 'Both Single and Multiple (This is a bug!)', - Title = 'Title', - ArtistTooltip = "Multiple artists are specified like this: 'Artist 1, Artist 2 & Artist 3'", - Artists = 'Artist(s)', - Album = 'Album', - Year = 'Year', - TrackNum = 'Track #', - DiskNum = 'Disk #', - DiskName = 'Disk Name', - Compilation = 'Compilation', - Soundtrack = 'Soundtrack', - AdditionalArtists = 'Additional Artist(s)', - VariationsTooltip = 'Separate vartiations with a semicolon', - Variations = 'Variation(s)', - AlbumCover = 'Album Cover', - ChooseFile = 'Choose File...', - FromClipboard = 'From Clipboard', - ViewNowPlaying = 'Now Playing', - ViewAlbums = 'Albums', - ViewArtists = 'Artists', - ViewSongs = 'All Songs', - ViewPlaylists = 'Playlists', - ViewSettings = 'Settings', - ViewTools = 'Tools', - ImportFiles = 'Import Files...', -} + ChooseCoverArt: 'Select Cover Art Image', + ImageName: 'Images', + ErrNotSingleAndNotMultiple: 'Not Single and not Multiple (This is a bug!)', + ErrSingleAndMultiple: 'Both Single and Multiple (This is a bug!)', + Title: 'Title', + ArtistTooltip: + "Multiple artists are specified like this: 'Artist 1, Artist 2 & Artist 3'", + Artists: 'Artist(s)', + Album: 'Album', + Year: 'Year', + TrackNum: 'Track #', + DiskNum: 'Disk #', + DiskName: 'Disk Name', + Compilation: 'Compilation', + Soundtrack: 'Soundtrack', + AdditionalArtists: 'Additional Artist(s)', + VariationsTooltip: 'Separate vartiations with a semicolon', + Variations: 'Variation(s)', + AlbumCover: 'Album Cover', + ChooseFile: 'Choose File...', + FromClipboard: 'From Clipboard', + ViewNowPlaying: 'Now Playing', + ViewAlbums: 'Albums', + ViewArtists: 'Artists', + ViewSongs: 'All Songs', + ViewPlaylists: 'Playlists', + ViewSettings: 'Settings', + ViewTools: 'Tools', + ImportFiles: 'Import Files...', +}); +export type StrIdEnum = (typeof StrId)[keyof typeof StrId]; -export function st(id: StrId): string { +export function st(id: StrIdEnum): string { return id; } -export enum CurrentView { - disabled = -1, - none = 0, - recent = 1, - albums = 2, - artists = 3, - songs = 4, - playlists = 5, - now_playing = 6, - settings = 7, - search = 8, - tools = 9, -} - -export const isCurrentView: typecheck = ( +export const CurrentView = Object.freeze({ + disabled: -1, + none: 0, + recent: 1, + albums: 2, + artists: 3, + songs: 4, + playlists: 5, + now_playing: 6, + settings: 7, + search: 8, + tools: 9, +} as const); +export type CurrentViewEnum = (typeof CurrentView)[keyof typeof CurrentView]; +export const isCurrentView: typecheck = ( val: unknown, -): val is CurrentView => +): val is CurrentViewEnum => isNumber(val) && Number.isInteger(val) && val >= CurrentView.disabled && val <= CurrentView.tools; -export enum TranscodeFormatTargets { - m4a = 'm4a', - mp3 = 'mp3', - aac = 'aac', -} -export type TranscodeFormatTargetNames = 'm4a' | 'mp3' | 'aac'; +export const TranscodeFormatTargetName = Object.freeze({ + m4a: 'm4a', + mp3: 'mp3', + aac: 'aac', +} as const); +export type TranscodeFormatTargetNameEnum = + (typeof TranscodeFormatTargetName)[keyof typeof TranscodeFormatTargetName]; +const TranscodeFormatTargetNameEnumValues: readonly TranscodeFormatTargetNameEnum[] = + Object.values(TranscodeFormatTargetName); +export const isTranscodeFormatTargetName = chkValidConst( + TranscodeFormatTargetNameEnumValues, +); -export enum TranscodeSourceType { - Playlist = 'p', - Artist = 'r', - Album = 'l', - Disk = 'd', -} -export function isTranscodeSourceType(v: unknown): v is TranscodeSourceType { - return v === 'p' || v === 'r' || v === 'l' || v === 'd'; -} +export const TranscodeSource = Object.freeze({ + Playlist: 'p', + Artist: 'r', + Album: 'l', + Disk: 'd', +} as const); +export type TranscodeSourceEnum = + (typeof TranscodeSource)[keyof typeof TranscodeSource]; +const TranscodeSourceEnumValues: readonly TranscodeSourceEnum[] = + Object.values(TranscodeSource); +export const isTranscodeSource = chkValidConst(TranscodeSourceEnumValues); export type TranscodeSourceLocation = { - type: TranscodeSourceType; + type: TranscodeSourceEnum; loc: string; }; export const isXcodeSrcLoc = chkObjectOfType({ - type: isTranscodeSourceType, + type: isTranscodeSource, loc: isString, }); @@ -181,11 +222,11 @@ export type TranscodeState = { }; export type TranscodeInfo = { - source: { type: TranscodeSourceType; loc: string }; + source: { type: TranscodeSourceEnum; loc: string }; dest: string; artwork: boolean; mirror: boolean; - format: TranscodeFormatTargetNames; + format: TranscodeFormatTargetNameEnum; bitrate: number; }; @@ -194,42 +235,25 @@ export const isXcodeInfo = chkObjectOfType({ dest: isString, artwork: isBoolean, mirror: isBoolean, - format: (o: unknown): o is TranscodeFormatTargetNames => { - return o === 'm4a' || o === 'mp3' || o === 'aac'; - }, + format: isTranscodeFormatTargetName, bitrate: isNumber, }); -export type IgnoreItemType = 'path-root' | 'path-keyword' | 'dir-name'; -export type IgnoreItem = { type: IgnoreItemType; value: string }; -export function IsIgnoreItemType(obj: unknown): obj is IgnoreItemType { - return obj === 'path-root' || obj === 'path-keyword' || obj === 'dir-name'; -} -export const isIgnoreItemFn = chkObjectOfType({ - type: IsIgnoreItemType, +export const IgnoreItemType = Object.freeze({ + PathRoot: 'path-root', + PathKeyword: 'path-keyword', + DirName: 'dir-name', +} as const); +export type IgnoreItemTypeEnum = + (typeof IgnoreItemType)[keyof typeof IgnoreItemType]; +export const isIgnoreItemType: typecheck = ( + val: unknown, +): val is IgnoreItemTypeEnum => + val === 'path-root' || val === 'path-keyword' || val === 'dir-name'; + +export type IgnoreItem = { type: IgnoreItemTypeEnum; value: string }; +export const isIgnoreItem = chkObjectOfType({ + type: isIgnoreItemType, value: isString, }); -export const isIgnoreItemArrayFn = chkArrayOf(isIgnoreItemFn); - -/* -export enum Decisions { - approve, - reject, -} - -export function isDecision(obj: unknown): obj is Decisions { - return (obj as any) in Decisions; -} - -export function sillyText(obj: string) { - if (isDecision(obj)) { - console.log(obj); - } else { - console.log('Not a decision: ' + obj); - } -} - -export function isEnum(obj: unknown): obj is T { - return (obj as any) in keyof T; -} -*/ +export const isIgnoreItemArray = chkArrayOf(isIgnoreItem); diff --git a/src/Jotai/CurrentView.ts b/src/Jotai/CurrentView.ts index 655c5c03..81561a4f 100644 --- a/src/Jotai/CurrentView.ts +++ b/src/Jotai/CurrentView.ts @@ -1,13 +1,13 @@ // The currently selected item from the left bar -import { CurrentView, isCurrentView } from '@freik/emp-shared'; +import { CurrentView, CurrentViewEnum, isCurrentView } from '@freik/emp-shared'; import { atom } from 'jotai'; import { isMiniplayerState } from './Local'; import { atomWithMainStorage } from './Storage'; // The currently selected item from the left bar // artist, album, search, tools, settings, etc... -const curViewBackerState = atomWithMainStorage( +const curViewBackerState = atomWithMainStorage( 'CurrentView', CurrentView.settings, isCurrentView, @@ -17,5 +17,5 @@ const curViewBackerState = atomWithMainStorage( export const curViewFunc = atom( (get) => get(isMiniplayerState) ? CurrentView.now_playing : get(curViewBackerState), - (_get, set, newVal: CurrentView) => set(curViewBackerState, newVal), + (_get, set, newVal: CurrentViewEnum) => set(curViewBackerState, newVal), ); diff --git a/src/Jotai/KeyBuffer.ts b/src/Jotai/KeyBuffer.ts index 8672fefe..50c911fc 100644 --- a/src/Jotai/KeyBuffer.ts +++ b/src/Jotai/KeyBuffer.ts @@ -1,4 +1,4 @@ -import { CurrentView } from '@freik/emp-shared'; +import { CurrentViewEnum } from '@freik/emp-shared'; import { Atom, atom } from 'jotai'; import { atomFamily } from 'jotai/utils'; import { curViewFunc } from './CurrentView'; @@ -6,7 +6,7 @@ import { curViewFunc } from './CurrentView'; // This is the currently 'typed' set of characters (for scrolling lists) export const keyBufferState = atom(''); -export const focusedKeysFuncFam = atomFamily>( +export const focusedKeysFuncFam = atomFamily>( (view) => atom((get) => get(curViewFunc) === view ? get(keyBufferState) : '', diff --git a/src/Recoil/ReadOnly.ts b/src/Recoil/ReadOnly.ts index 42ad2faa..8ecabae4 100644 --- a/src/Recoil/ReadOnly.ts +++ b/src/Recoil/ReadOnly.ts @@ -1,6 +1,6 @@ import { FlatAudioDatabase } from '@freik/audiodb'; import { Effects, Ipc } from '@freik/electron-render'; -import { IgnoreItem, IpcId, isIgnoreItemArrayFn } from '@freik/emp-shared'; +import { IgnoreItem, IpcId, isIgnoreItemArray } from '@freik/emp-shared'; import { MakeLog } from '@freik/logger'; import { Album, @@ -499,13 +499,13 @@ export const ignoreItemsState = atom({ const il = await Ipc.CallMain( IpcId.GetIgnoreList, undefined, - isIgnoreItemArrayFn, + isIgnoreItemArray, ); return il || []; }, IpcId.PushIgnoreList, (il: unknown) => { - if (isIgnoreItemArrayFn(il)) { + if (isIgnoreItemArray(il)) { return il; } wrn('Invalid result from ignore-items-update:'); diff --git a/src/Recoil/TranscodeState.ts b/src/Recoil/TranscodeState.ts index dca746ef..1589c49e 100644 --- a/src/Recoil/TranscodeState.ts +++ b/src/Recoil/TranscodeState.ts @@ -1,4 +1,10 @@ import { Effects } from '@freik/electron-render'; +import { + IpcId, + TranscodeSource, + TranscodeSourceEnum, + TranscodeState, +} from '@freik/emp-shared'; import { AlbumKey, ArtistKey, PlaylistName } from '@freik/media-core'; import { chkArrayOf, @@ -8,7 +14,6 @@ import { isString, } from '@freik/typechk'; import { atom, selector, selectorFamily } from 'recoil'; -import { IpcId, TranscodeSourceType, TranscodeState } from '@freik/emp-shared'; import { allPlaylistsFunc } from './PlaylistsState'; import { allAlbumsFunc, allArtistsFunc } from './ReadOnly'; @@ -62,9 +67,9 @@ export const transcodeStatusState = atom({ ], }); -export const sourceLocationTypeState = atom({ +export const sourceLocationTypeState = atom({ key: 'xcodeSrcLocType', - default: TranscodeSourceType.Playlist, + default: TranscodeSource.Playlist, }); export const sourceLocationDirState = atom({ @@ -123,20 +128,20 @@ export const validSourceFunc = selector({ get: ({ get }) => { const sel = get(sourceLocationTypeState); switch (sel) { - case TranscodeSourceType.Playlist: + case TranscodeSource.Playlist: return get(validPlaylist(get(sourceLocationPlaylistState))); - case TranscodeSourceType.Artist: + case TranscodeSource.Artist: return get(validArtist(get(sourceLocationArtistState))); - case TranscodeSourceType.Album: + case TranscodeSource.Album: return get(validAlbum(get(sourceLocationAlbumState))); - case TranscodeSourceType.Disk: + case TranscodeSource.Disk: return get(sourceLocationDirState).length > 0; } }, }); export const sourceLocationDescriptorFunc = selector<{ - type: TranscodeSourceType; + type: TranscodeSourceEnum; loc: string; }>({ key: 'xcodeSourceLocDescr', @@ -144,16 +149,16 @@ export const sourceLocationDescriptorFunc = selector<{ let loc: string; const type = get(sourceLocationTypeState); switch (type) { - case TranscodeSourceType.Playlist: + case TranscodeSource.Playlist: loc = get(sourceLocationPlaylistState); break; - case TranscodeSourceType.Artist: + case TranscodeSource.Artist: loc = get(sourceLocationArtistState); break; - case TranscodeSourceType.Album: + case TranscodeSource.Album: loc = get(sourceLocationAlbumState); break; - case TranscodeSourceType.Disk: + case TranscodeSource.Disk: loc = get(sourceLocationDirState); break; } diff --git a/src/UI/App.tsx b/src/UI/App.tsx index 61add1eb..5c5500f2 100644 --- a/src/UI/App.tsx +++ b/src/UI/App.tsx @@ -1,6 +1,6 @@ import { IconButton, SpinnerSize } from '@fluentui/react'; import { ElectronWireUp, Ipc } from '@freik/electron-render'; -import { IpcId } from '@freik/emp-shared'; +import { IpcId, IpcIdEnum } from '@freik/emp-shared'; import { Spinner } from '@freik/web-utils'; import { Provider, useAtomValue } from 'jotai'; import { useRef, useState } from 'react'; @@ -30,7 +30,9 @@ function WindowChrome(): JSX.Element { // 'CheckBox' 'SingleColumn' 'GridViewLarge' all look okay const resMaxTitle = isMax ? 'restore' : 'maximize'; const resMaxName = isMax ? 'ChromeRestore' : 'GridViewLarge'; - const resMaxId: IpcId = isMax ? IpcId.RestoreWindow : IpcId.MaximizeWindow; + const resMaxId: IpcIdEnum = isMax + ? IpcId.RestoreWindow + : IpcId.MaximizeWindow; const ic = (iconName: string) => ({ iconName, style: { fontSize: 10 } }); return ( diff --git a/src/UI/MenuHandler.ts b/src/UI/MenuHandler.ts index 90f2cf15..93166651 100644 --- a/src/UI/MenuHandler.ts +++ b/src/UI/MenuHandler.ts @@ -1,4 +1,4 @@ -import { CurrentView } from '@freik/emp-shared'; +import { CurrentView, CurrentViewEnum } from '@freik/emp-shared'; import { MakeLog } from '@freik/logger'; import { hasStrField } from '@freik/typechk'; import { MyTransactionInterface } from '@freik/web-utils'; @@ -98,7 +98,7 @@ export function MenuHandler( break; case 'view': if (hasStrField(message, 'select')) { - let theView: CurrentView = CurrentView.none; + let theView: CurrentViewEnum = CurrentView.none; switch (message.select) { case 'NowPlaying': theView = CurrentView.now_playing; diff --git a/src/UI/MenuHelpers.ts b/src/UI/MenuHelpers.ts index 05fe2d1b..2678f936 100644 --- a/src/UI/MenuHelpers.ts +++ b/src/UI/MenuHelpers.ts @@ -1,4 +1,4 @@ -import { Keys } from '@freik/emp-shared'; +import { Keys, KeysEnum } from '@freik/emp-shared'; const HostOs: 'mac' | 'windows' | 'linux' = (() => { const ua = window.navigator.userAgent; @@ -13,7 +13,7 @@ const HostOs: 'mac' | 'windows' | 'linux' = (() => { const accPrefix = HostOs === 'mac' ? '⌘' : 'Ctrl'; -export function GetHelperText(key: Keys) { +export function GetHelperText(key: KeysEnum) { if (key.length === 1) { return `${accPrefix}-${key}`; } diff --git a/src/UI/Sidebar.tsx b/src/UI/Sidebar.tsx index 7623b2ee..bd9d69d4 100644 --- a/src/UI/Sidebar.tsx +++ b/src/UI/Sidebar.tsx @@ -1,5 +1,13 @@ import { FontIcon, SearchBox, Text } from '@fluentui/react'; -import { CurrentView, Keys, StrId, st } from '@freik/emp-shared'; +import { + CurrentView, + CurrentViewEnum, + Keys, + KeysEnum, + StrId, + StrIdEnum, + st, +} from '@freik/emp-shared'; import { hasStrField, isObjectNonNull } from '@freik/typechk'; import { useAtom } from 'jotai'; import { useRecoilCallback } from 'recoil'; @@ -10,8 +18,16 @@ import { GetHelperText } from './MenuHelpers'; import { Notifier } from './Notifier'; import './styles/Sidebar.css'; -type ViewEntry = { name: CurrentView; title: StrId; accelerator: Keys }; -const mkEntry = (name: CurrentView, title: StrId, accelerator: Keys) => ({ +type ViewEntry = { + name: CurrentViewEnum; + title: StrIdEnum; + accelerator: KeysEnum; +}; +const mkEntry = ( + name: CurrentViewEnum, + title: StrIdEnum, + accelerator: KeysEnum, +) => ({ name, title, accelerator, @@ -31,8 +47,8 @@ const views: (ViewEntry | null)[] = [ ]; function getEntry( - curView: CurrentView, - setCurView: (newView: CurrentView) => Promise, + curView: CurrentViewEnum, + setCurView: (newView: CurrentViewEnum) => Promise, view: ViewEntry | null, index: number, ) { diff --git a/src/UI/Views/Selector.tsx b/src/UI/Views/Selector.tsx index 58e2d9a9..3c88c10a 100644 --- a/src/UI/Views/Selector.tsx +++ b/src/UI/Views/Selector.tsx @@ -1,4 +1,4 @@ -import { CurrentView } from '@freik/emp-shared'; +import { CurrentView, CurrentViewEnum } from '@freik/emp-shared'; import { useAtomValue } from 'jotai'; import { CSSProperties, useState } from 'react'; import { curViewFunc } from '../../Jotai/CurrentView'; @@ -13,20 +13,20 @@ import { SettingsView } from './Settings'; import { ToolsView } from './Tools'; import './styles/Selector.css'; -function ignore(view: CurrentView): boolean { +function ignore(view: CurrentViewEnum): boolean { return view === CurrentView.settings || view === CurrentView.tools; } export function ViewSelector(): JSX.Element { const which = useAtomValue(curViewFunc); - const [rendered, setRendered] = useState(new Set([which])); + const [rendered, setRendered] = useState(new Set([which])); // Let's see if I can speed this up a bit by not trying to render everything // the first time - const sl = (v: CurrentView): CSSProperties => + const sl = (v: CurrentViewEnum): CSSProperties => which === v ? {} : { visibility: 'hidden' }; - const contents: [CurrentView, JSX.Element][] = []; + const contents: [CurrentViewEnum, JSX.Element][] = []; if (!rendered.has(which) && !ignore(which)) { - const newrendered = new Set([which, ...rendered]); + const newrendered = new Set([which, ...rendered]); setRendered(newrendered); // We still need to do a full render, because otherwise elements get // deleted and recreated, and that's probably bad, right? diff --git a/src/UI/Views/Settings.tsx b/src/UI/Views/Settings.tsx index 3ad44cca..9c585d0e 100644 --- a/src/UI/Views/Settings.tsx +++ b/src/UI/Views/Settings.tsx @@ -10,7 +10,7 @@ import { TooltipHost, } from '@fluentui/react'; import { Ipc, Util } from '@freik/electron-render'; -import { IgnoreItemType, IpcId, Keys, st, StrId } from '@freik/emp-shared'; +import { IgnoreItemTypeEnum, IpcId, Keys, st, StrId } from '@freik/emp-shared'; import { isDefined } from '@freik/typechk'; import { Catch, @@ -152,7 +152,7 @@ function MusicLocations(): JSX.Element { ); } -const ignoreTypeNameMap = new Map([ +const ignoreTypeNameMap = new Map([ ['path-root', 'Root Path'], ['dir-name', 'Directory Name'], ['path-keyword', 'Keyword'], @@ -164,7 +164,7 @@ const ignoreOptions: IDropdownOption[] = [...ignoreTypeNameMap.entries()].map( function IgnoreList(): JSX.Element { const ignoreItems = useRecoilValue(ignoreItemsState); - const [newType, setNewType] = useState(''); + const [newType, setNewType] = useState(''); const [newValue, setNewValue] = useState(''); return (
@@ -191,7 +191,7 @@ function IgnoreList(): JSX.Element { selectedKey={newType} onChange={(ev: unknown, option?: IDropdownOption) => { if (isDefined(option) && option.key !== '') { - setNewType(option.key as IgnoreItemType); + setNewType(option.key as IgnoreItemTypeEnum); } }} options={ignoreOptions} diff --git a/src/UI/Views/Tools/Transcoder.tsx b/src/UI/Views/Tools/Transcoder.tsx index b20d9f07..b2c3caf2 100644 --- a/src/UI/Views/Tools/Transcoder.tsx +++ b/src/UI/Views/Tools/Transcoder.tsx @@ -7,11 +7,7 @@ import { TextField, } from '@fluentui/react'; import { Ipc, Util } from '@freik/electron-render'; -import { - IpcId, - TranscodeSourceType, - isTranscodeSourceType, -} from '@freik/emp-shared'; +import { IpcId, TranscodeSource, isTranscodeSource } from '@freik/emp-shared'; import { isArrayOfString, isDefined } from '@freik/typechk'; import { StateToggle, useBoolState } from '@freik/web-utils'; import { useState } from 'react'; @@ -50,10 +46,10 @@ const targetFormats: IDropdownOption[] = [ */ const sourceOptions: IComboBoxOption[] = [ - { key: TranscodeSourceType.Playlist, text: 'Playlist' }, - { key: TranscodeSourceType.Artist, text: 'Artist' }, - { key: TranscodeSourceType.Album, text: 'Album' }, - { key: TranscodeSourceType.Disk, text: 'Disk location' }, + { key: TranscodeSource.Playlist, text: 'Playlist' }, + { key: TranscodeSource.Artist, text: 'Artist' }, + { key: TranscodeSource.Album, text: 'Album' }, + { key: TranscodeSource.Disk, text: 'Disk location' }, ]; const getDir = ( @@ -94,7 +90,7 @@ export function TranscoderConfiguration(): JSX.Element { event: React.FormEvent, option?: IDropdownOption, ): void => { - if (isDefined(option) && isTranscodeSourceType(option.key)) { + if (isDefined(option) && isTranscodeSource(option.key)) { setSrcLocType(option.key); } }; @@ -102,18 +98,18 @@ export function TranscoderConfiguration(): JSX.Element { // TODO: Create the element for the transcode source type (and populated it, if appropriate) let xcodeSrcLocElem; switch (srcLocType) { - case TranscodeSourceType.Playlist: + case TranscodeSource.Playlist: xcodeSrcLocElem = ( ); break; - case TranscodeSourceType.Artist: + case TranscodeSource.Artist: xcodeSrcLocElem = ; break; - case TranscodeSourceType.Album: + case TranscodeSource.Album: xcodeSrcLocElem = ; break; - case TranscodeSourceType.Disk: + case TranscodeSource.Disk: default: xcodeSrcLocElem = (