Skip to content

Commit dafe15e

Browse files
Merge pull request #14 from Yaya-Cout/omega-wallpaper
Omega wallpaper
2 parents cd7476e + d85fa70 commit dafe15e

File tree

8 files changed

+11384
-3
lines changed

8 files changed

+11384
-3
lines changed

index.html

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
<title translate="TITLE"></title>
2222
<link rel="icon" type="image/png" href="images/external_icon.png">
2323
<link rel="stylesheet" href="libs/bootstrap/css/bootstrap.min.css">
24+
<link rel="stylesheet" href="libs/cropperjs/cropper.min.css">
2425
<link rel="stylesheet" href="index.css">
2526
<script src="libs/jquery/jquery.min.js"></script>
2627
<script src="libs/angularjs/angular.min.js"></script>
@@ -47,6 +48,13 @@ <h4 class="d-flex justify-content-between align-items-center mb-3">
4748
</h4>
4849
<ul class="list-group mb-3">
4950

51+
<li class="list-group-item d-flex justify-content-between lh-condensed" ng-if="wallpaper.imagesrc != null">
52+
<div class="my-auto">
53+
<h6 class="my-0"><img ng-src="{{wallpaper.imagesrc}}" alt="" width="40" height="28" class="mr-3">{{wallpaper.name}}</h6>
54+
</div>
55+
<span><button class="btn btn-primary btn-sm" ng-click="removeWallpaper()" translate="REMOVE"></button></span>
56+
</li>
57+
5058
<li class="list-group-item d-flex justify-content-between lh-condensed" ng-repeat="app in selectedApps">
5159
<div class="my-auto">
5260
<h6 class="my-0"><img ng-src="apps/{{app.name}}/icon.png" alt="" width="26" height="26" class="mr-3">{{app.name}}</h6>
@@ -87,6 +95,15 @@ <h6 class="my-0">{{file.name}}</h6>
8795
</div>
8896

