2024-10-23 03:01:23 +02:00
import React , { ChangeEventHandler , KeyboardEventHandler , MouseEventHandler , useEffect , useState } from 'react' ;
2024-10-23 02:50:26 +02:00
import IFrontendSettings from "./interfaces/IFrontendSettings" ;
2024-10-20 17:54:38 +02:00
import '../styles/settings.css' ;
2024-10-20 20:12:27 +02:00
import IBackendSettings from "./interfaces/IBackendSettings" ;
2024-10-23 02:50:26 +02:00
import { getData , postData } from "../App" ;
2024-10-23 02:28:36 +02:00
import LibraryConnector , { Kavita , Komga } from "./LibraryConnector" ;
import NotificationConnector , { Gotify , Lunasea , Ntfy } from "./NotificationConnector" ;
2024-10-20 20:12:27 +02:00
import ILibraryConnector from "./interfaces/ILibraryConnector" ;
import INotificationConnector from "./interfaces/INotificationConnector" ;
2024-10-23 03:01:23 +02:00
import Toggle from 'react-toggle' ;
import '../styles/react-toggle.css' ;
2024-10-20 17:54:38 +02:00
2024-10-20 20:12:27 +02:00
export default function Settings ( { backendConnected , apiUri , settings , changeSettings } : { backendConnected : boolean , apiUri : string , settings : IFrontendSettings , changeSettings : ( settings : IFrontendSettings ) = > void } ) {
2024-10-22 18:12:24 +02:00
const [ frontendSettings , setFrontendSettings ] = useState < IFrontendSettings > ( settings ) ;
2024-10-20 20:12:27 +02:00
const [ backendSettings , setBackendSettings ] = useState < IBackendSettings > ( ) ;
2024-10-20 17:54:38 +02:00
const [ showSettings , setShowSettings ] = useState < boolean > ( false ) ;
2024-10-23 02:28:36 +02:00
const [ libraryConnectors , setLibraryConnectors ] = useState < ILibraryConnector [ ] > ( ) ;
const [ notificationConnectors , setNotificationConnectors ] = useState < INotificationConnector [ ] > ( ) ;
const [ komgaSettings , setKomgaSettings ] = useState < { url : string , username : string , password : string } > ( { url : "" , username : "" , password : "" } ) ;
const [ kavitaSettings , setKavitaSettings ] = useState < { url : string , username : string , password : string } > ( { url : "" , username : "" , password : "" } ) ;
const [ gotifySettings , setGotifySettings ] = useState < { url : string , appToken : string } > ( { url : "" , appToken : "" } ) ;
const [ lunaseaSettings , setLunaseaSettings ] = useState < { webhook : string } > ( { webhook : "" } ) ;
const [ ntfySettings , setNtfySettings ] = useState < { url : string , username : string , password : string , topic : string | undefined } > ( { url : "" , username : "" , password : "" , topic : undefined } ) ;
2024-10-20 20:12:27 +02:00
useEffect ( ( ) = > {
2024-10-23 02:28:36 +02:00
console . debug ( ` ${ showSettings ? "Showing" : "Not showing" } settings. ` ) ;
2024-10-20 20:12:27 +02:00
if ( ! showSettings || ! backendConnected )
return ;
2024-10-23 02:50:26 +02:00
UpdateBackendSettings ( ) ;
2024-10-23 02:28:36 +02:00
LibraryConnector . GetLibraryConnectors ( apiUri ) . then ( setLibraryConnectors ) . catch ( console . error ) ;
NotificationConnector . GetNotificationConnectors ( apiUri ) . then ( setNotificationConnectors ) . catch ( console . error ) ;
2024-10-20 20:12:27 +02:00
} , [ showSettings ] ) ;
2024-10-22 18:12:24 +02:00
useEffect ( ( ) = > {
changeSettings ( frontendSettings ) ;
} , [ frontendSettings ] ) ;
2024-10-20 20:12:27 +02:00
async function GetSettings ( apiUri : string ) : Promise < IBackendSettings > {
2024-10-20 20:16:32 +02:00
//console.info("Getting Settings");
2024-10-20 20:12:27 +02:00
return getData ( ` ${ apiUri } /v2/Settings ` )
. then ( ( json ) = > {
2024-10-20 20:16:32 +02:00
//console.info("Got Settings");
2024-10-20 20:12:27 +02:00
const ret = json as IBackendSettings ;
//console.debug(ret);
return ( ret ) ;
} )
. catch ( Promise . reject ) ;
}
2024-10-23 02:50:26 +02:00
function UpdateBackendSettings() {
GetSettings ( apiUri ) . then ( setBackendSettings ) . catch ( console . error ) ;
}
2024-10-23 02:28:36 +02:00
const GetKomga = ( ) : ILibraryConnector | undefined = >
libraryConnectors ? . find ( con = > con . libraryType == 0 ) ;
2024-10-20 20:12:27 +02:00
2024-10-23 02:28:36 +02:00
const KomgaConnected = ( ) : boolean = > GetKomga ( ) != undefined ;
2024-10-20 20:12:27 +02:00
2024-10-23 02:28:36 +02:00
const GetKavita = ( ) : ILibraryConnector | undefined = >
libraryConnectors ? . find ( con = > con . libraryType == 1 ) ;
2024-10-20 20:12:27 +02:00
2024-10-23 02:28:36 +02:00
const KavitaConnected = ( ) : boolean = > GetKavita ( ) != undefined ;
2024-10-20 20:12:27 +02:00
2024-10-23 02:28:36 +02:00
const GetGotify = ( ) : INotificationConnector | undefined = >
notificationConnectors ? . find ( con = > con . notificationConnectorType == 0 ) ;
2024-10-20 20:12:27 +02:00
2024-10-23 02:28:36 +02:00
const GotifyConnected = ( ) : boolean = > GetGotify ( ) != undefined ;
2024-10-20 20:12:27 +02:00
2024-10-23 02:28:36 +02:00
const GetLunasea = ( ) : INotificationConnector | undefined = >
notificationConnectors ? . find ( con = > con . notificationConnectorType == 1 ) ;
const LunaseaConnected = ( ) : boolean = > GetLunasea ( ) != undefined ;
const GetNtfy = ( ) : INotificationConnector | undefined = >
notificationConnectors ? . find ( con = > con . notificationConnectorType == 2 ) ;
const NtfyConnected = ( ) : boolean = > GetNtfy ( ) != undefined ;
2024-10-20 20:12:27 +02:00
const SubmitApiUri : KeyboardEventHandler < HTMLInputElement > = ( e ) = > {
2024-10-22 18:12:24 +02:00
if ( e . currentTarget . value . length < 1 )
return ;
if ( e . key == "Enter" ) {
2024-10-23 02:50:26 +02:00
setFrontendSettings ( { . . . frontendSettings , apiUri : e.currentTarget.value } ) ;
2024-10-23 02:28:36 +02:00
RefreshInputs ( ) ;
2024-10-22 18:12:24 +02:00
}
}
2024-10-23 02:50:26 +02:00
const SubmitUserAgent : KeyboardEventHandler < HTMLInputElement > = ( e ) = > {
if ( e . currentTarget . value . length < 1 || backendSettings === undefined )
return ;
if ( e . key == "Enter" ) {
//console.info(`Updating Useragent ${e.currentTarget.value}`);
postData ( ` ${ apiUri } /v2/Settings/UserAgent ` , { value : e.currentTarget.value } )
. then ( ( json ) = > {
//console.info(`Successfully updated Useragent ${e.currentTarget.value}`);
UpdateBackendSettings ( ) ;
RefreshInputs ( ) ;
} )
. catch ( ( ) = > alert ( "Failed to update Useragent." ) ) ;
}
}
2024-10-23 03:01:23 +02:00
2024-10-23 02:50:26 +02:00
const ResetUserAgent : MouseEventHandler < HTMLSpanElement > = ( ) = > {
2024-10-23 03:01:23 +02:00
//console.info(`Resetting Useragent`);
2024-10-23 02:50:26 +02:00
postData ( ` ${ apiUri } /v2/Settings/UserAgent ` , { value : undefined } )
. then ( ( json ) = > {
2024-10-23 03:01:23 +02:00
//console.info(`Successfully reset Useragent`);
2024-10-23 02:50:26 +02:00
UpdateBackendSettings ( ) ;
RefreshInputs ( ) ;
} )
. catch ( ( ) = > alert ( "Failed to update Useragent." ) ) ;
}
2024-10-23 03:01:23 +02:00
const SetAprilFoolsMode : ChangeEventHandler < HTMLInputElement > = ( e ) = > {
2024-10-27 02:32:05 +01:00
//console.info(`Updating AprilFoolsMode ${e.target.checked}`);
postData ( ` ${ apiUri } /v2/Settings/AprilFoolsMode ` , { value : e.target.checked } )
2024-10-23 03:01:23 +02:00
. then ( ( json ) = > {
//console.info(`Successfully updated AprilFoolsMode ${e.currentTarget.value}`);
UpdateBackendSettings ( ) ;
} )
}
2024-10-23 02:28:36 +02:00
function RefreshInputs ( ) {
alert ( "Saved." ) ;
2024-10-22 18:12:24 +02:00
setShowSettings ( false ) ;
2024-10-20 20:12:27 +02:00
}
2024-10-20 17:54:38 +02:00
return (
< div id = "Settings" >
< img id = "SettingsIcon" src = "../media/settings-cogwheel.svg" alt = "cogwheel" onClick = { ( ) = > setShowSettings ( true ) } / >
{ showSettings
? < div className = "popup" >
< div className = "popupHeader" >
< h1 > Settings < / h1 >
< img alt = "Close Settings" className = "close" src = "../media/close-x.svg" onClick = { ( ) = > setShowSettings ( false ) } / >
< / div >
< div id = "settingsPopupBody" className = "popupBody" >
< div className = "settings-section" >
TRANGA
< div className = "settings-section-content" >
< div className = "section-item" >
< span className = "settings-section-title" > API Settings < / span >
< label htmlFor = "settingApiUri" > API URI : < / label >
2024-10-20 20:12:27 +02:00
< input placeholder = { frontendSettings . apiUri } type = "text" id = "settingApiUri" onKeyDown = { SubmitApiUri } / >
2024-10-20 17:54:38 +02:00
< label htmlFor = "userAgent" > User Agent : < / label >
2024-10-23 02:50:26 +02:00
< input id = "userAgent" type = "text" placeholder = { backendSettings != undefined ? backendSettings . userAgent : "UserAgent" } onKeyDown = { SubmitUserAgent } / >
< span id = "resetUserAgent" onClick = { ResetUserAgent } > Reset < / span >
2024-10-23 03:01:23 +02:00
< label htmlFor = "aprilFoolsMode" > April Fools Mode < / label >
< Toggle id = "aprilFoolsMode"
defaultChecked = { backendSettings ? . aprilFoolsMode ? ? false }
onChange = { SetAprilFoolsMode } / >
2024-10-20 17:54:38 +02:00
< / div >
< div className = "section-item" >
< span className = "settings-section-title" > Rate Limits < / span >
< label htmlFor = "DefaultRL" > Default : < / label >
2024-10-20 20:12:27 +02:00
< input id = "defaultRL" type = "text" placeholder = { backendSettings != undefined ? backendSettings . requestLimits . Default . toString ( ) : "-1" } / >
2024-10-20 17:54:38 +02:00
< label htmlFor = "CoverRL" > Manga Covers : < / label >
2024-10-20 20:12:27 +02:00
< input id = "coverRL" type = "text" placeholder = { backendSettings != undefined ? backendSettings . requestLimits . MangaCover . toString ( ) : "-1" } / >
2024-10-20 17:54:38 +02:00
< label htmlFor = "ImageRL" > Manga Images : < / label >
2024-10-20 20:12:27 +02:00
< input id = "imageRL" type = "text" placeholder = { backendSettings != undefined ? backendSettings . requestLimits . MangaImage . toString ( ) : "-1" } / >
2024-10-20 17:54:38 +02:00
< label htmlFor = "InfoRL" > Manga Info : < / label >
2024-10-20 20:12:27 +02:00
< input id = "infoRL" type = "text" placeholder = { backendSettings != undefined ? backendSettings . requestLimits . MangaInfo . toString ( ) : "-1" } / >
2024-10-20 17:54:38 +02:00
< / div >
< div className = "section-item" >
< span className = "settings-section-title" > Appearance < / span >
< label htmlFor = "cssStyle" > Library Style : < / label >
< select id = "cssStyle" >
< option id = "card_compact" value = "card_compact" > Cards ( Compact ) < / option >
< option id = "card_hover" value = "card_hover" > Cards ( Hover ) < / option >
< / select >
< / div >
< / div >
< / div >
< div className = "settings-section" >
< span className = "settings-section-title" > Sources < / span >
< div className = "settings-section-content" >
< div className = "section-item" >
< span className = "settings-section-title" >
< img src = "../media/connector-icons/mangadex-logo.svg" alt = "Mangadex Logo" / >
< a href = "https://mangadex.org" > MangaDex < / a >
< / span >
< label htmlFor = "mDexFeedRL" > Feed Rate Limit : < / label >
2024-10-20 20:12:27 +02:00
< input id = "mDexFeedRL" type = "text" placeholder = { backendSettings != undefined ? backendSettings . requestLimits . MangaDexFeed . toString ( ) : "-1" } / >
2024-10-20 17:54:38 +02:00
< label htmlFor = "mDexImageRL" > Image Rate Limit : < / label >
2024-10-20 20:12:27 +02:00
< input id = "mDexImageRL" type = "number" placeholder = { backendSettings != undefined ? backendSettings . requestLimits . MangaDexImage . toString ( ) : "-1" } / >
2024-10-20 17:54:38 +02:00
< / div >
< / div >
< / div >
2024-10-22 18:32:20 +02:00
< div className = "settings-section" >
2024-10-20 17:54:38 +02:00
LIBRARY CONNECTORS
< div className = "settings-section-content" >
2024-10-23 02:28:36 +02:00
< div className = "section-item" connector - status = { KomgaConnected ( ) ? "Configured" : "Not Configured" } >
2024-10-20 17:54:38 +02:00
< span className = "settings-section-title" >
2024-10-22 18:32:20 +02:00
< img src = '../media/connector-icons/komga.svg' alt = "Komga Logo" / >
2024-10-20 17:54:38 +02:00
Komga
< / span >
2024-10-22 18:32:20 +02:00
< label htmlFor = "komgaUrl" > URL < / label >
2024-10-23 02:28:36 +02:00
< input placeholder = { GetKomga ( ) ? . baseUrl ? ? "URL" } id = "komgaUrl" type = "text" onChange = { ( e ) = > setKomgaSettings ( s = > ( { . . . s , url : e.target.value } ) ) } / >
2024-10-22 18:32:20 +02:00
< label htmlFor = "komgaUsername" > Username < / label >
2024-10-23 02:28:36 +02:00
< input placeholder = { KomgaConnected ( ) ? "***" : "Username" } id = "komgaUsername" type = "text" onChange = { ( e ) = > setKomgaSettings ( s = > ( { . . . s , username : e.target.value } ) ) } / >
2024-10-22 18:32:20 +02:00
< label htmlFor = "komgaPassword" > Password < / label >
2024-10-23 02:28:36 +02:00
< input placeholder = { KomgaConnected ( ) ? "***" : "Password" } id = "komgaPassword" type = "password" onChange = { ( e ) = > setKomgaSettings ( s = > ( { . . . s , password : e.target.value } ) ) } / >
2024-10-22 18:32:20 +02:00
< div className = "section-actions" >
2024-10-23 02:28:36 +02:00
< span onClick = { ( ) = > new Komga ( komgaSettings ) . Test ( apiUri ) . then ( ( ) = > alert ( "Test successful" ) ) } > Test < / span >
< span onClick = { ( ) = > new Komga ( komgaSettings ) . Reset ( apiUri ) . then ( RefreshInputs ) } > Reset < / span >
< span onClick = { ( ) = > new Komga ( komgaSettings ) . Create ( apiUri ) . then ( RefreshInputs ) } > Apply < / span >
2024-10-20 17:54:38 +02:00
< / div >
< / div >
2024-10-23 02:28:36 +02:00
< div className = "section-item" connector - status = { KavitaConnected ( ) ? "Configured" : "Not Configured" } >
2024-10-20 17:54:38 +02:00
< span className = "settings-section-title" >
2024-10-22 18:32:20 +02:00
< img src = '../media/connector-icons/kavita.png' alt = "Kavita Logo" / >
2024-10-20 17:54:38 +02:00
Kavita
< / span >
2024-10-22 18:32:20 +02:00
< label htmlFor = "kavitaUrl" > URL < / label >
2024-10-23 02:28:36 +02:00
< input placeholder = { GetKavita ( ) ? . baseUrl ? ? "URL" } id = "kavitaUrl" type = "text" onChange = { ( e ) = > setKavitaSettings ( s = > ( { . . . s , url : e.target.value } ) ) } / >
2024-10-22 18:32:20 +02:00
< label htmlFor = "kavitaUsername" > Username < / label >
2024-10-23 02:28:36 +02:00
< input placeholder = { KavitaConnected ( ) ? "***" : "Username" } id = "kavitaUsername" type = "text" onChange = { ( e ) = > setKavitaSettings ( s = > ( { . . . s , username : e.target.value } ) ) } / >
2024-10-22 18:32:20 +02:00
< label htmlFor = "kavitaPassword" > Password < / label >
2024-10-23 02:28:36 +02:00
< input placeholder = { KavitaConnected ( ) ? "***" : "Password" } id = "kavitaPassword" type = "password" onChange = { ( e ) = > setKavitaSettings ( s = > ( { . . . s , password : e.target.value } ) ) } / >
2024-10-22 18:32:20 +02:00
< div className = "section-actions" >
2024-10-23 02:28:36 +02:00
< span onClick = { ( ) = > new Kavita ( kavitaSettings ) . Test ( apiUri ) . then ( ( ) = > alert ( "Test successful" ) ) } > Test < / span >
< span onClick = { ( ) = > new Kavita ( kavitaSettings ) . Reset ( apiUri ) . then ( RefreshInputs ) } > Reset < / span >
< span onClick = { ( ) = > new Kavita ( kavitaSettings ) . Create ( apiUri ) . then ( RefreshInputs ) } > Apply < / span >
2024-10-20 17:54:38 +02:00
< / div >
< / div >
< / div >
< / div >
< div className = "settings-section" >
NOTIFICATION CONNECTORS
< div className = "settings-section-content" >
2024-10-23 02:28:36 +02:00
< div className = "section-item" connector - status = { GotifyConnected ( ) ? "Configured" : "Not Configured" } >
2024-10-20 17:54:38 +02:00
< span className = "settings-section-title" >
2024-10-22 18:32:20 +02:00
< img src = '../media/connector-icons/gotify-logo.png' alt = "Gotify Logo" / >
2024-10-20 17:54:38 +02:00
Gotify
< / span >
2024-10-22 18:32:20 +02:00
< label htmlFor = "gotifyUrl" > URL < / label >
2024-10-23 02:28:36 +02:00
< input placeholder = { GetGotify ( ) ? . endpoint ? ? "URL" } id = "gotifyUrl" type = "text" onChange = { ( e ) = > setGotifySettings ( s = > ( { . . . s , url : e.target.value } ) ) } / >
2024-10-22 18:32:20 +02:00
< label htmlFor = "gotifyAppToken" > AppToken < / label >
2024-10-23 02:28:36 +02:00
< input placeholder = { GotifyConnected ( ) ? "***" : "AppToken" } id = "gotifyAppToken" type = "text" onChange = { ( e ) = > setGotifySettings ( s = > ( { . . . s , appToken : e.target.value } ) ) } / >
2024-10-22 18:32:20 +02:00
< div className = "section-actions" >
2024-10-23 02:28:36 +02:00
< span onClick = { ( ) = > new Gotify ( gotifySettings ) . Test ( apiUri ) . then ( ( ) = > alert ( "Test successful" ) ) } > Test < / span >
< span onClick = { ( ) = > new Gotify ( gotifySettings ) . Reset ( apiUri ) . then ( RefreshInputs ) } > Reset < / span >
< span onClick = { ( ) = > new Gotify ( gotifySettings ) . Create ( apiUri ) . then ( RefreshInputs ) } > Apply < / span >
2024-10-20 17:54:38 +02:00
< / div >
2024-10-23 02:28:36 +02:00
< / div >
< div className = "section-item"
connector - status = { LunaseaConnected ( ) ? "Configured" : "Not Configured" } >
2024-10-20 17:54:38 +02:00
< span className = "settings-section-title" >
2024-10-22 18:32:20 +02:00
< img src = '../media/connector-icons/lunasea.png' alt = "Lunasea Logo" / >
2024-10-20 17:54:38 +02:00
LunaSea
< / span >
2024-10-22 18:32:20 +02:00
< label htmlFor = "lunaseaWebhook" > Webhook id < / label >
2024-10-23 02:28:36 +02:00
< input placeholder = { GetLunasea ( ) != undefined ? "***" : "device/:id or user/:id" } id = "lunaseaWebhook" type = "text" onChange = { ( e ) = > setLunaseaSettings ( s = > ( { . . . s , webhook : e.target.value } ) ) } / >
2024-10-22 18:32:20 +02:00
< div className = "section-actions" >
2024-10-23 02:28:36 +02:00
< span onClick = { ( ) = > new Lunasea ( lunaseaSettings ) . Test ( apiUri ) . then ( ( ) = > alert ( "Test successful" ) ) } > Test < / span >
< span onClick = { ( ) = > new Lunasea ( lunaseaSettings ) . Reset ( apiUri ) . then ( RefreshInputs ) } > Reset < / span >
< span onClick = { ( ) = > new Lunasea ( lunaseaSettings ) . Create ( apiUri ) . then ( RefreshInputs ) } > Apply < / span >
2024-10-20 17:54:38 +02:00
< / div >
< / div >
2024-10-23 02:28:36 +02:00
< div className = "section-item"
connector - status = { NtfyConnected ( ) ? "Configured" : "Not Configured" } >
2024-10-20 17:54:38 +02:00
< span className = "settings-section-title" >
2024-10-20 20:12:27 +02:00
< img src = '../media/connector-icons/ntfy.svg' alt = "ntfy Logo" / >
2024-10-20 17:54:38 +02:00
Ntfy
< / span >
2024-10-22 18:32:20 +02:00
< label htmlFor = "ntfyEndpoint" > URL < / label >
2024-10-23 02:28:36 +02:00
< input placeholder = { GetNtfy ( ) ? . endpoint ? ? "URL" } id = "ntfyEndpoint" type = "text" onChange = { ( e ) = > setNtfySettings ( s = > ( { . . . s , url : e.target.value } ) ) } / >
2024-10-20 20:12:27 +02:00
< label htmlFor = "ntfyUsername" > Username < / label >
2024-10-23 02:28:36 +02:00
< input placeholder = { NtfyConnected ( ) ? "***" : "Username" } id = "ntfyUsername" type = "text" onChange = { ( e ) = > setNtfySettings ( s = > ( { . . . s , username : e.target.value } ) ) } / >
2024-10-20 20:12:27 +02:00
< label htmlFor = "ntfyPassword" > Password < / label >
2024-10-23 02:28:36 +02:00
< input placeholder = { NtfyConnected ( ) ? "***" : "Password" } id = "ntfyPassword" type = "password" onChange = { ( e ) = > setNtfySettings ( s = > ( { . . . s , password : e.target.value } ) ) } / >
2024-10-20 20:12:27 +02:00
< label htmlFor = "ntfyTopic" > Topic < / label >
2024-10-23 02:28:36 +02:00
< input placeholder = { GetNtfy ( ) ? . topic ? ? "Topic" } id = "ntfyTopic" type = "text" onChange = { ( e ) = > setNtfySettings ( s = > ( { . . . s , topic : e.target.value } ) ) } / >
2024-10-22 18:32:20 +02:00
< div className = "section-actions" >
2024-10-23 02:28:36 +02:00
< span onClick = { ( ) = > new Ntfy ( ntfySettings ) . Test ( apiUri ) . then ( ( ) = > alert ( "Test successful" ) ) } > Test < / span >
< span onClick = { ( ) = > new Ntfy ( ntfySettings ) . Reset ( apiUri ) . then ( RefreshInputs ) } > Reset < / span >
< span onClick = { ( ) = > new Ntfy ( ntfySettings ) . Create ( apiUri ) . then ( RefreshInputs ) } > Apply < / span >
2024-10-20 17:54:38 +02:00
< / div >
< / div >
< / div >
< / div >
< / div >
< / div >
: < > < / >
}
< / div >
) ;
}