forked from Netsyms/PackageHelper
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
226 lines
7.7 KiB
JavaScript
226 lines
7.7 KiB
JavaScript
/*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*/
|
|
|
|
|
|
var lastGpsUpdateTimestamp = 0;
|
|
|
|
var userPosition = {
|
|
coords: {
|
|
latitude: 0.0,
|
|
longitude: 0.0,
|
|
accuracy: 999999
|
|
}
|
|
};
|
|
|
|
var geoerrorcount = 0;
|
|
|
|
var gotfirstfix = false;
|
|
|
|
var map = null;
|
|
|
|
function createMap() {
|
|
map = leafletMap();
|
|
map.updatePackageLayer(packages);
|
|
}
|
|
|
|
/**
|
|
* Make the toggle button on the popup sheet do things
|
|
*/
|
|
$("#app").on("click", "#package-info-sheet #package-info-toggle-status", function () {
|
|
var pid = $(this).data("packageid");
|
|
if (typeof packages[pid].delivered == "undefined" || packages[pid].delivered == false) {
|
|
packages[pid].delivered = true;
|
|
localStorage.setItem("packages", JSON.stringify(packages));
|
|
map.updatePackageLayer(packages);
|
|
openPackageInfoSheet(packages[pid], true);
|
|
} else {
|
|
app.dialog.confirm(
|
|
packages[pid].address,
|
|
"Mark Undelivered",
|
|
function () {
|
|
// undeliver
|
|
packages[pid].delivered = false;
|
|
localStorage.setItem("packages", JSON.stringify(packages));
|
|
map.updatePackageLayer(packages);
|
|
openPackageInfoSheet(packages[pid], true);
|
|
},
|
|
function () {
|
|
// cancel
|
|
}
|
|
);
|
|
}
|
|
});
|
|
|
|
function openPackageInfoSheet(package, refreshOnly) {
|
|
if (typeof refreshOnly == "undefined") {
|
|
refreshOnly = false;
|
|
}
|
|
$("#package-info-toggle-status").data("packageid", packages.findIndex(function (p) {
|
|
return p == package;
|
|
}));
|
|
$("#package-info-address").text(package.address);
|
|
if (package.delivered) {
|
|
$("#package-info-delivery-status").html('<span class="text-color-green"><i class="fas fa-check-circle"></i> Delivered</span>');
|
|
$("#package-info-toggle-status").text("Mark undelivered");
|
|
} else {
|
|
$("#package-info-delivery-status").html('<i class="fas fa-circle"></i> Not delivered');
|
|
$("#package-info-toggle-status").text("Mark delivered");
|
|
}
|
|
if (!refreshOnly) {
|
|
app.sheet.create({el: "#package-info-sheet"}).open();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* TODO: make app location work before map is opened for first time
|
|
*/
|
|
if ("geolocation" in navigator) {
|
|
navigator.geolocation.watchPosition(function (position) {
|
|
userPosition = position;
|
|
if (gotfirstfix) {
|
|
//setMapLocation(position.coords.latitude, position.coords.longitude);
|
|
// Don't refresh at an interval less than ten seconds
|
|
var currentTimestamp = Math.floor(Date.now() / 1000);
|
|
if (lastGpsUpdateTimestamp < (currentTimestamp - 10)) {
|
|
updateDistances(position.coords.latitude, position.coords.longitude);
|
|
map.updatePackageLayer(packages);
|
|
lastGpsUpdateTimestamp = currentTimestamp;
|
|
for (var i = 0; i < packages.length; i++) {
|
|
if (packages[i].distance * 1 < localStorage.getItem("alertradius") * 1) {
|
|
|
|
if (packages[i].lastAlert > currentTimestamp - 30) {
|
|
continue;
|
|
}
|
|
|
|
if (packages[i].delivered) {
|
|
continue;
|
|
}
|
|
|
|
playSound("alert");
|
|
|
|
packages[i].lastAlert = currentTimestamp;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
if (map == null) {
|
|
return;
|
|
}
|
|
map.locateControl.start();
|
|
gotfirstfix = true;
|
|
}
|
|
}, function (err) {
|
|
if (typeof error == "function") {
|
|
error(err.message);
|
|
}
|
|
}, {
|
|
enableHighAccuracy: true,
|
|
timeout: 5000,
|
|
maximumAge: 0
|
|
});
|
|
} else {
|
|
geoerrorcount++;
|
|
console.log("Geolocation error #" + geoerrorcount + ": ", error);
|
|
// Stop showing error toasts if they're happening a lot
|
|
if (geoerrorcount <= 3) {
|
|
app.toast.show({
|
|
text: '<i class="fas fa-compass"></i> ' + error,
|
|
position: "bottom",
|
|
destroyOnClose: true,
|
|
closeTimeout: 1000 * 3
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update package distances relative to the passed coordinates.
|
|
* @param {type} latitude
|
|
* @param {type} longitude
|
|
* @returns {undefined}
|
|
*/
|
|
function updateDistances(latitude, longitude) {
|
|
for (var i = 0; i < packages.length; i++) {
|
|
var distance = getDistance(latitude, longitude, packages[i].coords[0], packages[i].coords[1]).toFixed(0);
|
|
packages[i].distance = distance;
|
|
$("#addresslist .package-list-item[data-latitude=\"" + packages[i].coords[0] + "\"][data-longitude=\"" + packages[i].coords[1] + "\"]").data("distance", distance);
|
|
$("#addresslist .package-list-item[data-latitude=\"" + packages[i].coords[0] + "\"][data-longitude=\"" + packages[i].coords[1] + "\"] .distance").text(distance + " m");
|
|
}
|
|
}
|
|
|
|
function setMapLocation(latitude, longitude) {
|
|
if (map == null) {
|
|
return;
|
|
}
|
|
map.setMapLocation(latitude, longitude);
|
|
}
|
|
|
|
function animateMapIn(latitude, longitude, zoom, heading) {
|
|
if (map == null) {
|
|
return;
|
|
}
|
|
if (typeof zoom == 'undefined') {
|
|
zoom = 14;
|
|
}
|
|
if (typeof heading == 'undefined') {
|
|
heading = 0;
|
|
}
|
|
map.animateMapIn(latitude, longitude, zoom, heading);
|
|
}
|
|
|
|
/**
|
|
* Calculate distance between two GPS points using Vincenty Formula.
|
|
*
|
|
* From Aman Singh https://stackoverflow.com/q/30536869
|
|
*
|
|
* @param {type} lat1
|
|
* @param {type} lon1
|
|
* @param {type} lat2
|
|
* @param {type} lon2
|
|
* @returns {Number} distance in meters
|
|
*/
|
|
function getDistance(lat1, lon1, lat2, lon2) {
|
|
|
|
var toRad = function (value) {
|
|
return value * Math.PI / 180;
|
|
}
|
|
|
|
var a = 6378137, b = 6356752.314245, f = 1 / 298.257223563;
|
|
var L = toRad(lon2 - lon1);
|
|
var U1 = Math.atan((1 - f) * Math.tan(toRad(lat1)));
|
|
var U2 = Math.atan((1 - f) * Math.tan(toRad(lat2)));
|
|
var sinU1 = Math.sin(U1), cosU1 = Math.cos(U1);
|
|
var sinU2 = Math.sin(U2), cosU2 = Math.cos(U2);
|
|
|
|
var lambda = L, lambdaP, iterLimit = 100;
|
|
do
|
|
{
|
|
var sinLambda = Math.sin(lambda), cosLambda = Math.cos(lambda);
|
|
var sinSigma = Math.sqrt((cosU2 * sinLambda) * (cosU2 * sinLambda) + (cosU1 * sinU2 - sinU1 * cosU2 * cosLambda) * (cosU1 * sinU2 - sinU1 * cosU2 * cosLambda));
|
|
if (sinSigma == 0)
|
|
return 0;
|
|
|
|
var cosSigma = sinU1 * sinU2 + cosU1 * cosU2 * cosLambda;
|
|
var sigma = Math.atan2(sinSigma, cosSigma);
|
|
var sinAlpha = cosU1 * cosU2 * sinLambda / sinSigma;
|
|
var cosSqAlpha = 1 - sinAlpha * sinAlpha;
|
|
var cos2SigmaM = cosSigma - 2 * sinU1 * sinU2 / cosSqAlpha;
|
|
if (isNaN(cos2SigmaM))
|
|
cos2SigmaM = 0;
|
|
var C = f / 16 * cosSqAlpha * (4 + f * (4 - 3 * cosSqAlpha));
|
|
lambdaP = lambda;
|
|
lambda = L + (1 - C) * f * sinAlpha * (sigma + C * sinSigma * (cos2SigmaM + C * cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM)));
|
|
} while (Math.abs(lambda - lambdaP) > 1e-12 && --iterLimit > 0);
|
|
|
|
if (iterLimit == 0)
|
|
return NaN
|
|
|
|
var uSq = cosSqAlpha * (a * a - b * b) / (b * b);
|
|
var A = 1 + uSq / 16384 * (4096 + uSq * (-768 + uSq * (320 - 175 * uSq)));
|
|
var B = uSq / 1024 * (256 + uSq * (-128 + uSq * (74 - 47 * uSq)));
|
|
var deltaSigma = B * sinSigma * (cos2SigmaM + B / 4 * (cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM) - B / 6 * cos2SigmaM * (-3 + 4 * sinSigma * sinSigma) * (-3 + 4 * cos2SigmaM * cos2SigmaM)));
|
|
var s = b * A * (sigma - deltaSigma);
|
|
return s;
|
|
} |