11import { audio } from '../api/audio.js' ;
22import { lastfm } from '../api/lastfm.js' ;
3+ import { plex } from '../api/plex.js' ;
34import { settings } from '../api/settings.js' ;
45import { tauriConfirm , tauriInvoke } from '../api/shared.js' ;
56import { modLabel , SHORTCUT_DEFINITIONS } from '../shortcuts.js' ;
@@ -22,6 +23,7 @@ export function createSettingsView(Alpine) {
2223 { id : 'sorting' , label : 'Sorting' } ,
2324 { id : 'advanced' , label : 'Advanced' } ,
2425 { id : 'lastfm' , label : 'Last.fm' } ,
26+ { id : 'plex' , label : 'Plex' } ,
2527 { id : 'stats' , label : 'Statistics' } ,
2628 ] ,
2729
@@ -45,6 +47,19 @@ export function createSettingsView(Alpine) {
4547 isResettingLoved : false ,
4648 } ,
4749
50+ plex : {
51+ url : '' ,
52+ token : '' ,
53+ serverName : null ,
54+ machineId : null ,
55+ version : null ,
56+ libraries : [ ] ,
57+ selectedLibraries : [ ] ,
58+ isConnecting : false ,
59+ isDiscovering : false ,
60+ connected : false ,
61+ } ,
62+
4863 reconcileScan : {
4964 isRunning : false ,
5065 lastResult : null ,
@@ -220,6 +235,7 @@ export function createSettingsView(Alpine) {
220235 } ) ;
221236 await this . loadWatchedFolders ( ) ;
222237 await this . loadLastfmSettings ( ) ;
238+ await this . loadPlexSettings ( ) ;
223239 await this . loadNetworkCacheStatus ( ) ;
224240 this . loadColumnSettings ( ) ;
225241 this . deduplicateAcrossDirectories = window . settings . get (
@@ -856,6 +872,114 @@ export function createSettingsView(Alpine) {
856872 }
857873 } ,
858874
875+ // ============================================
876+ // Plex methods
877+ // ============================================
878+
879+ plexStatusColor ( ) {
880+ return this . plex . connected ? 'bg-green-500' : 'bg-red-500' ;
881+ } ,
882+
883+ plexStatusText ( ) {
884+ if ( this . plex . connected ) {
885+ return this . plex . serverName ? `Connected to ${ this . plex . serverName } ` : 'Connected' ;
886+ }
887+ return 'Not Connected' ;
888+ } ,
889+
890+ async loadPlexSettings ( ) {
891+ if ( ! window . __TAURI__ ) return ;
892+
893+ try {
894+ const config = await plex . getConfig ( ) ;
895+ if ( config ?. status === 'configured' ) {
896+ this . plex . url = config . url ;
897+ this . plex . token = config . token ;
898+ this . plex . selectedLibraries = config . libraries ?? [ ] ;
899+ this . plex . connected = true ;
900+ }
901+ } catch ( error ) {
902+ console . error ( '[settings] Failed to load Plex settings:' , error ) ;
903+ }
904+ } ,
905+
906+ async connectPlex ( ) {
907+ if ( ! this . plex . url || ! this . plex . token ) {
908+ Alpine . store ( 'ui' ) . toast ( 'Server URL and token are required' , 'warning' ) ;
909+ return ;
910+ }
911+
912+ this . plex . isConnecting = true ;
913+ try {
914+ const info = await plex . ping ( this . plex . url , this . plex . token ) ;
915+ this . plex . serverName = info . server_name ;
916+ this . plex . machineId = info . machine_id ;
917+ this . plex . version = info . version ;
918+
919+ await plex . setConfig ( this . plex . url , this . plex . token , this . plex . selectedLibraries ) ;
920+ this . plex . connected = true ;
921+ Alpine . store ( 'settings' ) . plex_configured = true ;
922+ Alpine . store ( 'ui' ) . toast ( `Connected to ${ info . server_name } ` , 'success' ) ;
923+ } catch ( error ) {
924+ console . error ( '[settings] Failed to connect to Plex:' , error ) ;
925+ Alpine . store ( 'ui' ) . toast ( `Failed to connect: ${ error } ` , 'error' ) ;
926+ } finally {
927+ this . plex . isConnecting = false ;
928+ }
929+ } ,
930+
931+ async disconnectPlex ( ) {
932+ try {
933+ await plex . clearConfig ( ) ;
934+ this . plex . url = '' ;
935+ this . plex . token = '' ;
936+ this . plex . serverName = null ;
937+ this . plex . machineId = null ;
938+ this . plex . version = null ;
939+ this . plex . libraries = [ ] ;
940+ this . plex . selectedLibraries = [ ] ;
941+ this . plex . connected = false ;
942+ Alpine . store ( 'settings' ) . plex_configured = false ;
943+ Alpine . store ( 'ui' ) . toast ( 'Disconnected from Plex' , 'success' ) ;
944+ } catch ( error ) {
945+ console . error ( '[settings] Failed to disconnect from Plex:' , error ) ;
946+ Alpine . store ( 'ui' ) . toast ( 'Failed to disconnect from Plex' , 'error' ) ;
947+ }
948+ } ,
949+
950+ async discoverPlexLibraries ( ) {
951+ if ( ! this . plex . url || ! this . plex . token ) {
952+ Alpine . store ( 'ui' ) . toast ( 'Server URL and token are required' , 'warning' ) ;
953+ return ;
954+ }
955+
956+ this . plex . isDiscovering = true ;
957+ try {
958+ this . plex . libraries = await plex . listLibraries ( this . plex . url , this . plex . token ) ;
959+ if ( this . plex . libraries . length === 0 ) {
960+ Alpine . store ( 'ui' ) . toast ( 'No music libraries found on this server' , 'info' ) ;
961+ }
962+ } catch ( error ) {
963+ console . error ( '[settings] Failed to discover Plex libraries:' , error ) ;
964+ Alpine . store ( 'ui' ) . toast ( `Failed to discover libraries: ${ error } ` , 'error' ) ;
965+ } finally {
966+ this . plex . isDiscovering = false ;
967+ }
968+ } ,
969+
970+ plexLibrarySelected ( key ) {
971+ return this . plex . selectedLibraries . includes ( key ) ;
972+ } ,
973+
974+ togglePlexLibrary ( key ) {
975+ const idx = this . plex . selectedLibraries . indexOf ( key ) ;
976+ if ( idx === - 1 ) {
977+ this . plex . selectedLibraries = [ ...this . plex . selectedLibraries , key ] ;
978+ } else {
979+ this . plex . selectedLibraries = this . plex . selectedLibraries . filter ( ( k ) => k !== key ) ;
980+ }
981+ } ,
982+
859983 // ============================================
860984 // Column Settings methods
861985 // ============================================
0 commit comments