2023-08-22 04:51:00 +02:00
/ *
TODO :
* /
2023-10-10 01:51:09 +02:00
//const DEBUG_TONY_SAMA_FORK_MODE = true
2023-08-22 04:51:00 +02:00
2024-05-12 15:43:09 +02:00
import { getRequestHeaders , callPopup , processDroppedFiles , eventSource , event _types } from '../../../script.js' ;
2024-04-11 21:39:42 +02:00
import { deleteExtension , extensionNames , getContext , installExtension , renderExtensionTemplateAsync } from '../../extensions.js' ;
2024-05-12 15:43:09 +02:00
import { POPUP _TYPE , callGenericPopup } from '../../popup.js' ;
2024-02-16 19:42:56 +01:00
import { executeSlashCommands } from '../../slash-commands.js' ;
2024-07-10 18:12:01 +02:00
import { flashHighlight , getStringHash , isValidUrl } from '../../utils.js' ;
2023-08-22 04:51:00 +02:00
export { MODULE _NAME } ;
2023-10-18 23:26:00 +02:00
const MODULE _NAME = 'assets' ;
2023-12-02 19:04:51 +01:00
const DEBUG _PREFIX = '<Assets module> ' ;
2023-10-16 01:09:43 +02:00
let previewAudio = null ;
2023-12-02 20:11:06 +01:00
let ASSETS _JSON _URL = 'https://raw.githubusercontent.com/SillyTavern/SillyTavern-Content/main/index.json' ;
2023-08-22 04:51:00 +02:00
2023-08-23 18:51:41 +02:00
2023-08-22 04:51:00 +02:00
// DBG
//if (DEBUG_TONY_SAMA_FORK_MODE)
// ASSETS_JSON_URL = "https://raw.githubusercontent.com/Tony-sama/SillyTavern-Content/main/index.json"
2023-08-23 05:10:55 +02:00
let availableAssets = { } ;
let currentAssets = { } ;
2023-08-22 04:51:00 +02:00
//#############################//
// Extension UI and Settings //
//#############################//
2024-03-17 20:32:21 +01:00
function filterAssets ( ) {
const searchValue = String ( $ ( '#assets_search' ) . val ( ) ) . toLowerCase ( ) . trim ( ) ;
const typeValue = String ( $ ( '#assets_type_select' ) . val ( ) ) ;
if ( typeValue === '' ) {
$ ( '#assets_menu .assets-list-div' ) . show ( ) ;
$ ( '#assets_menu .assets-list-div h3' ) . show ( ) ;
} else {
$ ( '#assets_menu .assets-list-div h3' ) . hide ( ) ;
$ ( '#assets_menu .assets-list-div' ) . hide ( ) ;
$ ( ` #assets_menu .assets-list-div[data-type=" ${ typeValue } "] ` ) . show ( ) ;
}
if ( searchValue === '' ) {
$ ( '#assets_menu .asset-block' ) . show ( ) ;
} else {
$ ( '#assets_menu .asset-block' ) . hide ( ) ;
$ ( '#assets_menu .asset-block' ) . filter ( function ( ) {
return $ ( this ) . text ( ) . toLowerCase ( ) . includes ( searchValue ) ;
} ) . show ( ) ;
}
}
const KNOWN _TYPES = {
'extension' : 'Extensions' ,
'character' : 'Characters' ,
'ambient' : 'Ambient sounds' ,
'bgm' : 'Background music' ,
'blip' : 'Blip sounds' ,
} ;
2023-08-23 18:51:41 +02:00
function downloadAssetsList ( url ) {
2023-08-24 20:59:26 +02:00
updateCurrentAssets ( ) . then ( function ( ) {
2023-12-02 19:04:51 +01:00
fetch ( url , { cache : 'no-cache' } )
2023-08-24 20:59:26 +02:00
. then ( response => response . json ( ) )
. then ( json => {
2023-08-22 04:51:00 +02:00
2023-08-24 20:59:26 +02:00
availableAssets = { } ;
2023-12-02 19:04:51 +01:00
$ ( '#assets_menu' ) . empty ( ) ;
2023-08-24 20:59:26 +02:00
2023-12-02 19:04:51 +01:00
console . debug ( DEBUG _PREFIX , 'Received assets dictionary' , json ) ;
2023-08-24 20:59:26 +02:00
for ( const i of json ) {
//console.log(DEBUG_PREFIX,i)
2023-12-02 19:04:51 +01:00
if ( availableAssets [ i [ 'type' ] ] === undefined )
availableAssets [ i [ 'type' ] ] = [ ] ;
2023-08-24 20:59:26 +02:00
2023-12-02 19:04:51 +01:00
availableAssets [ i [ 'type' ] ] . push ( i ) ;
2023-08-24 20:59:26 +02:00
}
2023-12-02 19:04:51 +01:00
console . debug ( DEBUG _PREFIX , 'Updated available assets to' , availableAssets ) ;
2023-10-09 16:21:12 +02:00
// First extensions, then everything else
const assetTypes = Object . keys ( availableAssets ) . sort ( ( a , b ) => ( a === 'extension' ) ? - 1 : ( b === 'extension' ) ? 1 : 0 ) ;
2023-08-24 20:59:26 +02:00
2024-03-17 20:32:21 +01:00
$ ( '#assets_type_select' ) . empty ( ) ;
$ ( '#assets_search' ) . val ( '' ) ;
$ ( '#assets_type_select' ) . append ( $ ( '<option />' , { value : '' , text : 'All' } ) ) ;
for ( const type of assetTypes ) {
const option = $ ( '<option />' , { value : type , text : KNOWN _TYPES [ type ] || type } ) ;
$ ( '#assets_type_select' ) . append ( option ) ;
}
if ( assetTypes . includes ( 'extension' ) ) {
$ ( '#assets_type_select' ) . val ( 'extension' ) ;
}
$ ( '#assets_type_select' ) . off ( 'change' ) . on ( 'change' , filterAssets ) ;
$ ( '#assets_search' ) . off ( 'input' ) . on ( 'input' , filterAssets ) ;
2023-10-09 16:21:12 +02:00
for ( const assetType of assetTypes ) {
2023-12-02 19:04:51 +01:00
let assetTypeMenu = $ ( '<div />' , { id : 'assets_audio_ambient_div' , class : 'assets-list-div' } ) ;
2024-03-17 20:32:21 +01:00
assetTypeMenu . attr ( 'data-type' , assetType ) ;
assetTypeMenu . append ( ` <h3> ${ KNOWN _TYPES [ assetType ] || assetType } </h3> ` ) . hide ( ) ;
2023-10-27 12:07:56 +02:00
if ( assetType == 'extension' ) {
assetTypeMenu . append ( `
< div class = "assets-list-git" >
2024-04-08 19:48:39 +02:00
To download extensions from this page , you need to have < a href = "https://git-scm.com/downloads" target = "_blank" > Git < / a > i n s t a l l e d . < b r >
Click the < i class = "fa-solid fa-sm fa-arrow-up-right-from-square" > < / i > i c o n t o v i s i t t h e E x t e n s i o n ' s r e p o f o r t i p s o n h o w t o u s e i t .
2023-10-27 12:07:56 +02:00
< / d i v > ` ) ;
}
2024-05-13 15:29:34 +02:00
for ( const i in availableAssets [ assetType ] . sort ( ( a , b ) => a ? . name && b ? . name && a [ 'name' ] . localeCompare ( b [ 'name' ] ) ) ) {
2023-08-24 20:59:26 +02:00
const asset = availableAssets [ assetType ] [ i ] ;
const elemId = ` assets_install_ ${ assetType } _ ${ i } ` ;
2024-02-16 19:42:56 +01:00
let element = $ ( '<div />' , { id : elemId , class : 'asset-download-button right_menu_button' } ) ;
const label = $ ( '<i class="fa-fw fa-solid fa-download fa-lg"></i>' ) ;
2023-08-24 20:59:26 +02:00
element . append ( label ) ;
//if (DEBUG_TONY_SAMA_FORK_MODE)
2023-10-10 01:51:09 +02:00
// asset["url"] = asset["url"].replace("https://github.com/SillyTavern/","https://github.com/Tony-sama/"); // DBG
2023-08-24 20:59:26 +02:00
2023-12-02 19:04:51 +01:00
console . debug ( DEBUG _PREFIX , 'Checking asset' , asset [ 'id' ] , asset [ 'url' ] ) ;
2023-08-24 20:59:26 +02:00
2023-08-25 00:45:15 +02:00
const assetInstall = async function ( ) {
2023-12-02 19:04:51 +01:00
element . off ( 'click' ) ;
label . removeClass ( 'fa-download' ) ;
2023-08-25 00:45:15 +02:00
this . classList . add ( 'asset-download-button-loading' ) ;
2023-12-02 19:04:51 +01:00
await installAsset ( asset [ 'url' ] , assetType , asset [ 'id' ] ) ;
label . addClass ( 'fa-check' ) ;
2023-08-25 00:45:15 +02:00
this . classList . remove ( 'asset-download-button-loading' ) ;
2023-12-02 19:04:51 +01:00
element . on ( 'click' , assetDelete ) ;
element . on ( 'mouseenter' , function ( ) {
label . removeClass ( 'fa-check' ) ;
label . addClass ( 'fa-trash' ) ;
label . addClass ( 'redOverlayGlow' ) ;
} ) . on ( 'mouseleave' , function ( ) {
label . addClass ( 'fa-check' ) ;
label . removeClass ( 'fa-trash' ) ;
label . removeClass ( 'redOverlayGlow' ) ;
2023-08-25 00:45:15 +02:00
} ) ;
} ;
2023-10-18 23:26:00 +02:00
const assetDelete = async function ( ) {
2024-02-16 19:42:56 +01:00
if ( assetType === 'character' ) {
toastr . error ( 'Go to the characters menu to delete a character.' , 'Character deletion not supported' ) ;
await executeSlashCommands ( ` /go ${ asset [ 'id' ] } ` ) ;
return ;
}
2023-12-02 19:04:51 +01:00
element . off ( 'click' ) ;
await deleteAsset ( assetType , asset [ 'id' ] ) ;
label . removeClass ( 'fa-check' ) ;
label . removeClass ( 'redOverlayGlow' ) ;
label . removeClass ( 'fa-trash' ) ;
label . addClass ( 'fa-download' ) ;
element . off ( 'mouseenter' ) . off ( 'mouseleave' ) ;
element . on ( 'click' , assetInstall ) ;
2023-12-02 20:11:06 +01:00
} ;
2023-08-25 00:45:15 +02:00
2023-12-02 19:04:51 +01:00
if ( isAssetInstalled ( assetType , asset [ 'id' ] ) ) {
console . debug ( DEBUG _PREFIX , 'installed, checked' ) ;
label . toggleClass ( 'fa-download' ) ;
label . toggleClass ( 'fa-check' ) ;
element . on ( 'click' , assetDelete ) ;
element . on ( 'mouseenter' , function ( ) {
label . removeClass ( 'fa-check' ) ;
label . addClass ( 'fa-trash' ) ;
label . addClass ( 'redOverlayGlow' ) ;
} ) . on ( 'mouseleave' , function ( ) {
label . addClass ( 'fa-check' ) ;
label . removeClass ( 'fa-trash' ) ;
label . removeClass ( 'redOverlayGlow' ) ;
2023-08-25 00:45:15 +02:00
} ) ;
2023-08-24 20:59:26 +02:00
}
else {
2023-12-02 20:11:06 +01:00
console . debug ( DEBUG _PREFIX , 'not installed, unchecked' ) ;
2023-12-02 19:04:51 +01:00
element . prop ( 'checked' , false ) ;
element . on ( 'click' , assetInstall ) ;
2023-08-24 20:59:26 +02:00
}
2023-12-02 20:11:06 +01:00
console . debug ( DEBUG _PREFIX , 'Created element for ' , asset [ 'id' ] ) ;
2023-08-24 20:59:26 +02:00
2023-12-02 19:04:51 +01:00
const displayName = DOMPurify . sanitize ( asset [ 'name' ] || asset [ 'id' ] ) ;
const description = DOMPurify . sanitize ( asset [ 'description' ] || '' ) ;
const url = isValidUrl ( asset [ 'url' ] ) ? asset [ 'url' ] : '' ;
2024-04-09 10:30:24 +02:00
const title = assetType === 'extension' ? ` Extension repo/guide: ${ url } ` : 'Preview in browser' ;
2024-02-16 19:42:56 +01:00
const previewIcon = ( assetType === 'extension' || assetType === 'character' ) ? 'fa-arrow-up-right-from-square' : 'fa-headphones-simple' ;
2023-10-08 22:20:01 +02:00
2024-02-16 19:42:56 +01:00
const assetBlock = $ ( '<i></i>' )
2023-08-24 20:59:26 +02:00
. append ( element )
2024-02-16 19:42:56 +01:00
. append ( ` <div class="flex-container flexFlowColumn flexNoGap">
< span class = "asset-name flex-container alignitemscenter" >
2023-10-16 00:39:08 +02:00
< b > $ { displayName } < / b >
2024-04-09 10:30:24 +02:00
< a class = "asset_preview" href = "${url}" target = "_blank" title = "${title}" >
2023-10-16 01:09:43 +02:00
< i class = "fa-solid fa-sm ${previewIcon}" > < / i >
2023-10-16 00:39:08 +02:00
< / a >
< / s p a n >
2024-02-16 19:42:56 +01:00
< small class = "asset-description" >
$ { description }
< / s m a l l >
< / d i v > ` ) ;
if ( assetType === 'character' ) {
2024-05-13 15:29:34 +02:00
if ( asset . highlight ) {
assetBlock . find ( '.asset-name' ) . append ( '<i class="fa-solid fa-sm fa-trophy"></i>' ) ;
}
2024-02-16 19:42:56 +01:00
assetBlock . find ( '.asset-name' ) . prepend ( ` <div class="avatar"><img src=" ${ asset [ 'url' ] } " alt=" ${ displayName } "></div> ` ) ;
}
2024-03-17 20:32:21 +01:00
assetBlock . addClass ( 'asset-block' ) ;
2024-02-16 19:42:56 +01:00
assetTypeMenu . append ( assetBlock ) ;
2023-08-23 05:10:55 +02:00
}
2023-12-02 19:04:51 +01:00
assetTypeMenu . appendTo ( '#assets_menu' ) ;
2023-10-16 01:09:43 +02:00
assetTypeMenu . on ( 'click' , 'a.asset_preview' , previewAsset ) ;
2023-08-22 04:51:00 +02:00
}
2023-08-23 18:51:41 +02:00
2024-03-17 20:32:21 +01:00
filterAssets ( ) ;
$ ( '#assets_filters' ) . show ( ) ;
2023-12-02 19:04:51 +01:00
$ ( '#assets_menu' ) . show ( ) ;
2023-08-24 20:59:26 +02:00
} )
. catch ( ( error ) => {
2024-07-10 18:24:09 +02:00
// Info hint if the user maybe... likely accidently was trying to install an extension and we wanna help guide them? uwu :3
const installButton = $ ( '#third_party_extension_button' ) ;
flashHighlight ( installButton , 10_000 ) ;
toastr . info ( 'If you are trying to install an extension, click the flashing button to the right of this.' , 'Trying to install a custom extension?' , { timeOut : 10_000 } ) ;
// Error logged after, to appear on top
2023-08-24 20:59:26 +02:00
console . error ( error ) ;
2023-12-02 19:04:51 +01:00
toastr . error ( 'Problem with assets URL' , DEBUG _PREFIX + 'Cannot get assets list' ) ;
$ ( '#assets-connect-button' ) . addClass ( 'fa-plug-circle-exclamation' ) ;
$ ( '#assets-connect-button' ) . addClass ( 'redOverlayGlow' ) ;
2023-08-24 20:59:26 +02:00
} ) ;
2023-08-22 04:51:00 +02:00
} ) ;
}
2023-10-16 01:09:43 +02:00
function previewAsset ( e ) {
const href = $ ( this ) . attr ( 'href' ) ;
const audioExtensions = [ '.mp3' , '.ogg' , '.wav' ] ;
if ( audioExtensions . some ( ext => href . endsWith ( ext ) ) ) {
e . preventDefault ( ) ;
if ( previewAudio ) {
previewAudio . pause ( ) ;
if ( previewAudio . src === href ) {
previewAudio = null ;
return ;
}
}
previewAudio = new Audio ( href ) ;
previewAudio . play ( ) ;
return ;
}
}
2023-08-24 20:59:26 +02:00
function isAssetInstalled ( assetType , filename ) {
2023-10-08 22:20:01 +02:00
let assetList = currentAssets [ assetType ] ;
if ( assetType == 'extension' ) {
2023-12-02 19:04:51 +01:00
const thirdPartyMarker = 'third-party/' ;
2023-10-08 22:20:01 +02:00
assetList = extensionNames . filter ( x => x . startsWith ( thirdPartyMarker ) ) . map ( x => x . replace ( thirdPartyMarker , '' ) ) ;
}
2024-02-16 19:42:56 +01:00
if ( assetType == 'character' ) {
assetList = getContext ( ) . characters . map ( x => x . avatar ) ;
}
2023-10-08 22:20:01 +02:00
for ( const i of assetList ) {
2023-08-23 05:10:55 +02:00
//console.debug(DEBUG_PREFIX,i,filename)
2023-08-24 20:59:26 +02:00
if ( i . includes ( filename ) )
2023-08-22 04:51:00 +02:00
return true ;
}
return false ;
}
2023-08-23 05:10:55 +02:00
async function installAsset ( url , assetType , filename ) {
2023-12-02 19:04:51 +01:00
console . debug ( DEBUG _PREFIX , 'Downloading ' , url ) ;
2023-08-24 00:17:07 +02:00
const category = assetType ;
2023-08-22 04:51:00 +02:00
try {
2023-10-08 22:20:01 +02:00
if ( category === 'extension' ) {
2023-12-02 20:11:06 +01:00
console . debug ( DEBUG _PREFIX , 'Installing extension ' , url ) ;
2023-10-08 22:20:01 +02:00
await installExtension ( url ) ;
2023-12-02 20:11:06 +01:00
console . debug ( DEBUG _PREFIX , 'Extension installed.' ) ;
2023-10-08 22:20:01 +02:00
return ;
}
2023-08-24 20:59:26 +02:00
const body = { url , category , filename } ;
2023-09-16 15:39:07 +02:00
const result = await fetch ( '/api/assets/download' , {
2023-08-23 18:51:41 +02:00
method : 'POST' ,
headers : getRequestHeaders ( ) ,
2023-08-24 20:59:26 +02:00
body : JSON . stringify ( body ) ,
cache : 'no-cache' ,
2023-08-23 18:51:41 +02:00
} ) ;
2023-08-24 20:59:26 +02:00
if ( result . ok ) {
2023-12-02 20:11:06 +01:00
console . debug ( DEBUG _PREFIX , 'Download success.' ) ;
2024-02-16 19:42:56 +01:00
if ( category === 'character' ) {
console . debug ( DEBUG _PREFIX , 'Importing character ' , filename ) ;
const blob = await result . blob ( ) ;
const file = new File ( [ blob ] , filename , { type : blob . type } ) ;
2024-02-18 23:17:23 +01:00
await processDroppedFiles ( [ file ] , true ) ;
2024-02-16 19:42:56 +01:00
console . debug ( DEBUG _PREFIX , 'Character downloaded.' ) ;
}
2023-08-24 00:17:07 +02:00
}
2023-08-22 04:51:00 +02:00
}
catch ( err ) {
console . log ( err ) ;
return [ ] ;
}
}
2023-08-25 00:45:15 +02:00
async function deleteAsset ( assetType , filename ) {
2023-12-02 19:04:51 +01:00
console . debug ( DEBUG _PREFIX , 'Deleting ' , assetType , filename ) ;
2023-08-25 00:45:15 +02:00
const category = assetType ;
try {
2023-10-08 22:20:01 +02:00
if ( category === 'extension' ) {
2023-12-02 20:11:06 +01:00
console . debug ( DEBUG _PREFIX , 'Deleting extension ' , filename ) ;
2023-10-08 22:20:01 +02:00
await deleteExtension ( filename ) ;
2023-12-02 20:11:06 +01:00
console . debug ( DEBUG _PREFIX , 'Extension deleted.' ) ;
2023-10-08 22:20:01 +02:00
}
2023-08-25 00:45:15 +02:00
const body = { category , filename } ;
2023-09-16 15:39:07 +02:00
const result = await fetch ( '/api/assets/delete' , {
2023-08-25 00:45:15 +02:00
method : 'POST' ,
headers : getRequestHeaders ( ) ,
body : JSON . stringify ( body ) ,
cache : 'no-cache' ,
} ) ;
if ( result . ok ) {
2023-12-02 20:11:06 +01:00
console . debug ( DEBUG _PREFIX , 'Deletion success.' ) ;
2023-08-25 00:45:15 +02:00
}
}
catch ( err ) {
console . log ( err ) ;
return [ ] ;
}
}
2024-05-12 15:43:09 +02:00
async function openCharacterBrowser ( forceDefault ) {
const url = forceDefault ? ASSETS _JSON _URL : String ( $ ( '#assets-json-url-field' ) . val ( ) ) ;
const fetchResult = await fetch ( url , { cache : 'no-cache' } ) ;
const json = await fetchResult . json ( ) ;
const characters = json . filter ( x => x . type === 'character' ) ;
if ( ! characters . length ) {
toastr . error ( 'No characters found in the assets list' , 'Character browser' ) ;
return ;
}
2024-05-12 23:05:32 +02:00
const template = $ ( await renderExtensionTemplateAsync ( MODULE _NAME , 'market' , { } ) ) ;
2024-05-12 15:43:09 +02:00
2024-05-12 23:05:32 +02:00
for ( const character of characters . sort ( ( a , b ) => a . name . localeCompare ( b . name ) ) ) {
const listElement = template . find ( character . highlight ? '.contestWinnersList' : '.featuredCharactersList' ) ;
2024-05-12 15:43:09 +02:00
const characterElement = $ ( await renderExtensionTemplateAsync ( MODULE _NAME , 'character' , character ) ) ;
const downloadButton = characterElement . find ( '.characterAssetDownloadButton' ) ;
const checkMark = characterElement . find ( '.characterAssetCheckMark' ) ;
const isInstalled = isAssetInstalled ( 'character' , character . id ) ;
downloadButton . toggle ( ! isInstalled ) . on ( 'click' , async ( ) => {
downloadButton . toggleClass ( 'fa-download fa-spinner fa-spin' ) ;
await installAsset ( character . url , 'character' , character . id ) ;
downloadButton . hide ( ) ;
checkMark . show ( ) ;
} ) ;
checkMark . toggle ( isInstalled ) ;
listElement . append ( characterElement ) ;
}
2024-05-12 23:05:32 +02:00
callGenericPopup ( template , POPUP _TYPE . TEXT , '' , { okButton : 'Close' , wide : true , large : true , allowVerticalScrolling : true , allowHorizontalScrolling : false } ) ;
2024-05-12 15:43:09 +02:00
}
2023-08-22 04:51:00 +02:00
//#############################//
// API Calls //
//#############################//
async function updateCurrentAssets ( ) {
2023-12-02 20:11:06 +01:00
console . debug ( DEBUG _PREFIX , 'Checking installed assets...' ) ;
2023-08-22 04:51:00 +02:00
try {
2023-12-02 19:04:51 +01:00
const result = await fetch ( '/api/assets/get' , {
2023-08-23 18:51:41 +02:00
method : 'POST' ,
headers : getRequestHeaders ( ) ,
} ) ;
2023-08-23 05:10:55 +02:00
currentAssets = result . ok ? ( await result . json ( ) ) : { } ;
2023-08-22 04:51:00 +02:00
}
catch ( err ) {
console . log ( err ) ;
}
2023-12-02 20:11:06 +01:00
console . debug ( DEBUG _PREFIX , 'Current assets found:' , currentAssets ) ;
2023-08-22 04:51:00 +02:00
}
//#############################//
2023-08-23 18:51:41 +02:00
// Extension load //
2023-08-22 04:51:00 +02:00
//#############################//
2023-08-23 18:51:41 +02:00
// This function is called when the extension is loaded
jQuery ( async ( ) => {
// This is an example of loading HTML from a file
2024-04-11 21:39:42 +02:00
const windowTemplate = await renderExtensionTemplateAsync ( MODULE _NAME , 'window' , { } ) ;
const windowHtml = $ ( windowTemplate ) ;
2023-08-23 18:51:41 +02:00
2023-08-24 01:02:34 +02:00
const assetsJsonUrl = windowHtml . find ( '#assets-json-url-field' ) ;
2023-08-23 18:51:41 +02:00
assetsJsonUrl . val ( ASSETS _JSON _URL ) ;
2024-05-12 23:05:32 +02:00
const charactersButton = windowHtml . find ( '#assets-characters-button' ) ;
charactersButton . on ( 'click' , async function ( ) {
openCharacterBrowser ( false ) ;
} ) ;
2024-07-10 18:12:01 +02:00
const installHintButton = windowHtml . find ( '.assets-install-hint-link' ) ;
installHintButton . on ( 'click' , async function ( ) {
const installButton = $ ( '#third_party_extension_button' ) ;
flashHighlight ( installButton , 5000 ) ;
toastr . info ( 'Click the flashing button to the right of this to install extensions.' , 'How to install extensions?' ) ;
} ) ;
2023-08-24 01:02:34 +02:00
const connectButton = windowHtml . find ( '#assets-connect-button' ) ;
2023-12-02 19:04:51 +01:00
connectButton . on ( 'click' , async function ( ) {
2023-10-18 23:26:00 +02:00
const url = String ( assetsJsonUrl . val ( ) ) ;
const rememberKey = ` Assets_SkipConfirm_ ${ getStringHash ( url ) } ` ;
const skipConfirm = localStorage . getItem ( rememberKey ) === 'true' ;
2024-04-11 21:39:42 +02:00
const template = await renderExtensionTemplateAsync ( MODULE _NAME , 'confirm' , { url } ) ;
2023-10-18 23:26:00 +02:00
const confirmation = skipConfirm || await callPopup ( template , 'confirm' ) ;
2023-08-23 18:51:41 +02:00
if ( confirmation ) {
try {
2023-10-18 23:26:00 +02:00
if ( ! skipConfirm ) {
const rememberValue = Boolean ( $ ( '#assets-remember' ) . prop ( 'checked' ) ) ;
localStorage . setItem ( rememberKey , String ( rememberValue ) ) ;
}
2023-12-02 19:04:51 +01:00
console . debug ( DEBUG _PREFIX , 'Confimation, loading assets...' ) ;
2023-10-18 23:26:00 +02:00
downloadAssetsList ( url ) ;
2023-12-02 19:04:51 +01:00
connectButton . removeClass ( 'fa-plug-circle-exclamation' ) ;
connectButton . removeClass ( 'redOverlayGlow' ) ;
connectButton . addClass ( 'fa-plug-circle-check' ) ;
2023-08-23 18:51:41 +02:00
} catch ( error ) {
console . error ( 'Error:' , error ) ;
2023-10-18 23:26:00 +02:00
toastr . error ( ` Cannot get assets list from ${ url } ` ) ;
2023-12-02 19:04:51 +01:00
connectButton . removeClass ( 'fa-plug-circle-check' ) ;
connectButton . addClass ( 'fa-plug-circle-exclamation' ) ;
connectButton . removeClass ( 'redOverlayGlow' ) ;
2023-08-23 18:51:41 +02:00
}
}
else {
2023-12-02 19:04:51 +01:00
console . debug ( DEBUG _PREFIX , 'Connection refused by user' ) ;
2023-08-23 18:51:41 +02:00
}
} ) ;
2024-03-17 20:32:21 +01:00
windowHtml . find ( '#assets_filters' ) . hide ( ) ;
2024-06-24 21:15:08 +02:00
$ ( '#assets_container' ) . append ( windowHtml ) ;
2024-05-12 15:43:09 +02:00
eventSource . on ( event _types . OPEN _CHARACTER _LIBRARY , async ( forceDefault ) => {
openCharacterBrowser ( forceDefault ) ;
} ) ;
2023-08-24 20:59:26 +02:00
} ) ;