2019-11-03 11:13:21 +00:00
var appJSON = [ ] ; // List of apps and info from apps.json
2019-12-05 14:48:56 +00:00
var appsInstalled = [ ] ; // list of app JSON
2019-12-24 13:47:02 +00:00
var files = [ ] ; // list of files on Bangle
2019-11-03 11:13:21 +00:00
2019-10-30 17:33:58 +00:00
httpGet ( "apps.json" ) . then ( apps => {
2019-11-07 08:43:56 +00:00
try {
appJSON = JSON . parse ( apps ) ;
} catch ( e ) {
console . log ( e ) ;
showToast ( "App List Corrupted" , "error" ) ;
}
2019-11-03 11:13:21 +00:00
appJSON . sort ( appSorter ) ;
2019-10-30 17:33:58 +00:00
refreshLibrary ( ) ;
} ) ;
// Status
// =========================================== Top Navigation
2019-11-03 11:13:21 +00:00
function showToast ( message , type ) {
2019-10-30 17:33:58 +00:00
// toast-primary, toast-success, toast-warning or toast-error
2019-11-06 17:25:02 +00:00
var style = "toast-primary" ;
if ( type == "success" ) style = "toast-success" ;
else if ( type == "error" ) style = "toast-error" ;
else if ( type !== undefined ) console . log ( "showToast: unknown toast " + type ) ;
2019-10-30 17:33:58 +00:00
var toastcontainer = document . getElementById ( "toastcontainer" ) ;
2019-11-06 17:25:02 +00:00
var msgDiv = htmlElement ( ` <div class="toast ${ style } "></div> ` ) ;
2019-10-30 17:33:58 +00:00
msgDiv . innerHTML = message ;
toastcontainer . append ( msgDiv ) ;
setTimeout ( function ( ) {
msgDiv . remove ( ) ;
} , 5000 ) ;
}
2019-12-05 11:48:56 +00:00
var progressToast ;
Puck . writeProgress = function ( charsSent , charsTotal ) {
if ( charsSent === undefined ) {
if ( progressToast ) progressToast . remove ( ) ;
progressToast = undefined ;
return ;
}
var percent = Math . round ( charsSent * 100 / charsTotal ) ;
if ( ! progressToast ) {
var toastcontainer = document . getElementById ( "toastcontainer" ) ;
progressToast = htmlElement ( ` <div class="toast">
< div class = "bar bar-sm" >
< div class = "bar-item" id = "progressToast" role = "progressbar" style = "width:${percent}%;" aria - valuenow = "${percent}" aria - valuemin = "0" aria - valuemax = "100" > < / d i v >
< / d i v >
< / d i v > ` ) ;
toastcontainer . append ( progressToast ) ;
} else {
var pt = document . getElementById ( "progressToast" ) ;
pt . setAttribute ( "aria-valuenow" , percent ) ;
pt . style . width = percent + "%" ;
}
}
2019-10-30 17:33:58 +00:00
function showPrompt ( title , text ) {
return new Promise ( ( resolve , reject ) => {
var modal = htmlElement ( ` <div class="modal active">
<!-- < a href = "#close" class = "modal-overlay" aria - label = "Close" > < / a > - - >
< div class = "modal-container" >
< div class = "modal-header" >
< a href = "#close" class = "btn btn-clear float-right" aria - label = "Close" > < / a >
< div class = "modal-title h5" > $ { escapeHtml ( title ) } < / d i v >
< / d i v >
< div class = "modal-body" >
< div class = "content" >
$ { escapeHtml ( text ) }
< / d i v >
< / d i v >
< div class = "modal-footer" >
< div class = "modal-footer" >
< button class = "btn btn-primary" isyes = "1" > Yes < / b u t t o n >
< button class = "btn" isyes = "0" > No < / b u t t o n >
< / d i v >
< / d i v >
< / d i v >
< / d i v > ` ) ;
document . body . append ( modal ) ;
htmlToArray ( modal . getElementsByTagName ( "button" ) ) . forEach ( button => {
button . addEventListener ( "click" , event => {
2019-11-06 17:25:02 +00:00
event . preventDefault ( ) ;
2019-11-03 11:13:21 +00:00
var isYes = event . target . getAttribute ( "isyes" ) == "1" ;
2019-10-30 17:33:58 +00:00
if ( isYes ) resolve ( ) ;
else reject ( ) ;
modal . remove ( ) ;
} ) ;
} ) ;
} ) ;
}
2019-11-06 17:25:02 +00:00
function handleCustomApp ( app ) {
2020-02-07 17:16:45 +00:00
// Pops up an IFRAME that allows an app to be customised
if ( ! app . custom ) throw new Error ( "App doesn't have custom HTML" ) ;
2019-11-06 17:25:02 +00:00
return new Promise ( ( resolve , reject ) => {
var modal = htmlElement ( ` <div class="modal active">
< a href = "#close" class = "modal-overlay " aria - label = "Close" > < / a >
< div class = "modal-container" style = "height:100%" >
< div class = "modal-header" >
< a href = "#close" class = "btn btn-clear float-right" aria - label = "Close" > < / a >
< div class = "modal-title h5" > $ { escapeHtml ( app . name ) } < / d i v >
< / d i v >
< div class = "modal-body" style = "height:100%" >
< div class = "content" style = "height:100%" >
2019-11-17 22:39:31 +00:00
< iframe src = "apps/${app.id}/${app.custom}" style = "width:100%;height:100%;border:0px;" >
2019-11-06 17:25:02 +00:00
< / d i v >
< / d i v >
< / d i v >
< / d i v > ` ) ;
document . body . append ( modal ) ;
htmlToArray ( modal . getElementsByTagName ( "a" ) ) . forEach ( button => {
button . addEventListener ( "click" , event => {
event . preventDefault ( ) ;
modal . remove ( ) ;
reject ( "Window closed" ) ;
} ) ;
} ) ;
var iframe = modal . getElementsByTagName ( "iframe" ) [ 0 ] ;
iframe . contentWindow . addEventListener ( "message" , function ( event ) {
var app = event . data ;
console . log ( "Received custom app" , app ) ;
modal . remove ( ) ;
Comms . uploadApp ( app ) . then ( resolve , reject ) ;
} , false ) ;
} ) ;
}
2020-02-07 17:16:45 +00:00
function handleAppInterface ( app ) {
// IFRAME interface window that can be used to get data from the app
if ( ! app . interface ) throw new Error ( "App doesn't have interface HTML" ) ;
return new Promise ( ( resolve , reject ) => {
var modal = htmlElement ( ` <div class="modal active">
< a href = "#close" class = "modal-overlay " aria - label = "Close" > < / a >
< div class = "modal-container" style = "height:100%" >
< div class = "modal-header" >
< a href = "#close" class = "btn btn-clear float-right" aria - label = "Close" > < / a >
< div class = "modal-title h5" > $ { escapeHtml ( app . name ) } < / d i v >
< / d i v >
< div class = "modal-body" style = "height:100%" >
< div class = "content" style = "height:100%" >
< iframe style = "width:100%;height:100%;border:0px;" >
< / d i v >
< / d i v >
< / d i v >
< / d i v > ` ) ;
document . body . append ( modal ) ;
htmlToArray ( modal . getElementsByTagName ( "a" ) ) . forEach ( button => {
button . addEventListener ( "click" , event => {
event . preventDefault ( ) ;
modal . remove ( ) ;
//reject("Window closed");
} ) ;
} ) ;
var iframe = modal . getElementsByTagName ( "iframe" ) [ 0 ] ;
2020-02-10 13:49:36 +00:00
iframe . onload = function ( ) {
var iwin = iframe . contentWindow ;
iwin . addEventListener ( "message" , function ( event ) {
var msg = event . data ;
if ( msg . type == "eval" ) {
Puck . eval ( msg . data , function ( result ) {
iwin . postMessage ( {
type : "evalrsp" ,
data : result ,
id : msg . id
} ) ;
2020-02-07 17:16:45 +00:00
} ) ;
2020-02-10 13:49:36 +00:00
} else if ( msg . type == "write" ) {
Puck . write ( msg . data , function ( result ) {
iwin . postMessage ( {
type : "writersp" ,
data : result ,
id : msg . id
} ) ;
2020-02-07 17:16:45 +00:00
} ) ;
2020-02-10 13:49:36 +00:00
}
} , false ) ;
iwin . postMessage ( { type : "init" } ) ;
} ;
iframe . src = ` apps/ ${ app . id } / ${ app . interface } ` ;
2020-02-07 17:16:45 +00:00
} ) ;
}
2019-10-30 17:33:58 +00:00
// =========================================== Top Navigation
function showTab ( tabname ) {
htmlToArray ( document . querySelectorAll ( "#tab-navigate .tab-item" ) ) . forEach ( tab => {
tab . classList . remove ( "active" ) ;
} ) ;
htmlToArray ( document . querySelectorAll ( ".bangle-tab" ) ) . forEach ( tab => {
tab . style . display = "none" ;
} ) ;
document . getElementById ( "tab-" + tabname ) . classList . add ( "active" ) ;
document . getElementById ( tabname ) . style . display = "inherit" ;
}
// =========================================== Library
2019-11-13 17:27:22 +00:00
var activeFilter = '' ;
var currentSearch = '' ;
2019-10-30 17:33:58 +00:00
function refreshLibrary ( ) {
var panelbody = document . querySelector ( "#librarycontainer .panel-body" ) ;
2019-11-13 17:27:22 +00:00
var visibleApps = appJSON ;
if ( activeFilter ) {
visibleApps = visibleApps . filter ( app => app . tags && app . tags . split ( ',' ) . includes ( activeFilter ) ) ;
}
if ( currentSearch ) {
visibleApps = visibleApps . filter ( app => app . name . toLowerCase ( ) . includes ( currentSearch ) || app . tags . includes ( currentSearch ) ) ;
}
panelbody . innerHTML = visibleApps . map ( ( app , idx ) => {
2020-02-07 14:51:31 +00:00
var appInstalled = appsInstalled . find ( a => a . id == app . id ) ;
var version = getVersionInfo ( app , appInstalled ) ;
var versionInfo = version . text ;
2019-12-05 14:48:56 +00:00
if ( versionInfo ) versionInfo = " <small>(" + versionInfo + ")</small>" ;
2019-11-06 17:25:02 +00:00
return ` <div class="tile column col-6 col-sm-12 col-xs-12">
2019-10-30 17:33:58 +00:00
< div class = "tile-icon" >
2019-11-17 22:39:31 +00:00
< figure class = "avatar" > < img src = "apps/${app.icon?`${app.id}/${app.icon}`:" unknown . png "}" alt = "${escapeHtml(app.name)}" > < / f i g u r e >
2019-10-30 17:33:58 +00:00
< / d i v >
< div class = "tile-content" >
2019-12-05 14:48:56 +00:00
< p class = "tile-title text-bold" > $ { escapeHtml ( app . name ) } $ { versionInfo } < / p >
2019-10-30 17:33:58 +00:00
< p class = "tile-subtitle" > $ { escapeHtml ( app . description ) } < / p >
< / d i v >
< div class = "tile-action" >
2020-02-07 17:16:45 +00:00
< button class = "btn btn-link btn-action btn-lg ${(appInstalled&&app.interface)?" ":" d - hide "}" appid = "${app.id}" title = "Download data from app" > < i class = "icon icon-download" > < / i > < / b u t t o n >
2020-02-07 14:51:31 +00:00
< button class = "btn btn-link btn-action btn-lg ${app.allow_emulator?" ":" d - hide "}" appid = "${app.id}" title = "Try in Emulator" > < i class = "icon icon-share" > < / i > < / b u t t o n >
< button class = "btn btn-link btn-action btn-lg ${version.canUpdate?" ":" d - hide "}" appid = "${app.id}" title = "Update App" > < i class = "icon icon-refresh" > < / i > < / b u t t o n >
< button class = "btn btn-link btn-action btn-lg ${!appInstalled?" ":" d - hide "}" appid = "${app.id}" title = "Upload App" > < i class = "icon icon-upload" > < / i > < / b u t t o n >
< button class = "btn btn-link btn-action btn-lg ${appInstalled?" ":" d - hide "}" appid = "${app.id}" title = "Remove App" > < i class = "icon icon-delete" > < / i > < / b u t t o n >
< button class = "btn btn-link btn-action btn-lg ${app.custom?" ":" d - hide "}" appid = "${app.id}" title = "Customise and Upload App" > < i class = "icon icon-menu" > < / i > < / b u t t o n >
2019-10-30 17:33:58 +00:00
< / d i v >
< / d i v >
2019-11-06 17:25:02 +00:00
` ;}).join("");
2019-10-30 17:33:58 +00:00
// set badge up top
var tab = document . querySelector ( "#tab-librarycontainer a" ) ;
tab . classList . add ( "badge" ) ;
2019-11-03 11:13:21 +00:00
tab . setAttribute ( "data-badge" , appJSON . length ) ;
2019-10-30 17:33:58 +00:00
htmlToArray ( panelbody . getElementsByTagName ( "button" ) ) . forEach ( button => {
button . addEventListener ( "click" , event => {
2020-02-07 14:51:31 +00:00
var button = event . currentTarget ;
var icon = button . firstChild ;
var appid = button . getAttribute ( "appid" ) ;
var app = appNameToApp ( appid ) ;
if ( ! app ) throw new Error ( "App " + appid + " not found" ) ;
// check icon to figure out what we should do
2019-12-03 11:45:55 +00:00
if ( icon . classList . contains ( "icon-share" ) ) {
// emulator
var file = app . storage . find ( f => f . name [ 0 ] == '-' ) ;
if ( ! file ) {
console . error ( "No entrypoint found for " + appid ) ;
return ;
}
var baseurl = window . location . href ;
var url = baseurl + "apps/" + app . id + "/" + file . url ;
window . open ( ` https://espruino.com/ide/emulator.html?codeurl= ${ url } &upload ` ) ;
} else if ( icon . classList . contains ( "icon-upload" ) ) {
2020-02-07 14:51:31 +00:00
// upload
2019-11-03 11:13:21 +00:00
icon . classList . remove ( "icon-upload" ) ;
icon . classList . add ( "loading" ) ;
2019-12-05 14:48:56 +00:00
Comms . uploadApp ( app ) . then ( ( appJSON ) => {
if ( appJSON ) appsInstalled . push ( appJSON ) ;
2019-11-03 11:13:21 +00:00
showToast ( app . name + " Uploaded!" , "success" ) ;
icon . classList . remove ( "loading" ) ;
icon . classList . add ( "icon-delete" ) ;
refreshMyApps ( ) ;
2020-02-07 14:51:31 +00:00
refreshLibrary ( ) ;
2019-11-03 11:13:21 +00:00
} ) . catch ( err => {
showToast ( "Upload failed, " + err , "error" ) ;
icon . classList . remove ( "loading" ) ;
icon . classList . add ( "icon-upload" ) ;
} ) ;
2019-11-06 17:25:02 +00:00
} else if ( icon . classList . contains ( "icon-menu" ) ) {
2020-02-07 14:51:31 +00:00
// custom HTML update
2019-11-06 17:25:02 +00:00
if ( app . custom ) {
icon . classList . remove ( "icon-menu" ) ;
icon . classList . add ( "loading" ) ;
2019-12-05 14:48:56 +00:00
handleCustomApp ( app ) . then ( ( appJSON ) => {
if ( appJSON ) appsInstalled . push ( appJSON ) ;
2019-11-06 17:25:02 +00:00
showToast ( app . name + " Uploaded!" , "success" ) ;
icon . classList . remove ( "loading" ) ;
icon . classList . add ( "icon-delete" ) ;
refreshMyApps ( ) ;
2020-02-07 14:51:31 +00:00
refreshLibrary ( ) ;
2019-11-06 17:25:02 +00:00
} ) . catch ( err => {
showToast ( "Customise failed, " + err , "error" ) ;
icon . classList . remove ( "loading" ) ;
icon . classList . add ( "icon-menu" ) ;
} ) ;
}
2020-02-07 14:51:31 +00:00
} else if ( icon . classList . contains ( "icon-delete" ) ) {
// Remove app
2019-11-03 11:13:21 +00:00
icon . classList . remove ( "icon-delete" ) ;
icon . classList . add ( "loading" ) ;
removeApp ( app ) ;
2020-02-07 14:51:31 +00:00
} else if ( icon . classList . contains ( "icon-refresh" ) ) {
// Update app
icon . classList . remove ( "icon-refresh" ) ;
icon . classList . add ( "loading" ) ;
updateApp ( app ) ;
2020-02-07 17:16:45 +00:00
} else if ( icon . classList . contains ( "icon-download" ) ) {
handleAppInterface ( app ) ;
2019-11-03 11:13:21 +00:00
}
2019-10-30 17:33:58 +00:00
} ) ;
} ) ;
}
refreshLibrary ( ) ;
// =========================================== My Apps
2019-11-03 11:13:21 +00:00
function removeApp ( app ) {
2019-11-06 15:53:38 +00:00
return showPrompt ( "Delete" , "Really remove '" + app . name + "'?" ) . then ( ( ) => {
2020-02-07 14:51:31 +00:00
return Comms . removeApp ( app ) ;
} ) . then ( ( ) => {
appsInstalled = appsInstalled . filter ( a => a . id != app . id ) ;
showToast ( app . name + " removed successfully" , "success" ) ;
refreshMyApps ( ) ;
refreshLibrary ( ) ;
} , err => {
showToast ( app . name + " removal failed, " + err , "error" ) ;
} ) ;
}
function updateApp ( app ) {
Comms . removeApp ( app ) . then ( ( ) => {
showToast ( app . name + " removed successfully. Updating..." , ) ;
appsInstalled = appsInstalled . filter ( a => a . id != app . id ) ;
return Comms . uploadApp ( app ) ;
} ) . then ( ( appJSON ) => {
if ( appJSON ) appsInstalled . push ( appJSON ) ;
showToast ( app . name + " Updated!" , "success" ) ;
refreshMyApps ( ) ;
refreshLibrary ( ) ;
} , err => {
showToast ( app . name + " update failed, " + err , "error" ) ;
2019-11-03 11:13:21 +00:00
} ) ;
}
2020-02-07 17:16:45 +00:00
2019-10-30 17:33:58 +00:00
function appNameToApp ( appName ) {
2019-11-03 11:13:21 +00:00
var app = appJSON . find ( app => app . id == appName ) ;
2019-10-30 17:33:58 +00:00
if ( app ) return app ;
2019-11-03 11:13:21 +00:00
/ * I f a p p n o t k n o w n , a d d j u s t o n e f i l e
which is the JSON - so we ' ll remove it from
the menu but may not get rid of all files . * /
return { id : appName ,
2019-10-30 17:33:58 +00:00
name : "Unknown app " + appName ,
2019-11-17 22:39:31 +00:00
icon : "../unknown.png" ,
2019-10-30 17:33:58 +00:00
description : "Unknown app" ,
2019-11-03 11:13:21 +00:00
storage : [ { name : "+" + appName } ] ,
2019-10-30 17:33:58 +00:00
unknown : true ,
} ;
}
2019-12-24 13:47:02 +00:00
function showLoadingIndicator ( id ) {
var panelbody = document . querySelector ( ` # ${ id } .panel-body ` ) ;
var tab = document . querySelector ( ` #tab- ${ id } a ` ) ;
2019-10-30 17:33:58 +00:00
// set badge up top
tab . classList . add ( "badge" ) ;
tab . setAttribute ( "data-badge" , "" ) ;
// Loading indicator
2019-11-03 11:50:00 +00:00
panelbody . innerHTML = '<div class="tile column col-12"><div class="tile-content" style="min-height:48px;"><div class="loading loading-lg"></div></div></div>' ;
2019-11-03 11:13:21 +00:00
}
function refreshMyApps ( ) {
var panelbody = document . querySelector ( "#myappscontainer .panel-body" ) ;
var tab = document . querySelector ( "#tab-myappscontainer a" ) ;
tab . setAttribute ( "data-badge" , appsInstalled . length ) ;
2020-02-07 17:16:45 +00:00
panelbody . innerHTML = appsInstalled . map ( appInstalled => {
var app = appNameToApp ( appInstalled . id ) ;
var version = getVersionInfo ( app , appInstalled ) ;
2019-12-05 14:48:56 +00:00
return ` <div class="tile column col-6 col-sm-12 col-xs-12">
2019-11-03 11:13:21 +00:00
< div class = "tile-icon" >
2019-11-17 22:39:31 +00:00
< figure class = "avatar" > < img src = "apps/${app.icon?`${app.id}/${app.icon}`:" unknown . png "}" alt = "${escapeHtml(app.name)}" > < / f i g u r e >
2019-10-30 17:33:58 +00:00
< / d i v >
2019-11-03 11:13:21 +00:00
< div class = "tile-content" >
2020-02-07 14:51:31 +00:00
< p class = "tile-title text-bold" > $ { escapeHtml ( app . name ) } < small > ( $ { version . text } ) < / s m a l l > < / p >
2019-11-03 11:13:21 +00:00
< p class = "tile-subtitle" > $ { escapeHtml ( app . description ) } < / p >
< / d i v >
< div class = "tile-action" >
2020-02-07 17:16:45 +00:00
< button class = "btn btn-link btn-action btn-lg ${(appInstalled&&app.interface)?" ":" d - hide "}" appid = "${app.id}" title = "Download data from app" > < i class = "icon icon-download" > < / i > < / b u t t o n >
2020-02-07 14:51:31 +00:00
< button class = "btn btn-link btn-action btn-lg ${version.canUpdate?'':'d-hide'}" appid = "${app.id}" title = "Update App" > < i class = "icon icon-refresh" > < / i > < / b u t t o n >
< button class = "btn btn-link btn-action btn-lg" appid = "${app.id}" title = "Remove App" > < i class = "icon icon-delete" > < / i > < / b u t t o n >
2019-11-03 11:13:21 +00:00
< / d i v >
< / d i v >
2019-12-05 14:48:56 +00:00
` }).join("");
2019-11-03 11:13:21 +00:00
htmlToArray ( panelbody . getElementsByTagName ( "button" ) ) . forEach ( button => {
button . addEventListener ( "click" , event => {
2020-02-07 14:51:31 +00:00
var button = event . currentTarget ;
var icon = button . firstChild ;
var appid = button . getAttribute ( "appid" ) ;
2019-11-03 11:13:21 +00:00
var app = appNameToApp ( appid ) ;
2020-02-07 14:51:31 +00:00
if ( ! app ) throw new Error ( "App " + appid + " not found" ) ;
// check icon to figure out what we should do
if ( icon . classList . contains ( "icon-delete" ) ) removeApp ( app ) ;
if ( icon . classList . contains ( "icon-refresh" ) ) updateApp ( app ) ;
2020-02-07 17:16:45 +00:00
if ( icon . classList . contains ( "icon-download" ) ) handleAppInterface ( app )
2019-10-30 17:33:58 +00:00
} ) ;
} ) ;
}
2019-11-03 11:13:21 +00:00
function getInstalledApps ( ) {
2019-12-24 13:47:02 +00:00
showLoadingIndicator ( "myappscontainer" ) ;
showLoadingIndicator ( "myfscontainer" ) ;
// Get apps and files
return Comms . getInstalledApps ( )
. then ( appJSON => {
appsInstalled = appJSON ;
refreshMyApps ( ) ;
refreshLibrary ( ) ;
} )
. then ( Comms . listFiles )
. then ( list => {
files = list ;
refreshMyFS ( ) ;
} )
. then ( ( ) => handleConnectionChange ( true ) ) ;
2019-11-03 11:13:21 +00:00
}
2019-11-12 10:56:31 +00:00
var connectMyDeviceBtn = document . getElementById ( "connectmydevice" ) ;
function handleConnectionChange ( connected ) {
2019-11-12 14:41:03 +00:00
connectMyDeviceBtn . textContent = connected ? 'Disconnect' : 'Connect' ;
connectMyDeviceBtn . classList . toggle ( 'is-connected' , connected ) ;
2019-11-12 10:56:31 +00:00
}
2019-12-24 13:47:02 +00:00
htmlToArray ( document . querySelectorAll ( ".btn.refresh" ) ) . map ( button => button . addEventListener ( "click" , ( ) => {
2019-11-12 14:41:03 +00:00
getInstalledApps ( ) . catch ( err => {
showToast ( "Getting app list failed, " + err , "error" ) ;
} ) ;
2019-12-24 13:47:02 +00:00
} ) ) ;
2019-11-12 14:41:03 +00:00
connectMyDeviceBtn . addEventListener ( "click" , ( ) => {
if ( connectMyDeviceBtn . classList . contains ( 'is-connected' ) ) {
Comms . disconnectDevice ( ) ;
} else {
getInstalledApps ( ) . catch ( err => {
showToast ( "Device connection failed, " + err , "error" ) ;
} ) ;
}
} ) ;
2019-11-12 10:56:31 +00:00
Comms . watchConnectionChange ( handleConnectionChange ) ;
2019-11-07 09:26:46 +00:00
2019-11-13 17:27:22 +00:00
var filtersContainer = document . querySelector ( "#librarycontainer .filter-nav" ) ;
filtersContainer . addEventListener ( 'click' , ( { target } ) => {
if ( ! target . hasAttribute ( 'filterid' ) ) return ;
if ( target . classList . contains ( 'active' ) ) return ;
2019-11-17 22:39:31 +00:00
2019-11-13 17:27:22 +00:00
activeFilter = target . getAttribute ( 'filterid' ) ;
filtersContainer . querySelector ( '.active' ) . classList . remove ( 'active' ) ;
target . classList . add ( 'active' ) ;
refreshLibrary ( ) ;
} ) ;
var librarySearchInput = document . querySelector ( "#searchform input" ) ;
2019-11-17 22:39:31 +00:00
librarySearchInput . addEventListener ( 'input' , evt => {
2019-11-13 17:27:22 +00:00
currentSearch = evt . target . value . toLowerCase ( ) ;
2019-11-17 22:39:31 +00:00
refreshLibrary ( ) ;
2019-11-13 17:27:22 +00:00
} ) ;
2019-12-24 13:47:02 +00:00
// =========================================== My Files
function refreshMyFS ( ) {
var panelbody = document . querySelector ( "#myfscontainer .panel-body" ) ;
var tab = document . querySelector ( "#tab-myfscontainer a" ) ;
tab . setAttribute ( "data-badge" , files . length ) ;
panelbody . innerHTML = `
< thead >
< tr >
< th > Name < / t h >
< th > Type < / t h >
< / t r >
< / t h e a d >
< tbody > $ {
files . map ( file =>
` <tr data-name=" ${ file } "><td> ${ escapeHtml ( file ) } </td><td> ${ fileType ( file ) . name } </td></li> `
) . join ( "" ) }
< / t b o d y > ` ;
htmlToArray ( panelbody . getElementsByTagName ( "tr" ) ) . forEach ( row => {
row . addEventListener ( "click" , event => {
var name = event . target . closest ( 'tr' ) . dataset . name ;
const type = fileType ( name ) ;
Comms . readFile ( name ) . then ( content => content . length && saveAs ( new Blob ( [ content ] , type ) , name ) ) ;
} ) ;
} ) ;
}
function fileType ( file ) {
switch ( file [ 0 ] ) {
case "+" : return { name : "App descriptor" , type : "application/json;charset=utf-8" } ;
case "*" : return { name : "App icon" , type : "text/plain;charset=utf-8" } ;
case "-" : return { name : "App code" , type : "application/javascript;charset=utf-8" } ;
case "=" : return { name : "Boot-time code" , type : "application/javascript;charset=utf-8" } ;
default : return { name : "Plain" , type : "text/plain;charset=utf-8" } ;
}
}
2019-11-07 09:26:46 +00:00
// =========================================== About
document . getElementById ( "settime" ) . addEventListener ( "click" , event => {
Comms . setTime ( ) . then ( ( ) => {
showToast ( "Time set successfully" , "success" ) ;
} , err => {
showToast ( "Error setting time, " + err , "error" ) ;
} ) ;
} ) ;
document . getElementById ( "removeall" ) . addEventListener ( "click" , event => {
showPrompt ( "Remove All" , "Really remove all apps?" ) . then ( ( ) => {
2020-02-04 16:30:31 +00:00
return Comms . removeAllApps ( ) ;
} ) . then ( ( ) => {
appsInstalled = [ ] ;
showToast ( "All apps removed" , "success" ) ;
return getInstalledApps ( ) ;
} ) . catch ( err => {
showToast ( "App removal failed, " + err , "error" ) ;
2019-11-07 09:26:46 +00:00
} ) ;
} ) ;
2020-02-04 16:13:06 +00:00
// Install all default apps in one go
document . getElementById ( "installdefault" ) . addEventListener ( "click" , event => {
2020-02-04 16:30:31 +00:00
var defaultApps , appCount ;
2020-02-04 16:13:06 +00:00
httpGet ( "defaultapps.json" ) . then ( json => {
defaultApps = JSON . parse ( json ) ;
defaultApps = defaultApps . map ( appid => appJSON . find ( app => app . id == appid ) ) ;
if ( defaultApps . some ( x => x === undefined ) )
throw "Not all apps found" ;
2020-02-04 16:30:31 +00:00
appCount = defaultApps . length ;
2020-02-04 16:13:06 +00:00
return showPrompt ( "Install Defaults" , "Remove everything and install default apps?" ) ;
} ) . then ( ( ) => {
return Comms . removeAllApps ( ) ;
} ) . then ( ( ) => {
2020-02-04 16:30:31 +00:00
appsInstalled = [ ] ;
showToast ( ` Existing apps removed. Installing ${ appCount } apps... ` ) ;
2020-02-04 16:13:06 +00:00
return new Promise ( resolve => {
function upload ( ) {
var app = defaultApps . shift ( ) ;
if ( app === undefined ) return resolve ( ) ;
Comms . uploadApp ( app ) . then ( ( appJSON ) => {
if ( appJSON ) appsInstalled . push ( appJSON ) ;
2020-02-04 16:30:31 +00:00
showToast ( ` ( ${ appCount - defaultApps . length } / ${ appCount } ) ${ app . name } Uploaded ` ) ;
2020-02-04 16:13:06 +00:00
upload ( ) ;
} ) ;
}
upload ( ) ;
} ) ;
} ) . then ( ( ) => {
showToast ( "Default apps successfully installed!" , "success" ) ;
2020-02-04 16:30:31 +00:00
return getInstalledApps ( ) ;
2020-02-04 16:13:06 +00:00
} ) . catch ( err => {
showToast ( "App Install failed, " + err , "error" ) ;
} ) ;
} ) ;