8997
<div class="col-md-8 order-md-1">
98+
<h4 class="mb-3" translate="WALLPAPER"></h4>
99+
<div class="card p-2 mb-3">
100+
<div>
101+
<div class="custom-file">
102+
<input id="wallpaper-file-input" type="file" accept="image" class="custom-file-input" lang="{{locale}}" ng-wallpaper-select>
103+
<label class="custom-file-label" id="wallpaper-name" translate="WALLPAPER_FILE"></label>
104+
</div>
105+
</div>
106+
</div>
90107
<h4 class="mb-3" translate="AVAILABLE_APPLICATIONS"></h4>
91108
<div class="row pb-3">
92109
<div class="col-md-12">
@@ -129,13 +146,35 @@ <h5 class="card-title">{{app.name}}<!--<span class="text-muted float-right">{{ap
129146
</div>
130147
</div>
131148

149+
<div class="modal" id="imageModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
150+
<div class="modal-dialog-lg m-5" role="document">
151+
<div class="modal-content">
152+
<div class="modal-header">
153+
<h5 class="modal-title" id="exampleModalLabel">{{ 'CROP_IMAGE_TITLE' | translate }}</h5>
154+
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
155+
<span aria-hidden="true">&times;</span>
156+
</button>
157+
</div>
158+
<div class="modal-body">
159+
<div id="cropperDiv">
160+
</div>
161+
</div>
162+
<div class="modal-footer">
163+
<button type="button" class="btn btn-secondary" data-dismiss="modal">{{ 'CROP_IMAGE_CANCEL' | translate }}</button>
164+
<button type="button" class="btn btn-primary" ng-click="saveCroppedWallpaper()">{{ 'CROP_IMAGE_SAVE' | translate }}</button>
165+
</div>
166+
</div>
167+
</div>
168+
</div>
169+
132170
<footer class="my-5 pt-5 text-muted text-center text-small">
133171
<p class="mb-1" translate="ACKNOWLEDGMENTS"></p>
134172
<ul class="list-inline">
135173
<li class="list-inline-item"><a href="https://www.numworks.com/">NumWorks</a></li>
136174
<li class="list-inline-item"><a href="https://github.com/devanlai/webdfu">webdfu</a></li>
137175
<li class="list-inline-item"><a href="https://www.gnu.org/software/binutils/">GNU Binutils</a></li>
138176
<li class="list-inline-item"><a href="https://emscripten.org/">emscripten</a></li>
177+
<li class="list-inline-item"><a href="https://fengyuanchen.github.io/cropperjs/">cropperjs</a></li>
139178
</ul>
140179
</footer>
141180
</div>
@@ -146,9 +185,11 @@ <h5 class="card-title">{{app.name}}<!--<span class="text-muted float-right">{{ap
146185
<script src="libs/webdfu/dfu-util/dfuse.js"></script>
147186
<script src="libs/angularjs/angular-sanitize.min.js"></script>
148187
<script src="libs/angular-translate/angular-translate.min.js"></script>
188+
<script src="libs/bootstrap/js/bootstrap.min.js"></script>
149189
<script src="libs/lz4js/util.js"></script>
150190
<script src="libs/lz4js/xxh32.js"></script>
151191
<script src="libs/lz4js/lz4.js"></script>
192+
<script src="libs/cropperjs/cropper.min.js"></script>
152193
<script src="index.js"></script>
153194
<script src="apps/apps.js"></script>
154195
</body>

index.js

Lines changed: 141 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ Copyright (C) 2019 Damien Nicolet
2020
angular.module('nwas', ['ngSanitize', 'pascalprecht.translate']).controller('main', function($scope, $http, apps, $translate) {
2121

2222
$scope.locale = $translate.use();
23+
$scope.wallpaper = null;
2324
$scope.apps = apps;
2425
$scope.selectedApps = [];
2526
$scope.customFiles = [];
@@ -35,6 +36,63 @@ angular.module('nwas', ['ngSanitize', 'pascalprecht.translate']).controller('mai
3536
}
3637
};
3738

39+
$scope.setWallpaper = function setWallpaper(el) {
40+
let file = el[0].files[0];
41+
el.value = null;
42+
let reader = new FileReader();
43+
44+
reader.addEventListener("load", function() {
45+
let img = document.createElement('img');
46+
img.onload = function () {
47+
$scope.$apply(function () {
48+
let cropperDiv = document.getElementById("cropperDiv");
49+
cropperDiv.innerText = "";
50+
cropperDiv.appendChild(img);
51+
$('#imageModal').modal('show');
52+
img.style = "max-width: 100%;";
53+
54+
$scope.wallpaper = {
55+
name: file.name,
56+
cropper: new Cropper(img, {
57+
aspectRatio: 320 / 222,
58+
viewMode: 1
59+
})
60+
};
61+
});
62+
};
63+
img.src = reader.result;
64+
}, false);
65+
66+
if (file) {
67+
reader.readAsDataURL(file);
68+
}
69+
};
70+
71+
$scope.saveCroppedWallpaper = function saveCroppedWallpaper() {
72+
// Resize image
73+
var canvas = document.createElement('canvas'),
74+
ctx = canvas.getContext('2d');
75+
canvas.width = 320;
76+
canvas.height = 222;
77+
78+
ctx.drawImage($scope.wallpaper.cropper.getCroppedCanvas(), 0, 0, 320, 222);
79+
80+
$scope.wallpaper = {
81+
name: $scope.wallpaper.name,
82+
imagesrc: canvas.toDataURL("image/png")
83+
};
84+
document.getElementById("wallpaper-name").innerText = $scope.wallpaper.name;
85+
$('#imageModal').modal('hide');
86+
}
87+
88+
$scope.removeWallpaper = function removeWallpaper() {
89+
$scope.wallpaper = null;
90+
document.getElementById("wallpaper-file-input").value = null;
91+
$translate("WALLPAPER_FILE").then(function (translatedValue) {
92+
document.getElementById("wallpaper-name").innerText = translatedValue;
93+
});
94+
};
95+
3896
$scope.removeApplication = function removeApplication(app) {
3997
let index = $scope.selectedApps.indexOf(app);
4098
if(index >= 0) {
@@ -127,8 +185,56 @@ angular.module('nwas', ['ngSanitize', 'pascalprecht.translate']).controller('mai
127185
return compressed;
128186
}
129187
*/
130-
let buildArchive = async function buildArchive(applications, files) {
131-
if(applications.length == 0 && files.length == 0) {
188+
let fromPNGToOBM = function fromPNGToOBM(dataURL) {
189+
//OBM (Omega Bit Map) is the wallpaper format of Omega
190+
let img = new Image();
191+
img.src = dataURL;
192+
193+
let canvas = document.createElement('canvas');
194+
195+
canvas.width = img.width;
196+
canvas.height = img.height;
197+
198+
let img_header32 = new Uint32Array(3);
199+
img_header32[0] = 466512775; //We use a "random" magic number
200+
img_header32[1] = canvas.width;
201+
img_header32[2] = canvas.height;
202+
203+
let context = canvas.getContext('2d');
204+
context.drawImage(img, 0, 0);
205+
let imgd = context.getImageData(0, 0, img.width, img.height);
206+
207+
let img_rgba32 = new Uint32Array(imgd.data.buffer);
208+
let img_rgba8888 = new Uint8Array(imgd.data.buffer);
209+
let img_rgb565 = new Uint16Array(img_rgba32.length);
210+
for(let i = 0; i < img_rgba32.length; i++) {
211+
let r = img_rgba8888[i * 4 + 0] / 255;
212+
let g = img_rgba8888[i * 4 + 1] / 255;
213+
let b = img_rgba8888[i * 4 + 2] / 255;
214+
let a = img_rgba8888[i * 4 + 3] / 255;
215+
216+
let br = r * a + 1 * (1 - a);
217+
let bg = g * a + 1 * (1 - a);
218+
let bb = b * a + 1 * (1 - a);
219+
220+
let ir = Math.round(br * 0xFF);
221+
let ig = Math.round(bg * 0xFF);
222+
let ib = Math.round(bb * 0xFF);
223+
224+
img_rgb565[i] = (ir >> 3) << 11 | (ig >> 2) << 5 | (ib >> 3);
225+
}
226+
227+
228+
let img_header8 = new Uint8Array(img_header32.buffer, img_header32.byteOffset, img_header32.byteLength);
229+
let img_data = new Uint8Array(img_rgb565.buffer, img_rgb565.byteOffset, img_rgb565.byteLength);
230+
231+
let final_data = Uint8Array.from([...img_header8, ...img_data]);
232+
233+
return final_data;
234+
}
235+
236+
let buildArchive = async function buildArchive(applications, wallpaper, files) {
237+
if(applications.length == 0 && files.length == 0 && wallpaper == null) {
132238
return new Promise(function(resolve, reject) {
133239
resolve(new Uint8Array(0x200));
134240
});
@@ -160,6 +266,16 @@ angular.module('nwas', ['ngSanitize', 'pascalprecht.translate']).controller('mai
160266
}
161267

162268
}
269+
if(wallpaper != null) {
270+
console.log("Inling wallpaper");
271+
$scope.$apply(function() {
272+
$scope.lastAction = $translate.instant("ADDING") + " " + wallpaper.name;
273+
});
274+
files.push({
275+
name: "wallpaper.obm",
276+
binary: fromPNGToOBM(wallpaper.imagesrc)
277+
});
278+
}
163279

164280
for(let i = 0; i < files.length; i++) {
165281
let file = files[i];
@@ -237,7 +353,7 @@ angular.module('nwas', ['ngSanitize', 'pascalprecht.translate']).controller('mai
237353
$scope.$apply(function() {
238354
$scope.uploading = true;
239355
});
240-
let archive = await buildArchive($scope.selectedApps, $scope.customFiles);
356+
let archive = await buildArchive($scope.selectedApps, $scope.wallpaper, $scope.customFiles);
241357
console.log("Archive", archive);
242358
await uploadFile(selectedDevice, "@External Flash /0x90200000/32*064Kg,64*064Kg", archive, false);
243359
$scope.$apply(function() {
@@ -329,6 +445,16 @@ angular.module('nwas', ['ngSanitize', 'pascalprecht.translate']).controller('mai
329445
})
330446
}
331447
}
448+
449+
}).directive("ngWallpaperSelect", function() {
450+
return {
451+
link: function($scope, el) {
452+
el.bind("change", function(e) {
453+
$scope.setWallpaper(el);
454+
})
455+
}
456+
}
457+
332458
}).config(function ($translateProvider) {
333459
$translateProvider
334460
.translations('en', {
@@ -342,6 +468,9 @@ angular.module('nwas', ['ngSanitize', 'pascalprecht.translate']).controller('mai
342468
REMOVE: 'Remove',
343469
CUSTOM_FILE: 'Custom file',
344470
INSTALL: 'Install',
471+
WALLPAPER: "Wallpaper",
472+
WALLPAPER_FILE: 'PNG file of size 320x222',
473+
WALLPAPER_FILE_SIZE_ERROR: 'Error : the file is not the right size.',
345474
AVAILABLE_APPLICATIONS: 'Available applications',
346475
ADD: 'Add',
347476
ACKNOWLEDGMENTS: 'Acknowledgments',
@@ -355,6 +484,9 @@ angular.module('nwas', ['ngSanitize', 'pascalprecht.translate']).controller('mai
355484
DFU_WROTE: "Done",
356485
OR: "or",
357486
CHECK_ICONS: "Enable experimental icons support.",
487+
CROP_IMAGE_TITLE: "Crop wallpaper",
488+
CROP_IMAGE_SAVE: "Save",
489+
CROP_IMAGE_CANCEL: "Cancel",
358490
})
359491
.translations('fr', {
360492
TITLE: 'Dépôt d\'application N110 non officiel',
@@ -367,6 +499,9 @@ angular.module('nwas', ['ngSanitize', 'pascalprecht.translate']).controller('mai
367499
REMOVE: 'Supprimer',
368500
CUSTOM_FILE: 'Fichier local',
369501
INSTALL: 'Installer',
502+
WALLPAPER: 'Fond d\'écran',
503+
WALLPAPER_FILE: 'Fichier PNG de taille 320x222',
504+
WALLPAPER_FILE_SIZE_ERROR: 'Erreur : le fichier ne fait pas la bonne taile.',
370505
AVAILABLE_APPLICATIONS: 'Applications disponibles',
371506
ADD: 'Ajouter',
372507
ACKNOWLEDGMENTS: 'Remerciements',
@@ -380,6 +515,9 @@ angular.module('nwas', ['ngSanitize', 'pascalprecht.translate']).controller('mai
380515
DFU_WROTE: "Terminé",
381516
OR: "ou",
382517
CHECK_ICONS: "Activer le support des icons (Expérimental)",
518+
CROP_IMAGE_TITLE: "Recadrer le fond d'écran",
519+
CROP_IMAGE_SAVE: "Sauvegarder",
520+
CROP_IMAGE_CANCEL: "Annuler",
383521
})
384522
.registerAvailableLanguageKeys(['en', 'fr'], {
385523
'en_*': 'en',

0 commit comments

Comments
 (0)