Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
<title translate="TITLE"></title>
<link rel="icon" type="image/png" href="images/external_icon.png">
<link rel="stylesheet" href="libs/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="libs/cropperjs/cropper.min.css">
<link rel="stylesheet" href="index.css">
<script src="libs/jquery/jquery.min.js"></script>
<script src="libs/angularjs/angular.min.js"></script>
Expand All @@ -47,6 +48,13 @@ <h4 class="d-flex justify-content-between align-items-center mb-3">
</h4>
<ul class="list-group mb-3">

<li class="list-group-item d-flex justify-content-between lh-condensed" ng-if="wallpaper.imagesrc != null">
<div class="my-auto">
<h6 class="my-0"><img ng-src="{{wallpaper.imagesrc}}" alt="" width="40" height="28" class="mr-3">{{wallpaper.name}}</h6>
</div>
<span><button class="btn btn-primary btn-sm" ng-click="removeWallpaper()" translate="REMOVE"></button></span>
</li>

<li class="list-group-item d-flex justify-content-between lh-condensed" ng-repeat="app in selectedApps">
<div class="my-auto">
<h6 class="my-0"><img ng-src="apps/{{app.name}}/icon.png" alt="" width="26" height="26" class="mr-3">{{app.name}}</h6>
Expand Down Expand Up @@ -87,6 +95,15 @@ <h6 class="my-0">{{file.name}}</h6>
</div>

