morille 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -3
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +2 -1
- package/dist/app.js.map +1 -1
- package/dist/components/device-indicator.d.ts +18 -0
- package/dist/components/device-indicator.d.ts.map +1 -0
- package/dist/components/device-indicator.js +53 -0
- package/dist/components/device-indicator.js.map +1 -0
- package/dist/components/device-picker-view.d.ts +10 -0
- package/dist/components/device-picker-view.d.ts.map +1 -0
- package/dist/components/device-picker-view.js +65 -0
- package/dist/components/device-picker-view.js.map +1 -0
- package/dist/components/panel-content.d.ts.map +1 -1
- package/dist/components/panel-content.js +4 -0
- package/dist/components/panel-content.js.map +1 -0
- package/dist/components/player.d.ts.map +1 -1
- package/dist/components/player.js +35 -3
- package/dist/components/player.js.map +1 -1
- package/dist/contexts/devices-context.d.ts +28 -0
- package/dist/contexts/devices-context.d.ts.map +1 -0
- package/dist/contexts/devices-context.js +33 -0
- package/dist/contexts/devices-context.js.map +1 -0
- package/dist/contexts/panel-mode-context.d.ts +2 -1
- package/dist/contexts/panel-mode-context.d.ts.map +1 -0
- package/dist/contexts/panel-mode-context.js +3 -0
- package/dist/contexts/panel-mode-context.js.map +1 -0
- package/dist/hooks/use-album-art.d.ts.map +1 -1
- package/dist/hooks/use-album-art.js +2 -1
- package/dist/hooks/use-album-art.js.map +1 -1
- package/dist/hooks/use-browse.d.ts.map +1 -1
- package/dist/hooks/use-browse.js +4 -3
- package/dist/hooks/use-browse.js.map +1 -1
- package/dist/hooks/use-devices.d.ts +24 -0
- package/dist/hooks/use-devices.d.ts.map +1 -0
- package/dist/hooks/use-devices.js +106 -0
- package/dist/hooks/use-devices.js.map +1 -0
- package/dist/hooks/use-playback.d.ts +7 -0
- package/dist/hooks/use-playback.d.ts.map +1 -1
- package/dist/hooks/use-playback.js +31 -9
- package/dist/hooks/use-playback.js.map +1 -1
- package/dist/hooks/use-player-input.d.ts.map +1 -1
- package/dist/hooks/use-player-input.js +31 -2
- package/dist/hooks/use-player-input.js.map +1 -0
- package/dist/hooks/use-queue.d.ts.map +1 -1
- package/dist/hooks/use-queue.js +3 -2
- package/dist/hooks/use-queue.js.map +1 -1
- package/dist/hooks/use-search.d.ts.map +1 -1
- package/dist/hooks/use-search.js +2 -1
- package/dist/hooks/use-search.js.map +1 -0
- package/dist/icons.d.ts +7 -0
- package/dist/icons.d.ts.map +1 -1
- package/dist/icons.js +8 -0
- package/dist/icons.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +9 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +15 -0
- package/dist/logger.js.map +1 -0
- package/dist/spotify/auth.d.ts.map +1 -1
- package/dist/spotify/auth.js +2 -1
- package/dist/spotify/auth.js.map +1 -1
- package/dist/spotify/client.d.ts.map +1 -1
- package/dist/spotify/client.js +2 -1
- package/dist/spotify/client.js.map +1 -1
- package/dist/spotify/devices.d.ts +36 -0
- package/dist/spotify/devices.d.ts.map +1 -0
- package/dist/spotify/devices.js +72 -0
- package/dist/spotify/devices.js.map +1 -0
- package/dist/spotify/fetch-with-retry.d.ts.map +1 -1
- package/dist/spotify/fetch-with-retry.js +5 -4
- package/dist/spotify/fetch-with-retry.js.map +1 -0
- package/dist/spotify/lyrics.d.ts.map +1 -1
- package/dist/spotify/lyrics.js +3 -2
- package/dist/spotify/lyrics.js.map +1 -1
- package/dist/spotify/playback.d.ts +3 -0
- package/dist/spotify/playback.d.ts.map +1 -1
- package/dist/spotify/playback.js +39 -21
- package/dist/spotify/playback.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -43,6 +43,21 @@ and rebuild.
|
|
|
43
43
|
|
|
44
44
|
[quota]: https://developer.spotify.com/documentation/web-api/concepts/quota-modes
|
|
45
45
|
|
|
46
|
+
### Debug output
|
|
47
|
+
|
|
48
|
+
morille is silent on stderr by default so the terminal UI stays clean. To see
|
|
49
|
+
internal diagnostics (fetch traces, retry notices, auth and API errors), run
|
|
50
|
+
with the `--debug` flag or set the `DEBUG=1` environment variable:
|
|
51
|
+
|
|
52
|
+
```sh
|
|
53
|
+
npx morille --debug
|
|
54
|
+
# or
|
|
55
|
+
DEBUG=1 npx morille
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Debug output is written to stderr and will visibly interfere with the ink UI —
|
|
59
|
+
this mode is intended for development, not regular use.
|
|
60
|
+
|
|
46
61
|
## Usage
|
|
47
62
|
|
|
48
63
|
- **Space** - toggle play/pause
|
|
@@ -74,9 +89,6 @@ pnpm test:biome # lint/format check
|
|
|
74
89
|
|
|
75
90
|
- Add track to queue
|
|
76
91
|
- Device selection / transfer playback
|
|
77
|
-
- ~~Search tracks, albums, artists, and playlists~~
|
|
78
|
-
- ~~Browse and play playlists~~
|
|
79
|
-
- ~~Browse and play albums~~
|
|
80
92
|
- Show recently played tracks
|
|
81
93
|
- Like / unlike tracks (save to library)
|
|
82
94
|
- Keyboard shortcuts customization
|
package/dist/app.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.tsx"],"names":[],"mappings":"AAOA;;;GAGG;AACH,wBAAgB,GAAG,4CAmFlB"}
|
package/dist/app.js
CHANGED
|
@@ -2,6 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { Box, Text, useApp, useInput } from 'ink';
|
|
3
3
|
import { useEffect, useRef, useState } from 'react';
|
|
4
4
|
import { Player } from './components/player.js';
|
|
5
|
+
import { logger } from './logger.js';
|
|
5
6
|
import { createSpotifyClient, getClientId } from './spotify/client.js';
|
|
6
7
|
/**
|
|
7
8
|
* Root application component. Handles Spotify authentication on mount,
|
|
@@ -31,7 +32,7 @@ export function App() {
|
|
|
31
32
|
}
|
|
32
33
|
}
|
|
33
34
|
catch (err) {
|
|
34
|
-
|
|
35
|
+
logger.error('Spotify authentication failed:', err);
|
|
35
36
|
if (!cancelled) {
|
|
36
37
|
setAuthError(err instanceof Error ? err.message : 'Authentication failed');
|
|
37
38
|
}
|
package/dist/app.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACpD,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChD,OAAO,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAEvE;;;GAGG;AACH,MAAM,UAAU,GAAG;IACjB,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAoB,IAAI,CAAC,CAAC;IAC9D,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;IAChE,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;IAC5D,MAAM,cAAc,GAAG,MAAM,CAAsB,IAAI,CAAC,CAAC;IACzD,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,EAAE,CAAC;IAE1B,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,SAAS,GAAG,KAAK,CAAC;QAEtB,KAAK,UAAU,IAAI;YACjB,IAAI,CAAC;gBACH,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;gBAC/B,MAAM,OAAO,GAAG,MAAM,mBAAmB,CAAC,QAAQ,EAAE;oBAClD,SAAS,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE;wBACzB,IAAI,CAAC,SAAS,EAAE,CAAC;4BACf,UAAU,CAAC,GAAG,CAAC,CAAC;4BAChB,cAAc,CAAC,OAAO,GAAG,MAAM,CAAC;wBAClC,CAAC;oBACH,CAAC;iBACF,CAAC,CAAC;gBACH,IAAI,CAAC,SAAS,EAAE,CAAC;oBACf,SAAS,CAAC,OAAO,CAAC,CAAC;gBACrB,CAAC;YACH,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,
|
|
1
|
+
{"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { DeviceType } from '../spotify/devices.js';
|
|
2
|
+
type DeviceIndicatorProps = {
|
|
3
|
+
name: string | null;
|
|
4
|
+
type: DeviceType | null;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Picks a glyph for a device type. Kept as an exported helper so the
|
|
8
|
+
* device-picker-view can reuse it next to each row without duplicating the
|
|
9
|
+
* icon-to-type mapping.
|
|
10
|
+
*/
|
|
11
|
+
export declare function deviceIcon(type: DeviceType | null): string;
|
|
12
|
+
/**
|
|
13
|
+
* Compact always-visible header badge showing which Spotify Connect device
|
|
14
|
+
* is currently playing. On narrow terminals (<60 columns) only the glyph is
|
|
15
|
+
* rendered so the animated title still has room.
|
|
16
|
+
*/
|
|
17
|
+
export declare function DeviceIndicator({ name, type }: DeviceIndicatorProps): import("react/jsx-runtime").JSX.Element;
|
|
18
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"device-indicator.d.ts","sourceRoot":"","sources":["../../src/components/device-indicator.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAIxD,KAAK,oBAAoB,GAAG;IAC1B,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,IAAI,EAAE,UAAU,GAAG,IAAI,CAAC;CACzB,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,GAAG,MAAM,CA2B1D;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,oBAAoB,2CAanE"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Text, useWindowSize } from 'ink';
|
|
3
|
+
import { ICON_DEVICE_CAR, ICON_DEVICE_COMPUTER, ICON_DEVICE_GAME, ICON_DEVICE_PHONE, ICON_DEVICE_SPEAKER, ICON_DEVICE_TV, ICON_DEVICE_UNKNOWN, } from '../icons.js';
|
|
4
|
+
const MIN_WIDE_COLUMNS = 60;
|
|
5
|
+
/**
|
|
6
|
+
* Picks a glyph for a device type. Kept as an exported helper so the
|
|
7
|
+
* device-picker-view can reuse it next to each row without duplicating the
|
|
8
|
+
* icon-to-type mapping.
|
|
9
|
+
*/
|
|
10
|
+
export function deviceIcon(type) {
|
|
11
|
+
switch (type) {
|
|
12
|
+
case 'Computer':
|
|
13
|
+
return ICON_DEVICE_COMPUTER;
|
|
14
|
+
case 'Smartphone':
|
|
15
|
+
return ICON_DEVICE_PHONE;
|
|
16
|
+
case 'Speaker':
|
|
17
|
+
case 'AVR':
|
|
18
|
+
case 'STB':
|
|
19
|
+
case 'AudioDongle':
|
|
20
|
+
case 'CastAudio':
|
|
21
|
+
return ICON_DEVICE_SPEAKER;
|
|
22
|
+
case 'TV':
|
|
23
|
+
case 'CastVideo':
|
|
24
|
+
return ICON_DEVICE_TV;
|
|
25
|
+
case 'Automobile':
|
|
26
|
+
return ICON_DEVICE_CAR;
|
|
27
|
+
case 'GameConsole':
|
|
28
|
+
return ICON_DEVICE_GAME;
|
|
29
|
+
case 'Unknown':
|
|
30
|
+
case null:
|
|
31
|
+
return ICON_DEVICE_UNKNOWN;
|
|
32
|
+
default: {
|
|
33
|
+
const _exhaustive = type;
|
|
34
|
+
return _exhaustive;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Compact always-visible header badge showing which Spotify Connect device
|
|
40
|
+
* is currently playing. On narrow terminals (<60 columns) only the glyph is
|
|
41
|
+
* rendered so the animated title still has room.
|
|
42
|
+
*/
|
|
43
|
+
export function DeviceIndicator({ name, type }) {
|
|
44
|
+
const { columns } = useWindowSize();
|
|
45
|
+
const glyph = deviceIcon(type);
|
|
46
|
+
if (!name) {
|
|
47
|
+
return _jsx(Text, { dimColor: true, children: `${glyph} no device` });
|
|
48
|
+
}
|
|
49
|
+
if (columns < MIN_WIDE_COLUMNS) {
|
|
50
|
+
return _jsx(Text, { dimColor: true, children: glyph });
|
|
51
|
+
}
|
|
52
|
+
return _jsx(Text, { dimColor: true, children: `${glyph} ${name}` });
|
|
53
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"device-indicator.js","sourceRoot":"","sources":["../../src/components/device-indicator.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAC1C,OAAO,EACL,eAAe,EACf,oBAAoB,EACpB,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,EACnB,cAAc,EACd,mBAAmB,GACpB,MAAM,aAAa,CAAC;AAGrB,MAAM,gBAAgB,GAAG,EAAE,CAAC;AAO5B;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAC,IAAuB;IAChD,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,UAAU;YACb,OAAO,oBAAoB,CAAC;QAC9B,KAAK,YAAY;YACf,OAAO,iBAAiB,CAAC;QAC3B,KAAK,SAAS,CAAC;QACf,KAAK,KAAK,CAAC;QACX,KAAK,KAAK,CAAC;QACX,KAAK,aAAa,CAAC;QACnB,KAAK,WAAW;YACd,OAAO,mBAAmB,CAAC;QAC7B,KAAK,IAAI,CAAC;QACV,KAAK,WAAW;YACd,OAAO,cAAc,CAAC;QACxB,KAAK,YAAY;YACf,OAAO,eAAe,CAAC;QACzB,KAAK,aAAa;YAChB,OAAO,gBAAgB,CAAC;QAC1B,KAAK,SAAS,CAAC;QACf,KAAK,IAAI;YACP,OAAO,mBAAmB,CAAC;QAC7B,SAAS,CAAC;YACR,MAAM,WAAW,GAAU,IAAI,CAAC;YAChC,OAAO,WAAW,CAAC;QACrB,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,EAAE,IAAI,EAAE,IAAI,EAAwB;IAClE,MAAM,EAAE,OAAO,EAAE,GAAG,aAAa,EAAE,CAAC;IACpC,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;IAE/B,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,KAAC,IAAI,IAAC,QAAQ,kBAAE,GAAG,KAAK,YAAY,GAAQ,CAAC;IACtD,CAAC;IAED,IAAI,OAAO,GAAG,gBAAgB,EAAE,CAAC;QAC/B,OAAO,KAAC,IAAI,IAAC,QAAQ,kBAAE,KAAK,GAAQ,CAAC;IACvC,CAAC;IAED,OAAO,KAAC,IAAI,IAAC,QAAQ,kBAAE,GAAG,KAAK,IAAI,IAAI,EAAE,GAAQ,CAAC;AACpD,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
type DevicePickerViewProps = {
|
|
2
|
+
height: number;
|
|
3
|
+
};
|
|
4
|
+
/**
|
|
5
|
+
* Device picker panel — lists Spotify Connect devices and lets the user
|
|
6
|
+
* transfer playback to one. The currently active device is highlighted in
|
|
7
|
+
* green; arrow keys move the cursor and enter triggers the transfer.
|
|
8
|
+
*/
|
|
9
|
+
export declare function DevicePickerView({ height }: DevicePickerViewProps): import("react/jsx-runtime").JSX.Element;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"device-picker-view.d.ts","sourceRoot":"","sources":["../../src/components/device-picker-view.tsx"],"names":[],"mappings":"AAKA,KAAK,qBAAqB,GAAG;IAC3B,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAuCF;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,MAAM,EAAE,EAAE,qBAAqB,2CAsDjE"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Box, Text } from 'ink';
|
|
3
|
+
import { useDevicesContext } from '../contexts/devices-context.js';
|
|
4
|
+
import { deviceIcon } from './device-indicator.js';
|
|
5
|
+
function formatType(type) {
|
|
6
|
+
if (type === 'Unknown')
|
|
7
|
+
return '';
|
|
8
|
+
if (type === 'AVR' || type === 'STB' || type === 'TV')
|
|
9
|
+
return type;
|
|
10
|
+
// Break "GameConsole" / "CastVideo" / "CastAudio" / "AudioDongle" into two words
|
|
11
|
+
return type.replace(/([a-z])([A-Z])/g, '$1 $2');
|
|
12
|
+
}
|
|
13
|
+
function formatVolume(vol) {
|
|
14
|
+
if (vol === null)
|
|
15
|
+
return '';
|
|
16
|
+
return `${vol}%`;
|
|
17
|
+
}
|
|
18
|
+
function DeviceRow({ device, isSelected }) {
|
|
19
|
+
const icon = deviceIcon(device.type);
|
|
20
|
+
const type = formatType(device.type);
|
|
21
|
+
const volume = formatVolume(device.volumePercent);
|
|
22
|
+
const details = [
|
|
23
|
+
type,
|
|
24
|
+
volume,
|
|
25
|
+
]
|
|
26
|
+
.filter((s) => s.length > 0)
|
|
27
|
+
.join(' · ');
|
|
28
|
+
const label = details ? `${icon} ${device.name} ${details}` : `${icon} ${device.name}`;
|
|
29
|
+
if (device.isActive) {
|
|
30
|
+
return (_jsx(Text, { bold: true, color: "green", inverse: isSelected, children: label }));
|
|
31
|
+
}
|
|
32
|
+
if (isSelected) {
|
|
33
|
+
return _jsx(Text, { inverse: true, children: label });
|
|
34
|
+
}
|
|
35
|
+
return _jsx(Text, { children: label });
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Device picker panel — lists Spotify Connect devices and lets the user
|
|
39
|
+
* transfer playback to one. The currently active device is highlighted in
|
|
40
|
+
* green; arrow keys move the cursor and enter triggers the transfer.
|
|
41
|
+
*/
|
|
42
|
+
export function DevicePickerView({ height }) {
|
|
43
|
+
const { devices, isLoading, selectedIndex, error } = useDevicesContext();
|
|
44
|
+
if (isLoading && devices.length === 0) {
|
|
45
|
+
return _jsx(Text, { dimColor: true, children: "Loading devices..." });
|
|
46
|
+
}
|
|
47
|
+
if (devices.length === 0) {
|
|
48
|
+
return _jsx(Text, { dimColor: true, children: "No devices available. Open Spotify on a device to connect." });
|
|
49
|
+
}
|
|
50
|
+
const activeName = devices.find((d) => d.isActive)?.name ?? null;
|
|
51
|
+
const headerLines = 1;
|
|
52
|
+
const availableHeight = Math.max(height - headerLines, 2);
|
|
53
|
+
const visibleCount = Math.min(availableHeight, devices.length);
|
|
54
|
+
const halfHeight = Math.floor(availableHeight / 2);
|
|
55
|
+
const startIndex = Math.max(0, Math.min(selectedIndex - halfHeight, devices.length - visibleCount));
|
|
56
|
+
return (_jsxs(Box, { flexDirection: "column", height: height, overflow: "hidden", children: [_jsxs(Box, { gap: 1, borderColor: "gray", borderStyle: "single", borderBottom: true, borderLeft: false, borderRight: false, borderTop: false, children: [_jsx(Text, { bold: true, children: "Devices" }), _jsx(Text, { dimColor: true, children: "-" }), _jsxs(Text, { dimColor: true, children: [devices.length, " available"] }), activeName && _jsxs(Text, { dimColor: true, children: ["\u00B7 on ", activeName] })] }), Array.from({
|
|
57
|
+
length: visibleCount,
|
|
58
|
+
}, (_, i) => {
|
|
59
|
+
const idx = startIndex + i;
|
|
60
|
+
const device = devices[idx];
|
|
61
|
+
if (!device)
|
|
62
|
+
return _jsx(Text, { children: " " }, idx);
|
|
63
|
+
return _jsx(DeviceRow, { device: device, isSelected: idx === selectedIndex }, device.id);
|
|
64
|
+
}), error && (_jsx(Box, { marginTop: 1, children: _jsx(Text, { color: "red", children: error }) }))] }));
|
|
65
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"device-picker-view.js","sourceRoot":"","sources":["../../src/components/device-picker-view.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"panel-content.d.ts","sourceRoot":"","sources":["../../src/components/panel-content.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"panel-content.d.ts","sourceRoot":"","sources":["../../src/components/panel-content.tsx"],"names":[],"mappings":"AAMA,KAAK,iBAAiB,GAAG;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF;;;GAGG;AACH,wBAAgB,YAAY,CAAC,EAAE,UAAU,EAAE,MAAM,EAAE,EAAE,iBAAiB,kDAoBrE"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { usePanelMode } from '../contexts/panel-mode-context.js';
|
|
3
|
+
import { DevicePickerView } from './device-picker-view.js';
|
|
3
4
|
import { LyricsPanel } from './lyrics-panel.js';
|
|
4
5
|
import { QueueView } from './queue-view.js';
|
|
5
6
|
import { SearchPanel } from './search-panel.js';
|
|
@@ -18,5 +19,8 @@ export function PanelContent({ progressMs, height }) {
|
|
|
18
19
|
if (panelMode === 'search') {
|
|
19
20
|
return _jsx(SearchPanel, { height: height });
|
|
20
21
|
}
|
|
22
|
+
if (panelMode === 'devices') {
|
|
23
|
+
return _jsx(DevicePickerView, { height: height });
|
|
24
|
+
}
|
|
21
25
|
return null;
|
|
22
26
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"panel-content.js","sourceRoot":"","sources":["../../src/components/panel-content.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AACjE,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAOhD;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,EAAE,UAAU,EAAE,MAAM,EAAqB;IACpE,MAAM,EAAE,SAAS,EAAE,GAAG,YAAY,EAAE,CAAC;IAErC,IAAI,SAAS,KAAK,QAAQ,EAAE,CAAC;QAC3B,OAAO,KAAC,WAAW,IAAC,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,GAAI,CAAC;IACjE,CAAC;IAED,IAAI,SAAS,KAAK,OAAO,EAAE,CAAC;QAC1B,OAAO,KAAC,SAAS,IAAC,MAAM,EAAE,MAAM,GAAI,CAAC;IACvC,CAAC;IAED,IAAI,SAAS,KAAK,QAAQ,EAAE,CAAC;QAC3B,OAAO,KAAC,WAAW,IAAC,MAAM,EAAE,MAAM,GAAI,CAAC;IACzC,CAAC;IAED,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QAC5B,OAAO,KAAC,gBAAgB,IAAC,MAAM,EAAE,MAAM,GAAI,CAAC;IAC9C,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"player.d.ts","sourceRoot":"","sources":["../../src/components/player.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"player.d.ts","sourceRoot":"","sources":["../../src/components/player.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAuB1D,KAAK,WAAW,GAAG;IACjB,MAAM,EAAE,UAAU,CAAC;CACpB,CAAC;AAgNF;;GAEG;AACH,wBAAgB,MAAM,CAAC,EAAE,MAAM,EAAE,EAAE,WAAW,2CAM7C"}
|
|
@@ -2,6 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { Box, Spacer, useWindowSize } from 'ink';
|
|
3
3
|
import { useMemo } from 'react';
|
|
4
4
|
import { LYRICS_WIDE_COLUMNS } from '../config.js';
|
|
5
|
+
import { DevicesProvider } from '../contexts/devices-context.js';
|
|
5
6
|
import { LyricsProvider, useLyricsContext } from '../contexts/lyrics-context.js';
|
|
6
7
|
import { PanelModeProvider, usePanelMode } from '../contexts/panel-mode-context.js';
|
|
7
8
|
import { QueueProvider } from '../contexts/queue-context.js';
|
|
@@ -12,6 +13,7 @@ import { usePlayerInput } from '../hooks/use-player-input.js';
|
|
|
12
13
|
import { ICON_ARROW_HORIZONTAL, ICON_ARROW_VERTICAL } from '../icons.js';
|
|
13
14
|
import { AnimatedSubtitle } from './animated-subtitle.js';
|
|
14
15
|
import { AnimatedTitle } from './animated-title.js';
|
|
16
|
+
import { DeviceIndicator } from './device-indicator.js';
|
|
15
17
|
import { KeyboardHints } from './keyboard-hints.js';
|
|
16
18
|
import { PanelContent } from './panel-content.js';
|
|
17
19
|
import { PlaybackStatus } from './playback-status.js';
|
|
@@ -107,6 +109,30 @@ function buildHints(panelMode, lyricsOffset, isPlainText, isInputMode) {
|
|
|
107
109
|
},
|
|
108
110
|
];
|
|
109
111
|
}
|
|
112
|
+
if (panelMode === 'devices') {
|
|
113
|
+
return [
|
|
114
|
+
{
|
|
115
|
+
key: ICON_ARROW_VERTICAL,
|
|
116
|
+
label: 'navigate',
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
key: 'enter',
|
|
120
|
+
label: 'switch',
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
key: 'c',
|
|
124
|
+
label: 'close',
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
key: 'esc',
|
|
128
|
+
label: 'close',
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
key: 'q',
|
|
132
|
+
label: 'quit',
|
|
133
|
+
},
|
|
134
|
+
];
|
|
135
|
+
}
|
|
110
136
|
if (panelMode === 'lyrics') {
|
|
111
137
|
const hints = [];
|
|
112
138
|
if (isPlainText) {
|
|
@@ -175,6 +201,10 @@ function buildHints(panelMode, lyricsOffset, isPlainText, isInputMode) {
|
|
|
175
201
|
key: 'b',
|
|
176
202
|
label: 'playlists',
|
|
177
203
|
},
|
|
204
|
+
{
|
|
205
|
+
key: 'c',
|
|
206
|
+
label: 'devices',
|
|
207
|
+
},
|
|
178
208
|
{
|
|
179
209
|
key: 'q',
|
|
180
210
|
label: 'quit',
|
|
@@ -195,12 +225,12 @@ function PlayerWithProviders({ client }) {
|
|
|
195
225
|
const { track, isLoading, error } = playback;
|
|
196
226
|
const { columns, rows } = useWindowSize();
|
|
197
227
|
const { panelMode, hasPanel } = usePanelMode();
|
|
198
|
-
return (_jsx(LyricsProvider, { track: track, children: _jsx(QueueProvider, { client: client, track: track, playTrackUri: playback.playTrackUri, refresh: playback.refresh, children: _jsx(SearchProvider, { client: client, track: track, playTrackUri: playback.playTrackUri, refresh: playback.refresh, children: _jsx(PlayerUI, { playback: playback, track: track, isLoading: isLoading, error: error, columns: columns, rows: rows, panelMode: panelMode, hasPanel: hasPanel }) }) }) }));
|
|
228
|
+
return (_jsx(LyricsProvider, { track: track, children: _jsx(QueueProvider, { client: client, track: track, playTrackUri: playback.playTrackUri, refresh: playback.refresh, children: _jsx(SearchProvider, { client: client, track: track, playTrackUri: playback.playTrackUri, refresh: playback.refresh, children: _jsx(DevicesProvider, { client: client, track: track, children: _jsx(PlayerUI, { playback: playback, track: track, activeDevice: playback.activeDevice, isLoading: isLoading, error: error, columns: columns, rows: rows, panelMode: panelMode, hasPanel: hasPanel }) }) }) }) }));
|
|
199
229
|
}
|
|
200
230
|
/**
|
|
201
231
|
* Pure UI component - consumes contexts for panel data, receives playback as props.
|
|
202
232
|
*/
|
|
203
|
-
function PlayerUI({ playback, track, isLoading, error, columns, rows, panelMode, hasPanel }) {
|
|
233
|
+
function PlayerUI({ playback, track, activeDevice, isLoading, error, columns, rows, panelMode, hasPanel, }) {
|
|
204
234
|
const { offset: lyricsOffset, isPlainText: isPlainLyrics } = useLyricsContext();
|
|
205
235
|
const { isInputMode } = usePanelMode();
|
|
206
236
|
const layout = computeLayout(columns, rows, hasPanel, false);
|
|
@@ -215,5 +245,7 @@ function PlayerUI({ playback, track, isLoading, error, columns, rows, panelMode,
|
|
|
215
245
|
]);
|
|
216
246
|
const showPanelWide = finalLayout.isPanelWide && hasPanel && !!track;
|
|
217
247
|
const showPanelNarrow = !finalLayout.isPanelWide && hasPanel && !!track;
|
|
218
|
-
|
|
248
|
+
const indicatorName = track?.deviceName ?? activeDevice?.name ?? null;
|
|
249
|
+
const indicatorType = track?.deviceType ?? activeDevice?.type ?? null;
|
|
250
|
+
return (_jsxs(Box, { flexDirection: "column", paddingX: 1, height: "100%", borderColor: "black", borderStyle: "single", children: [_jsxs(Box, { flexDirection: "row", children: [_jsx(AnimatedTitle, { text: "morille", isPlaying: track?.isPlaying ?? false }), _jsx(Spacer, {}), _jsx(DeviceIndicator, { name: indicatorName, type: indicatorType })] }), _jsx(AnimatedSubtitle, { hasError: !!error, hasTrack: !!track, isPlaying: track?.isPlaying ?? false, panelMode: panelMode }), _jsxs(Box, { marginTop: 1, flexDirection: showPanelWide ? 'row' : 'column', flexGrow: 1, children: [_jsx(Box, { flexDirection: "column", width: showPanelWide ? finalLayout.leftWidth : undefined, flexGrow: showPanelWide ? 0 : 1, children: _jsx(PlaybackStatus, { track: track, isLoading: isLoading, error: error, art: art, progressBarWidth: finalLayout.progressBarWidth }) }), showPanelWide && track && (_jsx(SidePanel, { width: finalLayout.panelColumnWidth || undefined, isWideLayout: true, children: _jsx(PanelContent, { progressMs: track.progressMs, height: finalLayout.panelHeight }) }))] }), showPanelNarrow && track && (_jsx(SidePanel, { width: undefined, isWideLayout: false, children: _jsx(PanelContent, { progressMs: track.progressMs, height: finalLayout.panelHeight }) })), _jsx(Spacer, {}), _jsx(KeyboardHints, { hints: hints }), _jsx(TrackFacts, { track: track })] }));
|
|
219
251
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"player.js","sourceRoot":"","sources":["../../src/components/player.tsx"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"player.js","sourceRoot":"","sources":["../../src/components/player.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAChC,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAEjF,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AACpF,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AACzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAM9C,MAAM,gBAAgB,GAAG,EAAE,CAAC;AAC5B,MAAM,SAAS,GAAG,EAAE,CAAC;AACrB,MAAM,gBAAgB,GAAG,EAAE,CAAC;AAC5B,MAAM,kBAAkB,GAAG,CAAC,CAAC;AAC7B,MAAM,cAAc,GAAG,EAAE,CAAC;AAC1B,MAAM,gBAAgB,GAAG,CAAC,CAAC;AAC3B,MAAM,mBAAmB,GAAG,CAAC,CAAC;AAE9B,SAAS,aAAa,CAAC,OAAe,EAAE,IAAY,EAAE,QAAiB,EAAE,MAAe;IACtF,MAAM,OAAO,GAAG,CAAC,CAAC;IAClB,MAAM,MAAM,GAAG,OAAO,IAAI,gBAAgB,CAAC;IAC3C,MAAM,WAAW,GAAG,OAAO,IAAI,mBAAmB,CAAC;IACnD,MAAM,QAAQ,GAAG,MAAM,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5C,MAAM,WAAW,GAAG,CAAC,CAAC;IACtB,MAAM,gBAAgB,GAAG,WAAW,IAAI,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,GAAG,OAAO,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/F,MAAM,SAAS,GAAG,OAAO,GAAG,OAAO,GAAG,CAAC,GAAG,gBAAgB,GAAG,CAAC,gBAAgB,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAE5F,OAAO;QACL,MAAM;QACN,WAAW;QACX,SAAS,EAAE,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,GAAG,kBAAkB,EAAE,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC;QACxF,gBAAgB,EAAE,IAAI,CAAC,GAAG,CAAC,SAAS,GAAG,QAAQ,GAAG,WAAW,GAAG,gBAAgB,EAAE,EAAE,CAAC;QACrF,gBAAgB;QAChB,SAAS;QACT,WAAW,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,GAAG,mBAAmB,EAAE,gBAAgB,CAAC;KACpE,CAAC;AACJ,CAAC;AAED,SAAS,UAAU,CAAC,SAAoB,EAAE,YAAoB,EAAE,WAAoB,EAAE,WAAoB;IACxG,IAAI,SAAS,KAAK,QAAQ,IAAI,WAAW,EAAE,CAAC;QAC1C,OAAO;YACL;gBACE,GAAG,EAAE,MAAM;gBACX,KAAK,EAAE,QAAQ;aAChB;YACD;gBACE,GAAG,EAAE,OAAO;gBACZ,KAAK,EAAE,QAAQ;aAChB;YACD;gBACE,GAAG,EAAE,KAAK;gBACV,KAAK,EAAE,OAAO;aACf;SACF,CAAC;IACJ,CAAC;IAED,IAAI,SAAS,KAAK,QAAQ,EAAE,CAAC;QAC3B,OAAO;YACL;gBACE,GAAG,EAAE,mBAAmB;gBACxB,KAAK,EAAE,UAAU;aAClB;YACD;gBACE,GAAG,EAAE,qBAAqB;gBAC1B,KAAK,EAAE,UAAU;aAClB;YACD;gBACE,GAAG,EAAE,OAAO;gBACZ,KAAK,EAAE,QAAQ;aAChB;YACD;gBACE,GAAG,EAAE,KAAK;gBACV,KAAK,EAAE,MAAM;aACd;YACD;gBACE,GAAG,EAAE,GAAG;gBACR,KAAK,EAAE,MAAM;aACd;SACF,CAAC;IACJ,CAAC;IAED,IAAI,SAAS,KAAK,OAAO,EAAE,CAAC;QAC1B,OAAO;YACL;gBACE,GAAG,EAAE,mBAAmB;gBACxB,KAAK,EAAE,UAAU;aAClB;YACD;gBACE,GAAG,EAAE,OAAO;gBACZ,KAAK,EAAE,MAAM;aACd;YACD;gBACE,GAAG,EAAE,GAAG;gBACR,KAAK,EAAE,OAAO;aACf;YACD;gBACE,GAAG,EAAE,KAAK;gBACV,KAAK,EAAE,OAAO;aACf;YACD;gBACE,GAAG,EAAE,GAAG;gBACR,KAAK,EAAE,MAAM;aACd;SACF,CAAC;IACJ,CAAC;IAED,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QAC5B,OAAO;YACL;gBACE,GAAG,EAAE,mBAAmB;gBACxB,KAAK,EAAE,UAAU;aAClB;YACD;gBACE,GAAG,EAAE,OAAO;gBACZ,KAAK,EAAE,QAAQ;aAChB;YACD;gBACE,GAAG,EAAE,GAAG;gBACR,KAAK,EAAE,OAAO;aACf;YACD;gBACE,GAAG,EAAE,KAAK;gBACV,KAAK,EAAE,OAAO;aACf;YACD;gBACE,GAAG,EAAE,GAAG;gBACR,KAAK,EAAE,MAAM;aACd;SACF,CAAC;IACJ,CAAC;IAED,IAAI,SAAS,KAAK,QAAQ,EAAE,CAAC;QAC3B,MAAM,KAAK,GAAG,EAAE,CAAC;QACjB,IAAI,WAAW,EAAE,CAAC;YAChB,KAAK,CAAC,IAAI,CAAC;gBACT,GAAG,EAAE,mBAAmB;gBACxB,KAAK,EAAE,QAAQ;aAChB,CAAC,CAAC;QACL,CAAC;QACD,KAAK,CAAC,IAAI,CACR;YACE,GAAG,EAAE,KAAK;YACV,KAAK,EAAE,UAAU,YAAY,KAAK;SACnC,EACD;YACE,GAAG,EAAE,GAAG;YACR,KAAK,EAAE,OAAO;SACf,EACD;YACE,GAAG,EAAE,KAAK;YACV,KAAK,EAAE,OAAO;SACf,EACD;YACE,GAAG,EAAE,GAAG;YACR,KAAK,EAAE,MAAM;SACd,CACF,CAAC;QACF,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO;QACL;YACE,GAAG,EAAE,OAAO;YACZ,KAAK,EAAE,YAAY;SACpB;QACD;YACE,GAAG,EAAE,GAAG;YACR,KAAK,EAAE,MAAM;SACd;QACD;YACE,GAAG,EAAE,GAAG;YACR,KAAK,EAAE,MAAM;SACd;QACD;YACE,GAAG,EAAE,qBAAqB;YAC1B,KAAK,EAAE,MAAM;SACd;QACD;YACE,GAAG,EAAE,mBAAmB;YACxB,KAAK,EAAE,KAAK;SACb;QACD;YACE,GAAG,EAAE,GAAG;YACR,KAAK,EAAE,SAAS;SACjB;QACD;YACE,GAAG,EAAE,GAAG;YACR,KAAK,EAAE,QAAQ;SAChB;QACD;YACE,GAAG,EAAE,GAAG;YACR,KAAK,EAAE,QAAQ;SAChB;QACD;YACE,GAAG,EAAE,GAAG;YACR,KAAK,EAAE,OAAO;SACf;QACD;YACE,GAAG,EAAE,GAAG;YACR,KAAK,EAAE,QAAQ;SAChB;QACD;YACE,GAAG,EAAE,GAAG;YACR,KAAK,EAAE,WAAW;SACnB;QACD;YACE,GAAG,EAAE,GAAG;YACR,KAAK,EAAE,SAAS;SACjB;QACD;YACE,GAAG,EAAE,GAAG;YACR,KAAK,EAAE,MAAM;SACd;KACF,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,MAAM,CAAC,EAAE,MAAM,EAAe;IAC5C,OAAO,CACL,KAAC,iBAAiB,cAChB,KAAC,mBAAmB,IAAC,MAAM,EAAE,MAAM,GAAI,GACrB,CACrB,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,mBAAmB,CAAC,EAAE,MAAM,EAAe;IAClD,MAAM,QAAQ,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;IACrC,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,QAAQ,CAAC;IAC7C,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,aAAa,EAAE,CAAC;IAC1C,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,YAAY,EAAE,CAAC;IAE/C,OAAO,CACL,KAAC,cAAc,IAAC,KAAK,EAAE,KAAK,YAC1B,KAAC,aAAa,IAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,QAAQ,CAAC,YAAY,EAAE,OAAO,EAAE,QAAQ,CAAC,OAAO,YACzG,KAAC,cAAc,IAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,QAAQ,CAAC,YAAY,EAAE,OAAO,EAAE,QAAQ,CAAC,OAAO,YAC1G,KAAC,eAAe,IAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,YAC3C,KAAC,QAAQ,IACP,QAAQ,EAAE,QAAQ,EAClB,KAAK,EAAE,KAAK,EACZ,YAAY,EAAE,QAAQ,CAAC,YAAY,EACnC,SAAS,EAAE,SAAS,EACpB,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,IAAI,EACV,SAAS,EAAE,SAAS,EACpB,QAAQ,EAAE,QAAQ,GAClB,GACc,GACH,GACH,GACD,CAClB,CAAC;AACJ,CAAC;AAcD;;GAEG;AACH,SAAS,QAAQ,CAAC,EAChB,QAAQ,EACR,KAAK,EACL,YAAY,EACZ,SAAS,EACT,KAAK,EACL,OAAO,EACP,IAAI,EACJ,SAAS,EACT,QAAQ,GACM;IACd,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,GAAG,gBAAgB,EAAE,CAAC;IAChF,MAAM,EAAE,WAAW,EAAE,GAAG,YAAY,EAAE,CAAC;IAEvC,MAAM,MAAM,GAAG,aAAa,CAAC,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;IAC7D,MAAM,GAAG,GAAG,WAAW,CAAC,MAAM,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,aAAa,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC;IACxG,MAAM,WAAW,GAAG,GAAG,CAAC,CAAC,CAAC,aAAa,CAAC,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;IAEhF,cAAc,CAAC,QAAQ,CAAC,CAAC;IAEzB,MAAM,KAAK,GAAG,OAAO,CACnB,GAAG,EAAE,CAAC,UAAU,CAAC,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,WAAW,CAAC,EACrE;QACE,SAAS;QACT,YAAY;QACZ,aAAa;QACb,WAAW;KACZ,CACF,CAAC;IAEF,MAAM,aAAa,GAAG,WAAW,CAAC,WAAW,IAAI,QAAQ,IAAI,CAAC,CAAC,KAAK,CAAC;IACrE,MAAM,eAAe,GAAG,CAAC,WAAW,CAAC,WAAW,IAAI,QAAQ,IAAI,CAAC,CAAC,KAAK,CAAC;IAExE,MAAM,aAAa,GAAG,KAAK,EAAE,UAAU,IAAI,YAAY,EAAE,IAAI,IAAI,IAAI,CAAC;IACtE,MAAM,aAAa,GAAG,KAAK,EAAE,UAAU,IAAI,YAAY,EAAE,IAAI,IAAI,IAAI,CAAC;IAEtE,OAAO,CACL,MAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,EAAC,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAC,MAAM,EAAC,WAAW,EAAC,OAAO,EAAC,WAAW,EAAC,QAAQ,aAC7F,MAAC,GAAG,IAAC,aAAa,EAAC,KAAK,aACtB,KAAC,aAAa,IAAC,IAAI,EAAC,SAAS,EAAC,SAAS,EAAE,KAAK,EAAE,SAAS,IAAI,KAAK,GAAI,EACtE,KAAC,MAAM,KAAG,EACV,KAAC,eAAe,IAAC,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,aAAa,GAAI,IACzD,EACN,KAAC,gBAAgB,IACf,QAAQ,EAAE,CAAC,CAAC,KAAK,EACjB,QAAQ,EAAE,CAAC,CAAC,KAAK,EACjB,SAAS,EAAE,KAAK,EAAE,SAAS,IAAI,KAAK,EACpC,SAAS,EAAE,SAAS,GACpB,EAEF,MAAC,GAAG,IAAC,SAAS,EAAE,CAAC,EAAE,aAAa,EAAE,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,EAAE,QAAQ,EAAE,CAAC,aAC7E,KAAC,GAAG,IACF,aAAa,EAAC,QAAQ,EACtB,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,EACxD,QAAQ,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,YAE/B,KAAC,cAAc,IACb,KAAK,EAAE,KAAK,EACZ,SAAS,EAAE,SAAS,EACpB,KAAK,EAAE,KAAK,EACZ,GAAG,EAAE,GAAG,EACR,gBAAgB,EAAE,WAAW,CAAC,gBAAgB,GAC9C,GACE,EAEL,aAAa,IAAI,KAAK,IAAI,CACzB,KAAC,SAAS,IAAC,KAAK,EAAE,WAAW,CAAC,gBAAgB,IAAI,SAAS,EAAE,YAAY,kBACvE,KAAC,YAAY,IAAC,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,CAAC,WAAW,GAAI,GACrE,CACb,IACG,EAEL,eAAe,IAAI,KAAK,IAAI,CAC3B,KAAC,SAAS,IAAC,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,KAAK,YAC9C,KAAC,YAAY,IAAC,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,CAAC,WAAW,GAAI,GACrE,CACb,EAED,KAAC,MAAM,KAAG,EAEV,KAAC,aAAa,IAAC,KAAK,EAAE,KAAK,GAAI,EAC/B,KAAC,UAAU,IAAC,KAAK,EAAE,KAAK,GAAI,IACxB,CACP,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { SpotifyApi } from '@spotify/web-api-ts-sdk';
|
|
2
|
+
import type { ReactNode } from 'react';
|
|
3
|
+
import type { SpotifyDevice } from '../spotify/devices.js';
|
|
4
|
+
import type { TrackInfo } from '../spotify/playback.js';
|
|
5
|
+
type DevicesContextValue = {
|
|
6
|
+
devices: SpotifyDevice[];
|
|
7
|
+
isLoading: boolean;
|
|
8
|
+
selectedIndex: number;
|
|
9
|
+
error: string | null;
|
|
10
|
+
devicesUp: (() => void) | undefined;
|
|
11
|
+
devicesDown: (() => void) | undefined;
|
|
12
|
+
devicesSelect: (() => Promise<void>) | undefined;
|
|
13
|
+
};
|
|
14
|
+
type DevicesProviderProps = {
|
|
15
|
+
client: SpotifyApi;
|
|
16
|
+
track: TrackInfo | null;
|
|
17
|
+
children: ReactNode;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Provides Spotify Connect device list and transfer-playback controls.
|
|
21
|
+
* Only fetches the device list while the devices panel is active.
|
|
22
|
+
*/
|
|
23
|
+
export declare function DevicesProvider({ client, track, children }: DevicesProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
24
|
+
/**
|
|
25
|
+
* Access the device list and transfer controls.
|
|
26
|
+
*/
|
|
27
|
+
export declare function useDevicesContext(): DevicesContextValue;
|
|
28
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"devices-context.d.ts","sourceRoot":"","sources":["../../src/contexts/devices-context.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAGxD,KAAK,mBAAmB,GAAG;IACzB,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB,SAAS,EAAE,OAAO,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,SAAS,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAC;IACpC,WAAW,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAC;IACtC,aAAa,EAAE,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,SAAS,CAAC;CAClD,CAAC;AAIF,KAAK,oBAAoB,GAAG;IAC1B,MAAM,EAAE,UAAU,CAAC;IACnB,KAAK,EAAE,SAAS,GAAG,IAAI,CAAC;IACxB,QAAQ,EAAE,SAAS,CAAC;CACrB,CAAC;AAEF;;;GAGG;AACH,wBAAgB,eAAe,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,oBAAoB,2CAqBhF;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,mBAAmB,CAIvD"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { createContext, useContext } from 'react';
|
|
3
|
+
import { useDevices } from '../hooks/use-devices.js';
|
|
4
|
+
import { usePanelMode } from './panel-mode-context.js';
|
|
5
|
+
const DevicesContext = createContext(null);
|
|
6
|
+
/**
|
|
7
|
+
* Provides Spotify Connect device list and transfer-playback controls.
|
|
8
|
+
* Only fetches the device list while the devices panel is active.
|
|
9
|
+
*/
|
|
10
|
+
export function DevicesProvider({ client, track, children }) {
|
|
11
|
+
const { panelMode } = usePanelMode();
|
|
12
|
+
const isActive = panelMode === 'devices';
|
|
13
|
+
const { devices, isLoading, selectedIndex, error, up, down, select } = useDevices(client, isActive, track?.isPlaying ?? false);
|
|
14
|
+
const value = {
|
|
15
|
+
devices,
|
|
16
|
+
isLoading,
|
|
17
|
+
selectedIndex,
|
|
18
|
+
error,
|
|
19
|
+
devicesUp: isActive ? up : undefined,
|
|
20
|
+
devicesDown: isActive ? down : undefined,
|
|
21
|
+
devicesSelect: isActive ? select : undefined,
|
|
22
|
+
};
|
|
23
|
+
return _jsx(DevicesContext, { value: value, children: children });
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Access the device list and transfer controls.
|
|
27
|
+
*/
|
|
28
|
+
export function useDevicesContext() {
|
|
29
|
+
const ctx = useContext(DevicesContext);
|
|
30
|
+
if (!ctx)
|
|
31
|
+
throw new Error('useDevicesContext must be used within DevicesProvider');
|
|
32
|
+
return ctx;
|
|
33
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"devices-context.js","sourceRoot":"","sources":["../../src/contexts/devices-context.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAGrD,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAYvD,MAAM,cAAc,GAAG,aAAa,CAA6B,IAAI,CAAC,CAAC;AAQvE;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAwB;IAC/E,MAAM,EAAE,SAAS,EAAE,GAAG,YAAY,EAAE,CAAC;IACrC,MAAM,QAAQ,GAAG,SAAS,KAAK,SAAS,CAAC;IAEzC,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,UAAU,CAC/E,MAAM,EACN,QAAQ,EACR,KAAK,EAAE,SAAS,IAAI,KAAK,CAC1B,CAAC;IAEF,MAAM,KAAK,GAAwB;QACjC,OAAO;QACP,SAAS;QACT,aAAa;QACb,KAAK;QACL,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS;QACpC,WAAW,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;QACxC,aAAa,EAAE,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS;KAC7C,CAAC;IAEF,OAAO,KAAC,cAAc,IAAC,KAAK,EAAE,KAAK,YAAG,QAAQ,GAAkB,CAAC;AACnE,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB;IAC/B,MAAM,GAAG,GAAG,UAAU,CAAC,cAAc,CAAC,CAAC;IACvC,IAAI,CAAC,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC;IACnF,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
|
-
export type PanelMode = 'none' | 'lyrics' | 'queue' | 'search';
|
|
2
|
+
export type PanelMode = 'none' | 'lyrics' | 'queue' | 'search' | 'devices';
|
|
3
3
|
type PanelModeContextValue = {
|
|
4
4
|
panelMode: PanelMode;
|
|
5
5
|
hasPanel: boolean;
|
|
@@ -8,6 +8,7 @@ type PanelModeContextValue = {
|
|
|
8
8
|
toggleLyrics: () => void;
|
|
9
9
|
toggleQueue: () => void;
|
|
10
10
|
toggleSearch: () => void;
|
|
11
|
+
toggleDevices: () => void;
|
|
11
12
|
};
|
|
12
13
|
/**
|
|
13
14
|
* Provides shared panel mode state. Only one panel can be active at a time.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"panel-mode-context.d.ts","sourceRoot":"","sources":["../../src/contexts/panel-mode-context.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvC,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,GAAG,SAAS,CAAC;AAE3E,KAAK,qBAAqB,GAAG;IAC3B,SAAS,EAAE,SAAS,CAAC;IACrB,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,OAAO,CAAC;IACrB,YAAY,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IACnC,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,WAAW,EAAE,MAAM,IAAI,CAAC;IACxB,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,aAAa,EAAE,MAAM,IAAI,CAAC;CAC3B,CAAC;AAIF;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,EAAE,SAAS,CAAA;CAAE,2CA4CtE;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,qBAAqB,CAIpD"}
|
|
@@ -31,6 +31,9 @@ export function PanelModeProvider({ children }) {
|
|
|
31
31
|
toggleSearch: useCallback(() => toggle('search'), [
|
|
32
32
|
toggle,
|
|
33
33
|
]),
|
|
34
|
+
toggleDevices: useCallback(() => toggle('devices'), [
|
|
35
|
+
toggle,
|
|
36
|
+
]),
|
|
34
37
|
};
|
|
35
38
|
return _jsx(PanelModeContext, { value: value, children: children });
|
|
36
39
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"panel-mode-context.js","sourceRoot":"","sources":["../../src/contexts/panel-mode-context.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAezE,MAAM,gBAAgB,GAAG,aAAa,CAA+B,IAAI,CAAC,CAAC;AAE3E;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,EAAE,QAAQ,EAA2B;IACrE,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAY,MAAM,CAAC,CAAC;IAC9D,MAAM,CAAC,WAAW,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAEpD,MAAM,MAAM,GAAG,WAAW,CAAC,CAAC,IAAe,EAAE,EAAE;QAC7C,YAAY,CAAC,CAAC,CAAC,EAAE,EAAE;YACjB,MAAM,IAAI,GAAG,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;YACxC,IAAI,IAAI,KAAK,QAAQ;gBAAE,YAAY,CAAC,KAAK,CAAC,CAAC;YAC3C,OAAO,IAAI,CAAC;QACd,CAAC,CAAC,CAAC;IACL,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,KAAK,GAA0B;QACnC,SAAS;QACT,QAAQ,EAAE,SAAS,KAAK,MAAM;QAC9B,WAAW;QACX,YAAY;QACZ,YAAY,EAAE,WAAW,CACvB,GAAG,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,EACtB;YACE,MAAM;SACP,CACF;QACD,WAAW,EAAE,WAAW,CACtB,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,EACrB;YACE,MAAM;SACP,CACF;QACD,YAAY,EAAE,WAAW,CACvB,GAAG,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,EACtB;YACE,MAAM;SACP,CACF;QACD,aAAa,EAAE,WAAW,CACxB,GAAG,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,EACvB;YACE,MAAM;SACP,CACF;KACF,CAAC;IAEF,OAAO,KAAC,gBAAgB,IAAC,KAAK,EAAE,KAAK,YAAG,QAAQ,GAAoB,CAAC;AACvE,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY;IAC1B,MAAM,GAAG,GAAG,UAAU,CAAC,gBAAgB,CAAC,CAAC;IACzC,IAAI,CAAC,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;IAChF,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-album-art.d.ts","sourceRoot":"","sources":["../../src/hooks/use-album-art.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"use-album-art.d.ts","sourceRoot":"","sources":["../../src/hooks/use-album-art.ts"],"names":[],"mappings":"AAIA;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,iBAyDlE"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { useEffect, useRef, useState } from 'react';
|
|
2
2
|
import terminalImage from 'terminal-image';
|
|
3
|
+
import { logger } from '../logger.js';
|
|
3
4
|
/**
|
|
4
5
|
* Fetches an album art image and converts it to a terminal-renderable ANSI string.
|
|
5
6
|
* Caches by URL to avoid re-fetching on every render cycle.
|
|
@@ -39,7 +40,7 @@ export function useAlbumArt(imageUrl, height) {
|
|
|
39
40
|
}
|
|
40
41
|
}
|
|
41
42
|
catch (err) {
|
|
42
|
-
|
|
43
|
+
logger.error(`Failed to render album art for ${imageUrl}:`, err);
|
|
43
44
|
if (!cancelled) {
|
|
44
45
|
setArt(null);
|
|
45
46
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-album-art.js","sourceRoot":"","sources":["../../src/hooks/use-album-art.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACpD,OAAO,aAAa,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"use-album-art.js","sourceRoot":"","sources":["../../src/hooks/use-album-art.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACpD,OAAO,aAAa,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CAAC,QAAuB,EAAE,MAAc;IACjE,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;IACpD,MAAM,QAAQ,GAAG,MAAM,CAIb,IAAI,CAAC,CAAC;IAEhB,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,MAAM,CAAC,IAAI,CAAC,CAAC;YACb,OAAO;QACT,CAAC;QAED,IAAI,QAAQ,CAAC,OAAO,EAAE,GAAG,KAAK,QAAQ,IAAI,QAAQ,CAAC,OAAO,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;YAC7E,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YAC7B,OAAO;QACT,CAAC;QAED,IAAI,SAAS,GAAG,KAAK,CAAC;QAEtB,KAAK,UAAU,IAAI;YACjB,IAAI,CAAC;gBACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,QAAS,CAAC,CAAC;gBACxC,MAAM,WAAW,GAAG,MAAM,QAAQ,CAAC,WAAW,EAAE,CAAC;gBACjD,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,MAAM,CAAC,IAAI,UAAU,CAAC,WAAW,CAAC,EAAE;oBACvE,MAAM;oBACN,mBAAmB,EAAE,IAAI;oBACzB,kBAAkB,EAAE,KAAK;iBAC1B,CAAC,CAAC;gBAEH,IAAI,CAAC,SAAS,EAAE,CAAC;oBACf,QAAQ,CAAC,OAAO,GAAG;wBACjB,GAAG,EAAE,QAAS;wBACd,MAAM;wBACN,GAAG,EAAE,QAAQ;qBACd,CAAC;oBACF,MAAM,CAAC,QAAQ,CAAC,CAAC;gBACnB,CAAC;YACH,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,CAAC,KAAK,CAAC,kCAAkC,QAAQ,GAAG,EAAE,GAAG,CAAC,CAAC;gBACjE,IAAI,CAAC,SAAS,EAAE,CAAC;oBACf,MAAM,CAAC,IAAI,CAAC,CAAC;gBACf,CAAC;YACH,CAAC;QACH,CAAC;QAED,IAAI,EAAE,CAAC;QACP,OAAO,GAAG,EAAE;YACV,SAAS,GAAG,IAAI,CAAC;QACnB,CAAC,CAAC;IACJ,CAAC,EAAE;QACD,QAAQ;QACR,MAAM;KACP,CAAC,CAAC;IAEH,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-browse.d.ts","sourceRoot":"","sources":["../../src/hooks/use-browse.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"use-browse.d.ts","sourceRoot":"","sources":["../../src/hooks/use-browse.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAG1D,OAAO,KAAK,EAA+B,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAG9F,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,OAAO,GAAG,UAAU,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,KAAK,CAAC;QACZ,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;QACf,GAAG,EAAE,MAAM,CAAC;QACZ,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC,CAAC;CACJ,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,UAAU;;;;;yBAQxB,MAAM;+BA2BH,MAAM;;;EAyD5B"}
|
package/dist/hooks/use-browse.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { useCallback, useRef, useState } from 'react';
|
|
2
|
+
import { logger } from '../logger.js';
|
|
2
3
|
import { fetchAlbumTracks, fetchPlaylistTracks, fetchUserPlaylists } from '../spotify/search.js';
|
|
3
4
|
/**
|
|
4
5
|
* Manages drill-down browse state for albums, playlists, and user playlist library.
|
|
@@ -27,7 +28,7 @@ export function useBrowse(client) {
|
|
|
27
28
|
});
|
|
28
29
|
}
|
|
29
30
|
catch (err) {
|
|
30
|
-
|
|
31
|
+
logger.error(`Failed to load album ${albumId}:`, err);
|
|
31
32
|
if (cancelRef.current !== token)
|
|
32
33
|
return;
|
|
33
34
|
setData(null);
|
|
@@ -55,7 +56,7 @@ export function useBrowse(client) {
|
|
|
55
56
|
});
|
|
56
57
|
}
|
|
57
58
|
catch (err) {
|
|
58
|
-
|
|
59
|
+
logger.error(`Failed to load playlist ${playlistId}:`, err);
|
|
59
60
|
if (cancelRef.current !== token)
|
|
60
61
|
return;
|
|
61
62
|
setData(null);
|
|
@@ -74,7 +75,7 @@ export function useBrowse(client) {
|
|
|
74
75
|
setUserPlaylists(result.items);
|
|
75
76
|
}
|
|
76
77
|
catch (err) {
|
|
77
|
-
|
|
78
|
+
logger.error('Failed to load user playlists:', err);
|
|
78
79
|
setUserPlaylists(null);
|
|
79
80
|
}
|
|
80
81
|
finally {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-browse.js","sourceRoot":"","sources":["../../src/hooks/use-browse.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"use-browse.js","sourceRoot":"","sources":["../../src/hooks/use-browse.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { SpotifyApi } from '@spotify/web-api-ts-sdk';
|
|
2
|
+
import type { SpotifyDevice } from '../spotify/devices.js';
|
|
3
|
+
/**
|
|
4
|
+
* Fetches and manages the list of Spotify Connect devices while the device
|
|
5
|
+
* picker panel is open. Only fetches when `enabled` is true. Exposes a
|
|
6
|
+
* `select` action that transfers playback to the currently highlighted
|
|
7
|
+
* device using the "mirror current playing state" policy supplied by the
|
|
8
|
+
* caller.
|
|
9
|
+
* @param client - Authenticated Spotify API client
|
|
10
|
+
* @param enabled - Whether the picker is active (gates the initial fetch)
|
|
11
|
+
* @param shouldResume - Current playing state used to decide whether the
|
|
12
|
+
* transferred session should resume on the new device
|
|
13
|
+
* @returns Device list, loading state, and navigation / selection controls
|
|
14
|
+
*/
|
|
15
|
+
export declare function useDevices(client: SpotifyApi, enabled: boolean, shouldResume: boolean): {
|
|
16
|
+
devices: SpotifyDevice[];
|
|
17
|
+
isLoading: boolean;
|
|
18
|
+
selectedIndex: number;
|
|
19
|
+
error: string | null;
|
|
20
|
+
up: () => void;
|
|
21
|
+
down: () => void;
|
|
22
|
+
select: () => Promise<void>;
|
|
23
|
+
refresh: () => Promise<void>;
|
|
24
|
+
};
|