BangleApps/apps/imageclock/custom.html

283 lines
10 KiB
HTML

<html>
<head>
<link rel="stylesheet" href="../../css/spectre.min.css">
</head>
<body>
<script src="../../core/lib/heatshrink.js"></script>
<script src="../../core/lib/imageconverter.js"></script>
<script src="../../core/lib/customize.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.7.1/jszip.js"></script>
<h4>Upload watchface:</h4>
<p>Select watchface folder:</br><input type="file" id="fileLoader" name="files[]" multiple directory="" webkitdirectory="" moxdirectory="" /></p>
<p><b>or</b></p>
<p>Select watchface zip file: </br><input type="file" id="zipLoader" name="zip"/></p><br/>
<button id="btnUpload" class="btn btn-primary">Upload to watch</button>
<button id="btnSave" class="btn btn-secondary">Save resources file</button></br>
<canvas id="canvas" style="display:none;"></canvas></br>
<script>
var result = "";
var resultJson = {};
var infoJson;
var faceJson;
var handledFiles = 0;
var expectedFiles = 0;
function imageLoaded() {
var options = {};
options.diffusion = infoJson.diffusion ? infoJson.diffusion : "none";
options.compression = false;
options.alphaToColor = false;
options.transparent = false;
options.inverted = false;
options.autoCrop = false;
options.brightness = 0;
options.contrast = 0;
options.mode = infoJson.color ? infoJson.color : "1bit";
options.output = "jsonobject";
var faceJson;
console.log("Loaded image has path", this.path);
var jsonPath = this.path.split("/");
var forcedTransparentColorMatch = jsonPath[jsonPath.length-1].match(/.*\.t([^.]+)\..*/)
var forcedTransparentColor;
if (jsonPath[jsonPath.length-1].includes(".t.")){
options.transparent = true;
} else if (forcedTransparentColorMatch){
options.transparent = false;
forcedTransparentColor = forcedTransparentColorMatch[1];
}
console.log("image has transparency", options.transparent);
console.log("image has forced transparent color", forcedTransparentColor);
jsonPath[jsonPath.length-1] = jsonPath[jsonPath.length-1].replace(/([^.]*)\..*/, "$1");
console.log("Loaded image has json path", jsonPath);
var canvas = document.getElementById("canvas")
canvas.width = this.width*2;
canvas.height = this.height;
var ctx = canvas.getContext("2d");
ctx.drawImage(this,0,0);
var imgstr = "";
var imageData = ctx.getImageData(0, 0, this.width, this.height);
ctx.fillStyle = 'white';
ctx.fillRect(options.width, 0, this.width, this.height);
var rgba = imageData.data;
options.rgbaOut = rgba;
options.width = this.width;
options.height = this.height;
console.log("options", options);
imgstr = imageconverter.RGBAtoString(rgba, options);
var outputImageData = new ImageData(options.rgbaOut, options.width, options.height);
ctx.putImageData(outputImageData,this.width,0);
// checkerboard for transparency on original image
var imageData = ctx.getImageData(0, 0, this.width, this.height);
imageconverter.RGBAtoCheckerboard(imageData.data, {width:this.width,height:this.height});
ctx.putImageData(imageData,0,0);
var currentElement = resultJson;
for (var i = 0; i < jsonPath.length; i++){
if (i == jsonPath.length - 1){
var resultingObject = JSON.parse(imgstr);
if (forcedTransparentColor !== undefined) resultingObject.transparent = forcedTransparentColor;
currentElement[jsonPath[i]] = resultingObject;
console.log("result is ", resultingObject);
} else {
if (!currentElement[jsonPath[i]]) currentElement[jsonPath[i]] = {};
currentElement = currentElement[jsonPath[i]];
}
}
handledFiles++;
console.log("Expected:", expectedFiles, " handled:", handledFiles);
if (handledFiles == expectedFiles){
document.getElementById('btnSave').disabled = false;
document.getElementById('btnUpload').disabled = false;
}
}
function handleWatchFace(infoFile, faceFile, resourceFiles){
var reader = new FileReader();
reader.path = infoFile.webkitRelativePath;
reader.onload = function(event) {
infoJson = JSON.parse(reader.result);
handleFaceJson(faceFile, resourceFiles);
};
reader.readAsText(infoFile);
}
function handleFaceJson(faceFile, resourceFiles){
var reader = new FileReader();
reader.path = faceFile.webkitRelativePath;
reader.onload = function(event) {
faceJson = JSON.parse(reader.result);
handleResourceFiles(resourceFiles);
};
reader.readAsText(faceFile);
}
function handleResourceFiles(files){
for (var current of files){
console.log('Handle resource file ', current);
var reader = new FileReader();
console.log("Handling ", current.name, " with path ", current.webkitRelativePath);
var filteredPath = current.webkitRelativePath.replace(/.*\/resources\//,"")
reader.path = filteredPath;
reader.onload = function(event) {
var img = new Image();
img.path = this.path;
img.onload = imageLoaded;
img.src = event.target.result;
};
reader.readAsDataURL(current);
}
}
function handleFileSelect(event) {
handledFiles = 0;
expectedFiles = undefined;
document.getElementById('btnSave').disabled = true;
document.getElementById('btnUpload').disabled = true;
console.log("File select event", event);
if (event.target.files.length == 0) return;
result = "";
resultJson= {};
var resourceFiles = [];
var faceFile;
var infoFile;
for (var current of event.target.files){
console.log('Handle file ', current);
if (current.webkitRelativePath.split("/")[1].startsWith("resources")){
console.log('Found resource file', current.name);
resourceFiles.push(current);
expectedFiles = resourceFiles.length;
} else if (current.name == "face.json"){
console.log('Found face file', current.name);
faceFile = current;
} else if (current.name == "info.json"){
console.log('Found info file', current.name);
infoFile = current;
} else {
console.log('Found unsupported file', current.name);
}
}
handleWatchFace(infoFile, faceFile, resourceFiles);
};
document.getElementById('fileLoader').addEventListener('change', handleFileSelect, false);
document.getElementById("btnSave").addEventListener("click", function() {
var h = document.createElement('a');
h.href = 'data:text/json;charset=utf-8,' + encodeURI(JSON.stringify(resultJson));
h.target = '_blank';
h.download = "imageclock.resources.json";
h.click();
});
document.getElementById("btnUpload").addEventListener("click", function() {
var appDef = {
id : "imageclock",
storage:[
{name:"imageclock.app.js", url:"app.js"},
{name:"imageclock.face.json", content: JSON.stringify(faceJson)},
{name:"imageclock.resources.json", content: JSON.stringify(resultJson)},
{name:"imageclock.img", url:"app-icon.js", evaluate:true},
]
};
sendCustomizedApp(appDef);
});
function handleZipSelect(evt) {
function handleFile(f) {
expectedFiles = 0;
handledFiles = 0;
document.getElementById('btnSave').disabled = true;
document.getElementById('btnUpload').disabled = true;
JSZip.loadAsync(f).then(function(zip) {
console.log("Zip loaded", zip);
result = "";
resultJson= {};
var resourceFiles = [];
var promise = zip.file("face.json").async("string").then((data)=>{
console.log("face.json data", data);
faceJson = JSON.parse(data);
});
promise = promise.then(zip.file("info.json").async("string").then((data)=>{
console.log("info.json data", data);
infoJson = JSON.parse(data);
}));
zip.folder("resources").forEach(function (relativePath, file){
console.log("iterating over", relativePath);
if (!file.dir){
expectedFiles++;
promise = promise.then(file.async("blob").then(function (blob) {
var reader = new FileReader();
console.log("Handling ", file.name, " with path ", relativePath);
reader.path = relativePath;
reader.onload = function(event) {
var img = new Image();
img.path = this.path;
img.onload = imageLoaded;
img.src = event.target.result;
};
reader.readAsDataURL(blob);
}));
}
});
}, function (e) {
console.log("Error reading " + f.name + ": " + e.message);
});
}
console.log("Zip select event", evt);
var files = evt.target.files;
if (files.length > 1){
alert("Only one file allowed");
}
handleFile(files[0]);
}
document.getElementById('zipLoader').addEventListener('change', handleZipSelect, false);
document.getElementById('btnSave').disabled = true;
document.getElementById('btnUpload').disabled = true;
</script>
</body>
</html>