<div class="col-md-8 order-md-1">
<h4 class="mb-3" translate="WALLPAPER"></h4>
<div class="card p-2 mb-3">
<div>
<div class="custom-file">
<input id="wallpaper-file-input" type="file" accept="image" class="custom-file-input" lang="{{locale}}" ng-wallpaper-select>
<label class="custom-file-label" id="wallpaper-name" translate="WALLPAPER_FILE"></label>
</div>
</div>
</div>
<h4 class="mb-3" translate="AVAILABLE_APPLICATIONS"></h4>
<div class="row pb-3">
<div class="col-md-12">
Expand Down Expand Up @@ -129,13 +146,35 @@ <h5 class="card-title">{{app.name}}<!--<span class="text-muted float-right">{{ap
</div>
</div>

<div class="modal" id="imageModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog-lg m-5" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">{{ 'CROP_IMAGE_TITLE' | translate }}</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<div id="cropperDiv">
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">{{ 'CROP_IMAGE_CANCEL' | translate }}</button>
<button type="button" class="btn btn-primary" ng-click="saveCroppedWallpaper()">{{ 'CROP_IMAGE_SAVE' | translate }}</button>
</div>
</div>
</div>
</div>

<footer class="my-5 pt-5 text-muted text-center text-small">
<p class="mb-1" translate="ACKNOWLEDGMENTS"></p>
<ul class="list-inline">
<li class="list-inline-item"><a href="https://www.numworks.com/">NumWorks</a></li>
<li class="list-inline-item"><a href="https://github.com/devanlai/webdfu">webdfu</a></li>
<li class="list-inline-item"><a href="https://www.gnu.org/software/binutils/">GNU Binutils</a></li>
<li class="list-inline-item"><a href="https://emscripten.org/">emscripten</a></li>
<li class="list-inline-item"><a href="https://fengyuanchen.github.io/cropperjs/">cropperjs</a></li>
</ul>
</footer>
</div>
Expand All @@ -146,9 +185,11 @@ <h5 class="card-title">{{app.name}}<!--<span class="text-muted float-right">{{ap
<script src="libs/webdfu/dfu-util/dfuse.js"></script>
<script src="libs/angularjs/angular-sanitize.min.js"></script>
<script src="libs/angular-translate/angular-translate.min.js"></script>
<script src="libs/bootstrap/js/bootstrap.min.js"></script>
<script src="libs/lz4js/util.js"></script>
<script src="libs/lz4js/xxh32.js"></script>
<script src="libs/lz4js/lz4.js"></script>
<script src="libs/cropperjs/cropper.min.js"></script>
<script src="index.js"></script>
<script src="apps/apps.js"></script>
</body>
Expand Down
144 changes: 141 additions & 3 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ Copyright (C) 2019 Damien Nicolet
angular.module('nwas', ['ngSanitize', 'pascalprecht.translate']).controller('main', function($scope, $http, apps, $translate) {

$scope.locale = $translate.use();
$scope.wallpaper = null;
$scope.apps = apps;
$scope.selectedApps = [];
$scope.customFiles = [];
Expand All @@ -35,6 +36,63 @@ angular.module('nwas', ['ngSanitize', 'pascalprecht.translate']).controller('mai
}
};

$scope.setWallpaper = function setWallpaper(el) {
let file = el[0].files[0];
el.value = null;
let reader = new FileReader();

reader.addEventListener("load", function() {
let img = document.createElement('img');
img.onload = function () {
$scope.$apply(function () {
let cropperDiv = document.getElementById("cropperDiv");
cropperDiv.innerText = "";
cropperDiv.appendChild(img);
$('#imageModal').modal('show');
img.style = "max-width: 100%;";

$scope.wallpaper = {
name: file.name,
cropper: new Cropper(img, {
aspectRatio: 320 / 222,
viewMode: 1
})
};
});
};
img.src = reader.result;
}, false);

if (file) {
reader.readAsDataURL(file);
}
};

$scope.saveCroppedWallpaper = function saveCroppedWallpaper() {
// Resize image
var canvas = document.createElement('canvas'),
ctx = canvas.getContext('2d');
canvas.width = 320;
canvas.height = 222;

ctx.drawImage($scope.wallpaper.cropper.getCroppedCanvas(), 0, 0, 320, 222);

$scope.wallpaper = {
name: $scope.wallpaper.name,
imagesrc: canvas.toDataURL("image/png")
};
document.getElementById("wallpaper-name").innerText = $scope.wallpaper.name;
$('#imageModal').modal('hide');
}

$scope.removeWallpaper = function removeWallpaper() {
$scope.wallpaper = null;
document.getElementById("wallpaper-file-input").value = null;
$translate("WALLPAPER_FILE").then(function (translatedValue) {
document.getElementById("wallpaper-name").innerText = translatedValue;
});
};

$scope.removeApplication = function removeApplication(app) {
let index = $scope.selectedApps.indexOf(app);
if(index >= 0) {
Expand Down Expand Up @@ -127,8 +185,56 @@ angular.module('nwas', ['ngSanitize', 'pascalprecht.translate']).controller('mai
return compressed;
}
*/
let buildArchive = async function buildArchive(applications, files) {
if(applications.length == 0 && files.length == 0) {
let fromPNGToOBM = function fromPNGToOBM(dataURL) {
//OBM (Omega Bit Map) is the wallpaper format of Omega
let img = new Image();
img.src = dataURL;

let canvas = document.createElement('canvas');

canvas.width = img.width;
canvas.height = img.height;

let img_header32 = new Uint32Array(3);
img_header32[0] = 466512775; //We use a "random" magic number
img_header32[1] = canvas.width;
img_header32[2] = canvas.height;

let context = canvas.getContext('2d');
context.drawImage(img, 0, 0);
let imgd = context.getImageData(0, 0, img.width, img.height);

let img_rgba32 = new Uint32Array(imgd.data.buffer);
let img_rgba8888 = new Uint8Array(imgd.data.buffer);
let img_rgb565 = new Uint16Array(img_rgba32.length);
for(let i = 0; i < img_rgba32.length; i++) {
let r = img_rgba8888[i * 4 + 0] / 255;
let g = img_rgba8888[i * 4 + 1] / 255;
let b = img_rgba8888[i * 4 + 2] / 255;
let a = img_rgba8888[i * 4 + 3] / 255;

let br = r * a + 1 * (1 - a);
let bg = g * a + 1 * (1 - a);
let bb = b * a + 1 * (1 - a);

let ir = Math.round(br * 0xFF);
let ig = Math.round(bg * 0xFF);
let ib = Math.round(bb * 0xFF);

img_rgb565[i] = (ir >> 3) << 11 | (ig >> 2) << 5 | (ib >> 3);
}


let img_header8 = new Uint8Array(img_header32.buffer, img_header32.byteOffset, img_header32.byteLength);
let img_data = new Uint8Array(img_rgb565.buffer, img_rgb565.byteOffset, img_rgb565.byteLength);

let final_data = Uint8Array.from([...img_header8, ...img_data]);

return final_data;
}

let buildArchive = async function buildArchive(applications, wallpaper, files) {
if(applications.length == 0 && files.length == 0 && wallpaper == null) {
return new Promise(function(resolve, reject) {
resolve(new Uint8Array(0x200));
});
Expand Down Expand Up @@ -160,6 +266,16 @@ angular.module('nwas', ['ngSanitize', 'pascalprecht.translate']).controller('mai
}

}
if(wallpaper != null) {
console.log("Inling wallpaper");
$scope.$apply(function() {
$scope.lastAction = $translate.instant("ADDING") + " " + wallpaper.name;
});
files.push({
name: "wallpaper.obm",
binary: fromPNGToOBM(wallpaper.imagesrc)
});
}

for(let i = 0; i < files.length; i++) {
let file = files[i];
Expand Down Expand Up @@ -237,7 +353,7 @@ angular.module('nwas', ['ngSanitize', 'pascalprecht.translate']).controller('mai
$scope.$apply(function() {
$scope.uploading = true;
});
let archive = await buildArchive($scope.selectedApps, $scope.customFiles);
let archive = await buildArchive($scope.selectedApps, $scope.wallpaper, $scope.customFiles);
console.log("Archive", archive);
await uploadFile(selectedDevice, "@External Flash /0x90200000/32*064Kg,64*064Kg", archive, false);
$scope.$apply(function() {
Expand Down Expand Up @@ -329,6 +445,16 @@ angular.module('nwas', ['ngSanitize', 'pascalprecht.translate']).controller('mai
})
}
}

}).directive("ngWallpaperSelect", function() {
return {
link: function($scope, el) {
el.bind("change", function(e) {
$scope.setWallpaper(el);
})
}
}

}).config(function ($translateProvider) {
$translateProvider
.translations('en', {
Expand All @@ -342,6 +468,9 @@ angular.module('nwas', ['ngSanitize', 'pascalprecht.translate']).controller('mai
REMOVE: 'Remove',
CUSTOM_FILE: 'Custom file',
INSTALL: 'Install',
WALLPAPER: "Wallpaper",
WALLPAPER_FILE: 'PNG file of size 320x222',
WALLPAPER_FILE_SIZE_ERROR: 'Error : the file is not the right size.',
AVAILABLE_APPLICATIONS: 'Available applications',
ADD: 'Add',
ACKNOWLEDGMENTS: 'Acknowledgments',
Expand All @@ -355,6 +484,9 @@ angular.module('nwas', ['ngSanitize', 'pascalprecht.translate']).controller('mai
DFU_WROTE: "Done",
OR: "or",
CHECK_ICONS: "Enable experimental icons support.",
CROP_IMAGE_TITLE: "Crop wallpaper",
CROP_IMAGE_SAVE: "Save",
CROP_IMAGE_CANCEL: "Cancel",
})
.translations('fr', {
TITLE: 'Dépôt d\'application N110 non officiel',
Expand All @@ -367,6 +499,9 @@ angular.module('nwas', ['ngSanitize', 'pascalprecht.translate']).controller('mai
REMOVE: 'Supprimer',
CUSTOM_FILE: 'Fichier local',
INSTALL: 'Installer',
WALLPAPER: 'Fond d\'écran',
WALLPAPER_FILE: 'Fichier PNG de taille 320x222',
WALLPAPER_FILE_SIZE_ERROR: 'Erreur : le fichier ne fait pas la bonne taile.',
AVAILABLE_APPLICATIONS: 'Applications disponibles',
ADD: 'Ajouter',
ACKNOWLEDGMENTS: 'Remerciements',
Expand All @@ -380,6 +515,9 @@ angular.module('nwas', ['ngSanitize', 'pascalprecht.translate']).controller('mai
DFU_WROTE: "Terminé",
OR: "ou",
CHECK_ICONS: "Activer le support des icons (Expérimental)",
CROP_IMAGE_TITLE: "Recadrer le fond d'écran",
CROP_IMAGE_SAVE: "Sauvegarder",
CROP_IMAGE_CANCEL: "Annuler",
})
.registerAvailableLanguageKeys(['en', 'fr'], {
'en_*': 'en',
Expand Down
Loading