Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
218 lines
7.3 KiB
JavaScript
Executable file
218 lines
7.3 KiB
JavaScript
Executable file
'use strict';
|
|
/* global GestureDetector, ImageUtils */
|
|
|
|
window.onload = function() {
|
|
navigator.mozSetMessageHandler('activity', function handler(activityRequest) {
|
|
var activityName = activityRequest.source.name;
|
|
if (activityName !== 'share' && activityName !== 'setwallpaper') {
|
|
return;
|
|
}
|
|
startShare(activityRequest);
|
|
});
|
|
|
|
var preview = document.getElementById('preview');
|
|
var cancelButton = document.getElementById('cancel');
|
|
var setButton = document.getElementById('set-wallpaper');
|
|
var activity;
|
|
var blob;
|
|
var url;
|
|
var gestureDetector = new GestureDetector(preview);
|
|
// position of the image while dragging
|
|
var posX = 0;
|
|
var posY = 0;
|
|
// maximum number of pixel we can drag the image
|
|
var limitX;
|
|
var limitY;
|
|
var scale;
|
|
var previewImage = document.getElementById('previewImage');
|
|
|
|
// For the computations below, we need to know the full size of the screen
|
|
// in device pixels and the size of the window in CSS pixels. (The window
|
|
// and screen sizes can be different if there is a software home button.)
|
|
// We also need to ensure that the dimensions match the default orientation
|
|
// of the screen, even if the user is holding the device in a different
|
|
// orientation, and we want this to work for both phones (portrait) and
|
|
// tablets (landscape). This app is supposed to be locked to the default
|
|
// device orientation, but when it is launched as an activity from a
|
|
// different orientation sometimes it starts up in the wrong screen and
|
|
// window size. So we need to be careful to work around that window
|
|
// management bug, too.
|
|
var screenWidth, screenHeight;
|
|
var windowWidth, windowHeight;
|
|
if (screen.mozOrientation && screen.mozOrientation.startsWith('landscape')) {
|
|
// Since our manifest locks us to default orientation, mozOrientation
|
|
// should return that default orientation. If landscape then width is
|
|
// the larger dimension
|
|
screenWidth = Math.max(screen.width, screen.height);
|
|
windowWidth = Math.max(window.innerWidth, window.innerHeight);
|
|
screenHeight = Math.min(screen.width, screen.height);
|
|
windowHeight = Math.min(window.innerWidth, window.innerHeight);
|
|
} else {
|
|
// Otherwise, portrait is the default and width is the smaller dimension
|
|
screenWidth = Math.min(screen.width, screen.height);
|
|
windowWidth = Math.min(window.innerWidth, window.innerHeight);
|
|
screenHeight = Math.max(screen.width, screen.height);
|
|
windowHeight = Math.max(window.innerWidth, window.innerHeight);
|
|
}
|
|
|
|
// For the screen size we care about device pixels, not CSS pixels
|
|
screenWidth = Math.ceil(screenWidth * window.devicePixelRatio);
|
|
screenHeight = Math.ceil(screenHeight * window.devicePixelRatio);
|
|
|
|
function startShare(request) {
|
|
cancelButton.addEventListener('click', cancelShare);
|
|
|
|
gestureDetector.startDetecting();
|
|
|
|
activity = request;
|
|
blob = activity.source.data.blobs[0];
|
|
url = URL.createObjectURL(blob);
|
|
|
|
// Find out the size and type of the image without decoding it.
|
|
// If it is a really big jpeg, we'll need to downsample it while
|
|
// decoding it so we don't run out of memory.
|
|
ImageUtils.getSizeAndType(blob).then(gotImageData, imageDataError);
|
|
|
|
function imageDataError(err) {
|
|
console.error('Could not set wallpaper:', err);
|
|
activity.postError('Could not set wallpaper: ' + err);
|
|
endShare();
|
|
}
|
|
|
|
function gotImageData(imgdata) {
|
|
if (imgdata.type === ImageUtils.JPEG) {
|
|
var scale = Math.max(screenWidth / imgdata.width,
|
|
screenHeight / imgdata.height);
|
|
var fragment = ImageUtils.Downsample.sizeNoMoreThan(scale);
|
|
loadImage(url, fragment);
|
|
}
|
|
else {
|
|
loadImage(url);
|
|
}
|
|
}
|
|
|
|
function loadImage(url, fragment) {
|
|
previewImage.src = url + (fragment ? fragment : '');
|
|
|
|
previewImage.onload = function() {
|
|
previewImage.hidden = false;
|
|
|
|
// Compute a scale that will make the image at least as big as
|
|
// the screen in both dimensions.
|
|
var scalex = windowWidth / previewImage.width;
|
|
var scaley = windowHeight / previewImage.height;
|
|
scale = Math.max(scalex, scaley);
|
|
|
|
// Apply that scale to the image. Note that scaling width will
|
|
// also alter the height to match.
|
|
previewImage.width = Math.round(previewImage.width * scale);
|
|
|
|
// One dimension is now probably bigger than the screen, so figure
|
|
// out how to center the image on the screen and compute how much
|
|
// the user will be able to pan the image left and right or up
|
|
// and down.
|
|
limitX = windowWidth - previewImage.width;
|
|
limitY = windowHeight - previewImage.height;
|
|
|
|
posX = Math.round(limitX / 2);
|
|
posY = Math.round(limitY / 2);
|
|
previewImage.style.transform =
|
|
'translate(' + posX + 'px, ' + posY + 'px)';
|
|
|
|
setButton.addEventListener('click', scaleImage);
|
|
previewImage.addEventListener('pan', moveBackground);
|
|
};
|
|
}
|
|
}
|
|
|
|
function moveBackground(evt) {
|
|
var positions = evt.detail.relative;
|
|
|
|
posX += positions.dx;
|
|
if (posX > 0) {
|
|
posX = 0;
|
|
} else if (posX < limitX) {
|
|
posX = limitX;
|
|
}
|
|
|
|
posY += positions.dy;
|
|
if (posY > 0) {
|
|
posY = 0;
|
|
} else if (posY < limitY) {
|
|
posY = limitY;
|
|
}
|
|
|
|
previewImage.style.transform = 'translate(' + posX + 'px, ' + posY + 'px)';
|
|
}
|
|
|
|
function scaleImage() {
|
|
// Disable set wallpaper button to prevent hammering
|
|
// and causing multiple calls to scaleImage.
|
|
setButton.disabled = true;
|
|
|
|
// Create a canvas to have an image that is exactly
|
|
// the size of the screen in device pixels.
|
|
var canvas = document.createElement('canvas');
|
|
// To have an image which matches the device pixel, we need to multiply
|
|
// window.devicePixelRatio.
|
|
canvas.width = screenWidth;
|
|
canvas.height = screenHeight;
|
|
var ctx = canvas.getContext('2d');
|
|
|
|
var w = Math.round(windowWidth / scale);
|
|
var h = Math.round(windowHeight / scale);
|
|
var x = Math.round(-1 * posX / scale);
|
|
var y = Math.round(-1 * posY / scale);
|
|
|
|
if (x < 0) {
|
|
x = 0;
|
|
console.error('The value of x shouldn\'t be negative.');
|
|
}
|
|
if (y < 0) {
|
|
y = 0;
|
|
console.error('The value of y shouldn\'t be negative.');
|
|
}
|
|
|
|
ctx.drawImage(
|
|
previewImage,
|
|
x, y, w, h,
|
|
0, 0, canvas.width, canvas.height
|
|
);
|
|
|
|
canvas.toBlob(function(newBlob) {
|
|
blob = newBlob;
|
|
setWallpaper();
|
|
}, 'image/jpeg');
|
|
}
|
|
|
|
function setWallpaper() {
|
|
// Save the blob as the wallpaper setting
|
|
var request = navigator.mozSettings.createLock().set({
|
|
'wallpaper.image': blob
|
|
});
|
|
|
|
request.onsuccess = function() {
|
|
activity.postResult('shared');
|
|
endShare();
|
|
};
|
|
|
|
request.onerror = function() {
|
|
console.warn('error setting wallpaper.image:', request.error);
|
|
activity.postError('could not set wallpaper: ' + request.error);
|
|
endShare();
|
|
};
|
|
}
|
|
|
|
function cancelShare() {
|
|
activity.postError('cancelled');
|
|
endShare();
|
|
}
|
|
|
|
function endShare() {
|
|
activity = null;
|
|
window.URL.revokeObjectURL(url);
|
|
window.URL.revokeObjectURL(previewImage.src);
|
|
setButton.removeEventListener('click', scaleImage);
|
|
cancelButton.removeEventListener('click', cancelShare);
|
|
}
|
|
};
|