Merge pull request #3931 from RKBoss6/StoragwAnalyser

[Storage Analyser] Add pie charts
master
Gordon Williams 2025-07-21 09:52:28 +02:00 committed by GitHub
commit 1fae42ff84
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 139 additions and 57 deletions

View File

@ -1 +1,2 @@
0.01: New App! 0.01: New App!
0.02: Added pie chart for visualization, tweaked UI.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -3,41 +3,67 @@
<link rel="stylesheet" href="../../css/spectre.min.css"> <link rel="stylesheet" href="../../css/spectre.min.css">
</head> </head>
<body> <body>
<script src="../../core/lib/customize.js"></script> <script src="../../core/lib/customize.js"></script>
<div id="storageInfo"></div> <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<!-- Toggle Buttons -->
<div class="btn-group" style="margin: 1em; display: flex; justify-content: center;">
<button id="tableButton" class="btn btn-primary">View Table</button>
<button id="pieChartButton" class="btn">View Pie Chart</button>
</div>
<!-- Table View -->
<div id="storageTable"></div>
<!-- Chart View -->
<div id="storagePieChart" style="display: none; flex-direction: column; align-items: center;">
<div id="piechart" style="width: 100%; max-width: 600px; height: 400px;"></div>
<div id="totalStoragePie" style="width: 100%; max-width: 600px; height: 300px;"></div>
</div>
<script> <script>
// Called when we know what device we're using let globalApps = [];
let storageStats = null;
function onInit(device) { function onInit(device) {
Util.showModal("Reading Storage..."); Util.showModal("Reading Storage...");
Puck.eval(`require("Storage").list(/\\.info$/).map(appInfoName => { Puck.eval(`(()=>{
let getApps = () => require("Storage").list(/\\.info$/).map(appInfoName => {
let appInfo = require("Storage").readJSON(appInfoName,1)||{}; let appInfo = require("Storage").readJSON(appInfoName,1)||{};
//print(appInfoName, appInfo);
var fileSize = 0, dataSize = 0; var fileSize = 0, dataSize = 0;
appInfo.files.split(",").forEach(f => fileSize += require("Storage").read(f).length); appInfo.files.split(",").forEach(f => fileSize += require("Storage").read(f).length);
var data = (appInfo.data||"").split(";"); var data = (appInfo.data||"").split(";");
function wildcardToRegexp(wc) { function wildcardToRegexp(wc) {
return new RegExp("^"+wc.replaceAll(".","\\\\.").replaceAll("?",".*")+"$"); return new RegExp("^"+wc.replaceAll(".","\\\\.").replaceAll("?",".*")+"$");
} }
// normal files
if (data[0]) data[0].split(",").forEach(wc => { if (data[0]) data[0].split(",").forEach(wc => {
require("Storage").list(wildcardToRegexp(wc), {sf:false}).forEach(f => { require("Storage").list(wildcardToRegexp(wc), {sf:false}).forEach(f => {
dataSize += require("Storage").read(f).length dataSize += require("Storage").read(f).length
}); });
}); });
// storage files
if (data[1]) data[1].split(",").forEach(wc => { if (data[1]) data[1].split(",").forEach(wc => {
require("Storage").list(wildcardToRegexp(wc), {sf:true}).forEach(f => { require("Storage").list(wildcardToRegexp(wc), {sf:true}).forEach(f => {
dataSize += require("Storage").open(f,"r").getLength(); dataSize += require("Storage").open(f,"r").getLength();
}); });
}); });
return [appInfo.id, fileSize, dataSize]; return [appInfo.id, fileSize, dataSize];
})`, function(apps) { });
apps.sort((a,b) => (b[1]+b[2]) - (a[1]+a[2])); return [getApps(), require(\"Storage\").getStats()]; })()`, function(result) {
Util.hideModal(); Util.hideModal();
console.log(apps); globalApps = result[0].sort((a,b) => (b[1]+b[2]) - (a[1]+a[2]));
document.getElementById("storageInfo").innerHTML = ` storageStats = result[1];
if (globalApps.length === 0) {
document.getElementById("storageTable").innerHTML = "<p>No apps found</p>";
return;
}
drawTable();
});
}
function drawTable() {
document.getElementById("storageTable").innerHTML = `
<table class="table table-striped"> <table class="table table-striped">
<thead> <thead>
<tr> <tr>
@ -48,7 +74,7 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
${apps.map(app => ` ${globalApps.map(app => `
<tr> <tr>
<td>${app[0]}</td> <td>${app[0]}</td>
<td>${(app[1]/1000).toFixed(1)}</td> <td>${(app[1]/1000).toFixed(1)}</td>
@ -57,12 +83,67 @@
</tr>`).join("")} </tr>`).join("")}
</tbody> </tbody>
</table>`; </table>`;
if (apps.length === 0) {
document.getElementById("storageInfo").innerHTML = "<p>No apps found</p>";
}
});
} }
function drawChart() {
if (globalApps.length === 0) return;
// App-specific chart
const chartData = [
['App', 'Total Size (KB)']
].concat(globalApps.map(app => [app[0], (app[1] + app[2])/1000]));
const data = google.visualization.arrayToDataTable(chartData);
const options = {
title: 'App Storage Breakdown',
chartArea: { width: '90%', height: '80%' },
legend: { position: 'bottom' }
};
const chart = new google.visualization.PieChart(document.getElementById('piechart'));
chart.draw(data, options);
// Total storage chart
if (storageStats) {
const usedKB = storageStats.usedBytes / 1000;
const freeKB = storageStats.freeBytes / 1000;
const totalData = google.visualization.arrayToDataTable([
['Type', 'KB'],
['Used', usedKB],
['Free', freeKB]
]);
const totalOptions = {
title: 'Total Storage Usage',
pieHole: 0.4,
chartArea: { width: '90%', height: '80%' },
legend: { position: 'bottom' }
};
const totalChart = new google.visualization.PieChart(document.getElementById('totalStoragePie'));
totalChart.draw(totalData, totalOptions);
}
}
google.charts.load('current', {'packages':['corechart']});
document.getElementById("pieChartButton").addEventListener("click", function () {
document.getElementById("storageTable").style.display = "none";
document.getElementById("storagePieChart").style.display = "flex";
drawChart();
this.classList.add("btn-primary");
document.getElementById("tableButton").classList.remove("btn-primary");
});
document.getElementById("tableButton").addEventListener("click", function () {
document.getElementById("storageTable").style.display = "block";
document.getElementById("storagePieChart").style.display = "none";
drawTable();
this.classList.add("btn-primary");
document.getElementById("pieChartButton").classList.remove("btn-primary");
});
</script> </script>
</body> </body>

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View File

@ -1,9 +1,9 @@
{ {
"id": "storageanalyzer", "id": "storageanalyzer",
"name": "Storage Analyzer", "name": "Storage Analyzer",
"version": "0.01", "version": "0.02",
"description": "Analyses Bangle.js storage and shows which apps are using it", "description": "Analyzes Bangle.js storage and shows which apps are using storage space",
"icon": "app.png", "icon": "icon.png",
"type": "RAM", "type": "RAM",
"tags": "tool,storage,flash,memory", "tags": "tool,storage,flash,memory",
"supports": ["BANGLEJS","BANGLEJS2"], "supports": ["BANGLEJS","BANGLEJS2"],