@@ -320,7 +320,7 @@ function handleCustomApp(appTemplate) {
320
320
if ( ! appTemplate . custom ) throw new Error ( "App doesn't have custom HTML" ) ;
321
321
// if it needs a connection, do that first
322
322
if ( appTemplate . customConnect && ! device . connected )
323
- return getInstalledApps ( ) . then ( ( ) => handleCustomApp ( appTemplate ) ) ;
323
+ return getDeviceInfo ( ) . then ( ( ) => handleCustomApp ( appTemplate ) ) ;
324
324
// otherwise continue
325
325
return new Promise ( ( resolve , reject ) => {
326
326
let modal = htmlElement ( `<div class="modal active">
@@ -358,7 +358,7 @@ function handleCustomApp(appTemplate) {
358
358
console . log ( "Received custom app" , app ) ;
359
359
modal . remove ( ) ;
360
360
361
- getInstalledApps ( )
361
+ getDeviceInfo ( )
362
362
. then ( ( ) => checkDependencies ( app ) )
363
363
. then ( ( ) => Comms . uploadApp ( app , { device :device , language :LANGUAGE , noFinish : msg . options && msg . options . noFinish } ) )
364
364
. then ( ( ) => {
@@ -745,7 +745,7 @@ function showScreenshots(appId) {
745
745
// =========================================== My Apps
746
746
747
747
function uploadApp ( app ) {
748
- return getInstalledApps ( ) . then ( ( ) => {
748
+ return getDeviceInfo ( ) . then ( ( ) => {
749
749
if ( device . appsInstalled . some ( i => i . id === app . id ) ) {
750
750
return updateApp ( app ) ;
751
751
}
@@ -774,7 +774,7 @@ function uploadApp(app) {
774
774
775
775
function removeApp ( app ) {
776
776
return showPrompt ( "Delete" , "Really remove '" + app . name + "'?" ) . then ( ( ) => {
777
- return getInstalledApps ( ) . then ( ( ) => {
777
+ return getDeviceInfo ( ) . then ( ( ) => {
778
778
// a = from appid.info, app = from apps.json
779
779
return Comms . removeApp ( device . appsInstalled . find ( a => a . id === app . id ) ) ;
780
780
} ) ;
@@ -983,7 +983,7 @@ function refreshMyApps() {
983
983
}
984
984
985
985
let haveInstalledApps = false ;
986
- function getInstalledApps ( refresh ) {
986
+ function getDeviceInfo ( refresh ) {
987
987
if ( haveInstalledApps && ! refresh ) {
988
988
return Promise . resolve ( device . appsInstalled ) ;
989
989
}
@@ -995,6 +995,7 @@ function getInstalledApps(refresh) {
995
995
device . id = info . id ;
996
996
device . version = info . version ;
997
997
device . exptr = info . exptr ;
998
+ device . storageStats = info . storageStats ;
998
999
device . appsInstalled = info . apps ;
999
1000
haveInstalledApps = true ;
1000
1001
if ( "function" == typeof onFoundDeviceInfo )
@@ -1016,11 +1017,39 @@ function getInstalledApps(refresh) {
1016
1017
const deviceInfoElem = document . getElementById ( "more-deviceinfo" ) ;
1017
1018
if ( deviceInfoElem ) {
1018
1019
deviceInfoElem . style . display = "inherit" ;
1020
+ let storageRow = "" ;
1021
+ if ( device . storageStats ?. totalBytes ) {
1022
+ const stats = device . storageStats ;
1023
+ const totalKB = ( stats . totalBytes / 1000 ) . toFixed ( 2 ) ;
1024
+ const usedKB = ( stats . fileBytes / 1000 ) . toFixed ( 2 ) ;
1025
+ const trashKB = ( stats . trashBytes / 1000 ) . toFixed ( 2 ) ;
1026
+ const freeKB = ( stats . freeBytes / 1000 ) . toFixed ( 2 ) ;
1027
+ const bytePrc = 100 / stats . totalBytes ;
1028
+ const usedPrc = bytePrc * stats . fileBytes ;
1029
+ const trashPrc = bytePrc * stats . trashBytes ;
1030
+ const freePrc = bytePrc * stats . freeBytes ;
1031
+ if ( isNaN ( usedPrc ) || isNaN ( trashPrc ) || isNaN ( freePrc ) ) {
1032
+ console . error ( "Unexpected error: Could not calculate storage statistics" ) ;
1033
+ } else {
1034
+ storageRow = `
1035
+ <tr><td><b>Storage</b></td><td>
1036
+ <p style="margin-bottom:.4rem;">${ totalKB } KiB in total, ${ stats . fileCount } files used, ${ stats . trashCount } files trashed.</p>
1037
+ <div class="bar" style="margin-bottom:.3rem;">
1038
+ <!-- These styles prevent overflow of text if the bar item is too small to fit all the text -->
1039
+ <style>.bar-item{white-space:nowrap;padding-left:.1rem;padding-right:.1rem;}</style>
1040
+ <div class="bar-item tooltip bg-error" data-tooltip="${ usedKB } KiB, ${ usedPrc . toFixed ( 2 ) } % used" style="width:${ usedPrc } %; color:hsl(218 16% 2%)">${ usedPrc . toFixed ( 0 ) } % used</div>
1041
+ <div class="bar-item tooltip bg-warning" data-tooltip="${ trashKB } KiB, ${ trashPrc . toFixed ( 2 ) } % trash" style="width:${ trashPrc } %;color:hsl(218 16% 7%)">${ trashPrc . toFixed ( 0 ) } % trash</div>
1042
+ <div class="bar-item tooltip bg-success" data-tooltip="${ freeKB } KiB, ${ freePrc . toFixed ( 2 ) } % free" style="width:${ freePrc } %; color:hsl(218 16% 7%)">${ freePrc . toFixed ( 0 ) } % free</div>
1043
+ </div>
1044
+ </td></tr>` ;
1045
+ }
1046
+ }
1019
1047
const deviceInfoContentElem = document . getElementById ( "more-deviceinfo-content" ) ;
1020
1048
deviceInfoContentElem . innerHTML = `
1021
1049
<table class="table"><tbody>
1022
1050
<tr><td><b>Device Type</b></td><td>${ device . id } </td></tr>
1023
1051
<tr><td><b>Firmware Version</b></td><td>${ device . version } </td></tr>
1052
+ ${ storageRow }
1024
1053
<tr><td><b>Apps Installed</b></td><td>${ ( device . appsInstalled || [ ] ) . map ( a => `${ a . id } (${ a . version } )` ) . join ( ", " ) } </td></tr>
1025
1054
</tbody></table>` ;
1026
1055
}
@@ -1064,7 +1093,7 @@ function installMultipleApps(appIds, promptName) {
1064
1093
) . then ( ( ) => Comms . showUploadFinished ( )
1065
1094
) . then ( ( ) => {
1066
1095
showToast ( "Apps successfully installed!" , "success" ) ;
1067
- return getInstalledApps ( true ) ;
1096
+ return getDeviceInfo ( true ) ;
1068
1097
} ) ;
1069
1098
}
1070
1099
@@ -1110,7 +1139,7 @@ function handleConnectionChange(connected) {
1110
1139
}
1111
1140
1112
1141
htmlToArray ( document . querySelectorAll ( ".btn.refresh" ) ) . map ( button => button . addEventListener ( "click" , ( ) => {
1113
- getInstalledApps ( true ) . catch ( err => {
1142
+ getDeviceInfo ( true ) . catch ( err => {
1114
1143
showToast ( "Getting app list failed, " + err , "error" ) ;
1115
1144
} ) ;
1116
1145
} ) ) ;
@@ -1123,7 +1152,7 @@ connectMyDeviceBtn.addEventListener("click", () => {
1123
1152
const deviceInfoElem = document . getElementById ( "more-deviceinfo" ) ;
1124
1153
if ( deviceInfoElem ) deviceInfoElem . style . display = "none" ;
1125
1154
} else {
1126
- getInstalledApps ( true ) . catch ( err => {
1155
+ getDeviceInfo ( true ) . catch ( err => {
1127
1156
showToast ( "Device connection failed, " + err , "error" ) ;
1128
1157
Comms . disconnectDevice ( ) ;
1129
1158
} ) ;
@@ -1243,7 +1272,7 @@ if (btn) btn.addEventListener("click",event=>{
1243
1272
Progress . hide ( { sticky :true } ) ;
1244
1273
device . appsInstalled = [ ] ;
1245
1274
showToast ( "All apps removed" , "success" ) ;
1246
- return getInstalledApps ( true ) ;
1275
+ return getDeviceInfo ( true ) ;
1247
1276
} ) . catch ( err => {
1248
1277
Progress . hide ( { sticky :true } ) ;
1249
1278
showToast ( "App removal failed, " + err , "error" ) ;
@@ -1279,7 +1308,7 @@ if (btn) btn.addEventListener("click", event => {
1279
1308
1280
1309
btn = document . getElementById ( "screenshot" ) ;
1281
1310
if ( btn ) btn . addEventListener ( "click" , event => {
1282
- getInstalledApps ( false ) . then ( ( ) => {
1311
+ getDeviceInfo ( false ) . then ( ( ) => {
1283
1312
if ( device . id == "BANGLEJS" ) {
1284
1313
showPrompt ( "Screenshot" , "Screenshots are not supported on Bangle.js 1" , { ok :1 } ) ;
1285
1314
} else {
0 commit comments