From 68117dda32e6888719f6ed02518d21261fcae1c1 Mon Sep 17 00:00:00 2001 From: Skylar Ittner Date: Tue, 7 Jan 2020 16:06:12 -0700 Subject: [PATCH] Add settings sync/backup feature --- www/assets/js/audio.js | 12 +-- www/assets/js/autofill.js | 12 +-- www/assets/js/list.js | 12 +-- www/assets/js/location.js | 16 ++-- www/assets/js/login.js | 35 ++++++++ www/assets/js/main.js | 12 ++- www/assets/js/manage.js | 8 +- www/assets/js/map.js | 6 +- www/assets/js/map_leaflet.js | 10 +-- www/assets/js/map_mapbox.js | 10 +-- www/assets/js/packages.js | 34 ++++---- www/assets/js/platform.js | 2 +- www/assets/js/settings.js | 66 +++++++------- www/assets/js/storage.js | 58 +++++++++++++ www/assets/js/sync.js | 110 ++++++++++++++++++++++++ www/assets/js/toolbox_scanner.js | 8 +- www/assets/js/toolbox_scannerentries.js | 2 +- www/assets/js/toolbox_track.js | 4 +- www/assets/js/toolbox_weather.js | 6 +- www/index.html | 3 + www/pages/login.html | 24 ++++++ www/routes.js | 80 +++++++++++++---- www/settings.js | 11 ++- 23 files changed, 418 insertions(+), 123 deletions(-) create mode 100644 www/assets/js/login.js create mode 100644 www/assets/js/storage.js create mode 100644 www/assets/js/sync.js create mode 100644 www/pages/login.html diff --git a/www/assets/js/audio.js b/www/assets/js/audio.js index e8dbb9f..500d83c 100644 --- a/www/assets/js/audio.js +++ b/www/assets/js/audio.js @@ -7,15 +7,15 @@ var sfx = {}; function initSFX() { - if (localStorage.getItem("alertsound") == null) { - localStorage.setItem("alertsound", "sonar"); + if (getStorage("alertsound") == null) { + setStorage("alertsound", "sonar"); } - if (localStorage.getItem("alertvolume") == null) { - localStorage.setItem("alertvolume", 100); + if (getStorage("alertvolume") == null) { + setStorage("alertvolume", 100); } - var alertNoiseFile = SETTINGS.alertsounds[localStorage.getItem("alertsound")].file; - var alertVolume = localStorage.getItem("alertvolume"); + var alertNoiseFile = SETTINGS.alertsounds[getStorage("alertsound")].file; + var alertVolume = getStorage("alertvolume"); sfx = { "alert": new Audio("assets/audio/" + alertNoiseFile), diff --git a/www/assets/js/autofill.js b/www/assets/js/autofill.js index dc737b9..1df243d 100644 --- a/www/assets/js/autofill.js +++ b/www/assets/js/autofill.js @@ -7,12 +7,12 @@ var autofillDB = {}; var autofillStreetDB = []; -if (localStorage.getItem("autofill_db") != null) { - autofillDB = JSON.parse(localStorage.getItem("autofill_db")); +if (getStorage("autofill_db") != null) { + autofillDB = JSON.parse(getStorage("autofill_db")); } -if (localStorage.getItem("autofill_streetdb") != null) { - autofillStreetDB = JSON.parse(localStorage.getItem("autofill_streetdb")); +if (getStorage("autofill_streetdb") != null) { + autofillStreetDB = JSON.parse(getStorage("autofill_streetdb")); } function addressToNumberAndStreet(address) { @@ -54,7 +54,7 @@ function addAutofillEntry(address) { } } - localStorage.setItem("autofill_db", JSON.stringify(autofillDB)); + setStorage("autofill_db", JSON.stringify(autofillDB)); var found = false; @@ -70,7 +70,7 @@ function addAutofillEntry(address) { autofillStreetDB.push([street, 1]); } - localStorage.setItem("autofill_streetdb", JSON.stringify(autofillStreetDB)); + setStorage("autofill_streetdb", JSON.stringify(autofillStreetDB)); } function searchAutofill(q, number) { diff --git a/www/assets/js/list.js b/www/assets/js/list.js index 4af9ef6..4b70cdf 100644 --- a/www/assets/js/list.js +++ b/www/assets/js/list.js @@ -41,13 +41,13 @@ function updateDistances(latitude, longitude) { function loadPackageList(sortType) { // If no sort type is specified, use the saved pref or a default one if (typeof sortType == 'undefined') { - if (localStorage.getItem("sorttype") == null) { - localStorage.setItem("sorttype", "distance_asc"); + if (getStorage("sorttype") == null) { + setStorage("sorttype", "distance_asc"); } - sortType = localStorage.getItem("sorttype"); + sortType = getStorage("sorttype"); } else { // save the current sorting order so it'll stay consistent next time the list is refreshed - localStorage.setItem("sorttype", sortType); + setStorage("sorttype", sortType); } updateDistances(userPosition.coords.latitude, userPosition.coords.longitude); @@ -110,7 +110,7 @@ function loadPackageList(sortType) { delivered = true; icon = "far fa-check-circle"; classes = "text-color-green"; - } else if (typeof sortedPackages[i].value.distance != 'undefined' && sortedPackages[i].value.distance * 1 < localStorage.getItem("alertradius") * 1) { + } else if (typeof sortedPackages[i].value.distance != 'undefined' && sortedPackages[i].value.distance * 1 < getStorage("alertradius") * 1) { classes = "text-color-deeporange"; } $("#addresslist").append( @@ -157,7 +157,7 @@ function confirmDeleteAllPackages() { function () { // clear packages = []; - localStorage.setItem("packages", JSON.stringify(packages)); + setStorage("packages", JSON.stringify(packages)); loadPackageList(); if (map != null) { map.updatePackageLayer(packages); diff --git a/www/assets/js/location.js b/www/assets/js/location.js index dd87548..e02bc67 100644 --- a/www/assets/js/location.js +++ b/www/assets/js/location.js @@ -15,9 +15,9 @@ var userPosition = { }; // Preload last known location while GPS warms up -if (localStorage.getItem("user_latitude") != null && localStorage.getItem("user_longitude") != null) { - userPosition.coords.latitude = localStorage.getItem("user_latitude"); - userPosition.coords.longitude = localStorage.getItem("user_longitude"); +if (getStorage("user_latitude") != null && getStorage("user_longitude") != null) { + userPosition.coords.latitude = getStorage("user_latitude"); + userPosition.coords.longitude = getStorage("user_longitude"); } // Request the user's IP geolocation as a poor substitute for an actual location @@ -42,15 +42,15 @@ var mapLocationControlStarted = false; if ("geolocation" in navigator) { navigator.geolocation.watchPosition(function (position) { userPosition = position; - localStorage.setItem("user_latitude", userPosition.coords.latitude); - localStorage.setItem("user_longitude", userPosition.coords.longitude); + setStorage("user_latitude", userPosition.coords.latitude); + setStorage("user_longitude", userPosition.coords.longitude); if (mapLocationControlStarted) { // 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); - var alertinterval = localStorage.getItem("alertinterval"); + var alertinterval = getStorage("alertinterval"); if (alertinterval == null) { alertinterval = 30; } else { @@ -59,7 +59,7 @@ if ("geolocation" in navigator) { lastGpsUpdateTimestamp = currentTimestamp; for (var i = 0; i < packages.length; i++) { - if (packages[i].distance * 1 < localStorage.getItem("alertradius") * 1) { + if (packages[i].distance * 1 < getStorage("alertradius") * 1) { if (packages[i].lastAlert > currentTimestamp - alertinterval) { continue; @@ -178,7 +178,7 @@ function getDisplayDistance(meters, space) { if (typeof space == 'undefined') { space = true; } - var units = localStorage.getItem("units"); + var units = getStorage("units"); if (units == null) { units = "metric"; diff --git a/www/assets/js/login.js b/www/assets/js/login.js new file mode 100644 index 0000000..25ee073 --- /dev/null +++ b/www/assets/js/login.js @@ -0,0 +1,35 @@ +/* + * 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/. + */ + + +$(window).on("message", function (e) { + var data = e.originalEvent.data; + var parts = data.split("&"); + var u = ""; + var p = ""; + + for (var i = 0; i < parts.length; i++) { + if (parts[i].startsWith("user:")) { + u = parts[i].replace("user:", ""); + } else if (parts[i].startsWith("password:")) { + p = parts[i].replace("password:", ""); + } + } + + if (u != "" && p != "") { + setStorage("username", u); + setStorage("password", p); + app.toast.show({ + text: "You are now logged in!", + position: "bottom", + destroyOnClose: true, + closeTimeout: 1000 * 3 + }); + restartApplication(); + } else { + app.dialog.alert("There was a problem. Try again later.", "Error"); + } +}); \ No newline at end of file diff --git a/www/assets/js/main.js b/www/assets/js/main.js index de756a2..aec5a32 100644 --- a/www/assets/js/main.js +++ b/www/assets/js/main.js @@ -67,19 +67,17 @@ router.on("routeChange", function (newRoute) { }); // Set alert radius to 100 meters by default -if (localStorage.getItem("alertradius") == null) { - localStorage.setItem("alertradius", 100); +if (getStorage("alertradius") == null) { + setStorage("alertradius", 100); } // Set default alert sound volume -if (localStorage.getItem("alertvolume") == null) { - localStorage.setItem("alertvolume", 100); +if (getStorage("alertvolume") == null) { + setStorage("alertvolume", 100); } -if (localStorage.getItem("darktheme") == "true") { +if (getStorage("darktheme") == "true") { $("#app").addClass("theme-dark"); } -initPlatform(); - router.navigate("/home"); \ No newline at end of file diff --git a/www/assets/js/manage.js b/www/assets/js/manage.js index 5543912..d094133 100644 --- a/www/assets/js/manage.js +++ b/www/assets/js/manage.js @@ -37,8 +37,8 @@ $("#addpackagebtn").click(function () { } // Save city/state if changed - if (localStorage.getItem("citystate") != $("input[name=citystate]").val().trim()) { - localStorage.setItem("citystate", $("input[name=citystate]").val().trim()); + if (getStorage("citystate") != $("input[name=citystate]").val().trim()) { + setStorage("citystate", $("input[name=citystate]").val().trim()); } var address = ($("input[name=number]").val() + " " + $("input[name=street]").val()).toUpperCase(); @@ -82,6 +82,6 @@ $(".view-main").on("click", "#historylist .history-list-item", function () { }); // Restore user's last entered city/state combo -if (localStorage.getItem("citystate") != null) { - $("input[name=citystate]").val(localStorage.getItem("citystate")); +if (getStorage("citystate") != null) { + $("input[name=citystate]").val(getStorage("citystate")); } \ No newline at end of file diff --git a/www/assets/js/map.js b/www/assets/js/map.js index 9a5c94b..907a93f 100644 --- a/www/assets/js/map.js +++ b/www/assets/js/map.js @@ -9,10 +9,10 @@ var map = null; var maptype = "mapbox"; function createMap() { - if (localStorage.getItem("maptype") == null) { - localStorage.setItem("maptype", "mapbox"); + if (getStorage("maptype") == null) { + setStorage("maptype", "mapbox"); } - maptype = localStorage.getItem("maptype"); + maptype = getStorage("maptype"); if (maptype == "mapbox") { if (mapboxgl.supported()) { map = mapboxMap(); diff --git a/www/assets/js/map_leaflet.js b/www/assets/js/map_leaflet.js index 2b13265..2937eb7 100644 --- a/www/assets/js/map_leaflet.js +++ b/www/assets/js/map_leaflet.js @@ -16,13 +16,13 @@ function leafletMap() { map.maptype = "leaflet"; - if (localStorage.getItem("mapsource") == null) { - localStorage.setItem("mapsource", "liberty"); + if (getStorage("mapsource") == null) { + setStorage("mapsource", "liberty"); } - $("#mapbox").css("background-color", SETTINGS.maptileurls[localStorage.getItem("mapsource")].bgcolor); + $("#mapbox").css("background-color", SETTINGS.maptileurls[getStorage("mapsource")].bgcolor); - L.tileLayer(SETTINGS.maptileurls[localStorage.getItem("mapsource")].url, { + L.tileLayer(SETTINGS.maptileurls[getStorage("mapsource")].url, { minZoom: 1, maxZoom: 19 }).addTo(map); @@ -32,7 +32,7 @@ function leafletMap() { showPopup: false, locateOptions: { enableHighAccuracy: true, - maxZoom: localStorage.getItem("trackzoom") == null ? 16 : localStorage.getItem("trackzoom") * 1 + maxZoom: getStorage("trackzoom") == null ? 16 : getStorage("trackzoom") * 1 }, setView: "untilPanOrZoom", icon: "far fa-compass", diff --git a/www/assets/js/map_mapbox.js b/www/assets/js/map_mapbox.js index 358b54a..0086e32 100644 --- a/www/assets/js/map_mapbox.js +++ b/www/assets/js/map_mapbox.js @@ -10,16 +10,16 @@ var firstload = true; function mapboxMap() { - if (localStorage.getItem("mapsource") == null) { - localStorage.setItem("mapsource", "liberty"); + if (getStorage("mapsource") == null) { + setStorage("mapsource", "liberty"); } - $("#mapbox").css("background-color", SETTINGS.maptileurls[localStorage.getItem("mapsource")].bgcolor); + $("#mapbox").css("background-color", SETTINGS.maptileurls[getStorage("mapsource")].bgcolor); mapboxgl.accessToken = ''; var map = new mapboxgl.Map({ container: 'mapbox', - style: SETTINGS.maptileurls[localStorage.getItem("mapsource")].json, + style: SETTINGS.maptileurls[getStorage("mapsource")].json, attributionControl: false, dragPan: true, pitch: 0, @@ -40,7 +40,7 @@ function mapboxMap() { timeout: 10 * 1000 }, fitBoundsOptions: { - maxZoom: localStorage.getItem("trackzoom") == null ? 16 : localStorage.getItem("trackzoom") * 1 + maxZoom: getStorage("trackzoom") == null ? 16 : getStorage("trackzoom") * 1 }, trackUserLocation: true }), 'top-left' diff --git a/www/assets/js/packages.js b/www/assets/js/packages.js index a38e162..abc6503 100644 --- a/www/assets/js/packages.js +++ b/www/assets/js/packages.js @@ -6,8 +6,8 @@ var packages = []; -if (localStorage.getItem("packages") != null) { - packages = JSON.parse(localStorage.getItem("packages")); +if (getStorage("packages") != null) { + packages = JSON.parse(getStorage("packages")); } /** @@ -133,7 +133,7 @@ function addPackage(address, latitude, longitude, type, callback, deadline) { ] }); } - localStorage.setItem("packages", JSON.stringify(packages)); + setStorage("packages", JSON.stringify(packages)); playSound("ok"); @@ -196,7 +196,7 @@ function importPackageList(newlist) { } } } - localStorage.setItem("packages", JSON.stringify(packages)); + setStorage("packages", JSON.stringify(packages)); if (map != null) { reloadMap(); } @@ -223,7 +223,7 @@ function markDelivered(id, delivered) { } } - localStorage.setItem("packages", JSON.stringify(packages)); + setStorage("packages", JSON.stringify(packages)); } function confirmDeletePackage(package, callback) { @@ -250,7 +250,7 @@ function deletePackage(id, callback) { packages.splice(i, 1); } - localStorage.setItem("packages", JSON.stringify(packages)); + setStorage("packages", JSON.stringify(packages)); loadPackageList(); if (typeof callback == 'function') { @@ -290,10 +290,10 @@ function addPackageByAddress(number, street, citystate, type, callback) { var deadline = false; var ajaxlookup = function () { - var geocodecache = localStorage.getItem("geocode_cache"); + var geocodecache = getStorage("geocode_cache"); if (geocodecache == null) { geocodecache = "{}"; - localStorage.setItem("geocode_cache", "{}"); + setStorage("geocode_cache", "{}"); } geocodecache = JSON.parse(geocodecache); @@ -304,7 +304,7 @@ function addPackageByAddress(number, street, citystate, type, callback) { if (cacheitem.added + SETTINGS.geocodecacheexpiry < timestamp) { console.log("Info", "Removing expired geocode cache item " + cachekey); delete geocodecache[cachekey]; - localStorage.setItem("geocode_cache", JSON.stringify(geocodecache)); + setStorage("geocode_cache", JSON.stringify(geocodecache)); } else { console.log("Info", "Using cached geocode result", cacheitem); addPackage(cacheitem.address, cacheitem.latitude, cacheitem.longitude, type, callback, deadline); @@ -336,7 +336,7 @@ function addPackageByAddress(number, street, citystate, type, callback) { longitude: resp.coords[1], added: Math.floor(Date.now() / 1000) }; - localStorage.setItem("geocode_cache", JSON.stringify(geocodecache)); + setStorage("geocode_cache", JSON.stringify(geocodecache)); } else { playSound("error"); app.dialog.confirm( @@ -377,10 +377,10 @@ function addPackageByAddress(number, street, citystate, type, callback) { } if (type == "express") { - if (localStorage.getItem("deadlinealarm_minutes") == null) { - localStorage.setItem("deadlinealarm_minutes", 20); + if (getStorage("deadlinealarm_minutes") == null) { + setStorage("deadlinealarm_minutes", 20); } - var minutes = localStorage.getItem("deadlinealarm_minutes"); + var minutes = getStorage("deadlinealarm_minutes"); app.dialog.create({ title: 'Express Item', text: 'Set a reminder for ' + minutes + ' minutes before:', @@ -437,10 +437,10 @@ function addPackageByAddress(number, street, citystate, type, callback) { } function checkDeadlines() { - if (localStorage.getItem("deadlinealarm_minutes") == null) { - localStorage.setItem("deadlinealarm_minutes", 20); + if (getStorage("deadlinealarm_minutes") == null) { + setStorage("deadlinealarm_minutes", 20); } - var minutes = localStorage.getItem("deadlinealarm_minutes"); + var minutes = getStorage("deadlinealarm_minutes"); var currentTime = new Date().getTime() / 1000; var deadlineTime = currentTime + (minutes * 60); for (i in packages) { @@ -457,7 +457,7 @@ function checkDeadlines() { } ); packages[i].items[j].deadlinealarmed = true; - localStorage.setItem("packages", JSON.stringify(packages)); + setStorage("packages", JSON.stringify(packages)); } } } diff --git a/www/assets/js/platform.js b/www/assets/js/platform.js index c260160..978a19c 100644 --- a/www/assets/js/platform.js +++ b/www/assets/js/platform.js @@ -120,7 +120,7 @@ function initCordova() { } }, false); document.addEventListener("deviceready", function () { - if (localStorage.getItem("wakelock") == "true") { + if (getStorage("wakelock") == "true") { window.powerManagement.acquire(function () { console.log("Info", 'Wakelock acquired'); }, function () { diff --git a/www/assets/js/settings.js b/www/assets/js/settings.js index 2378d8b..cb9e6ef 100644 --- a/www/assets/js/settings.js +++ b/www/assets/js/settings.js @@ -5,48 +5,56 @@ */ +function logout() { + app.dialog.confirm( + "Are you sure you want to log out?", + "Log out?", + function () { + localStorage.removeItem('password'); + localStorage.removeItem('username'); + restartApplication(); + } + ); +} + +function resyncAndRestart() { + app.toast.show({ + text: "Syncing settings and restarting...", + position: "bottom", + destroyOnClose: true, + closeTimeout: 1000 * 10 + }); + syncNow(function () { + restartApplication(); + }); +} + $('.item-content[data-setting=darktheme] .toggle input').on("change", function () { var checked = $(this).prop('checked'); - localStorage.setItem("darktheme", checked); + setStorage("darktheme", checked); - if (localStorage.getItem("darktheme") == "true") { - $("#app").addClass("theme-dark"); - } else { - $("#app").removeClass("theme-dark"); - } + loadSettings(); }); $('.item-content[data-setting=showhelp] .toggle input').on("change", function () { var checked = $(this).prop('checked'); - localStorage.setItem("show_help", checked); + setStorage("show_help", checked); }); $('.item-link[data-setting=units] select').on("change", function () { - localStorage.setItem("units", $('.item-link[data-setting=units] select').val()); + setStorage("units", $('.item-link[data-setting=units] select').val()); }); $('.item-link[data-setting=trackzoom] select').on("change", function () { - localStorage.setItem("trackzoom", $('.item-link[data-setting=trackzoom] select').val()); + setStorage("trackzoom", $('.item-link[data-setting=trackzoom] select').val()); }); $('.item-content[data-setting=wakelock] .toggle input').on("change", function () { var checked = $(this).prop('checked'); - localStorage.setItem("wakelock", checked); + setStorage("wakelock", checked); if (platform_type == "cordova") { - if (localStorage.getItem("wakelock") == "true") { - window.powerManagement.acquire(function () { - console.log("Info", 'Wakelock acquired'); - }, function () { - console.log("Warn", 'Failed to acquire wakelock'); - }); - } else { - window.powerManagement.release(function () { - console.log("Info", 'Wakelock released'); - }, function () { - console.log("Warn", 'Failed to release wakelock'); - }); - } + loadSettings(); } else { app.toast.show({ text: "This setting won't do anything on your device.", @@ -59,30 +67,30 @@ $('.item-content[data-setting=wakelock] .toggle input').on("change", function () $('.item-content[data-setting=alertvolume] .range-slider').on('range:changed', function (e, range) { var val = app.range.get(".item-content[data-setting=alertvolume] .range-slider").getValue(); - localStorage.setItem("alertvolume", val); + setStorage("alertvolume", val); setVolume("alert", val); playSound("alert"); }); $('.item-content[data-setting=alertradius] .range-slider').on('range:changed', function (e, range) { var val = app.range.get(".item-content[data-setting=alertradius] .range-slider").getValue(); - localStorage.setItem("alertradius", val); + setStorage("alertradius", val); }); $('.item-content[data-setting=alertinterval] .range-slider').on('range:changed', function (e, range) { var val = app.range.get(".item-content[data-setting=alertinterval] .range-slider").getValue(); - localStorage.setItem("alertinterval", val); + setStorage("alertinterval", val); }); $('.item-link[data-setting=mapsource] select').on("change", function () { - localStorage.setItem("mapsource", $('.item-link[data-setting=mapsource] select').val()); + setStorage("mapsource", $('.item-link[data-setting=mapsource] select').val()); reloadMap(); }); $('.item-content[data-setting=maptype] .toggle input').on("change", function () { var checked = $(this).prop('checked'); - localStorage.setItem("maptype", checked ? "leaflet" : "mapbox"); + setStorage("maptype", checked ? "leaflet" : "mapbox"); maptype = checked ? "leaflet" : "mapbox"; @@ -90,7 +98,7 @@ $('.item-content[data-setting=maptype] .toggle input').on("change", function () }); $('.item-link[data-setting=alertsound] select').on("change", function () { - localStorage.setItem("alertsound", $('.item-link[data-setting=alertsound] select').val()); + setStorage("alertsound", $('.item-link[data-setting=alertsound] select').val()); // Reload sound effect stuff to apply new sound initSFX(); // Play the selected sound diff --git a/www/assets/js/storage.js b/www/assets/js/storage.js new file mode 100644 index 0000000..8e4c002 --- /dev/null +++ b/www/assets/js/storage.js @@ -0,0 +1,58 @@ +/* + * 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/. + */ + + +/** + * Save something to persistent storage. + * @param {string} key + * @param {string} value non-string values are converted to strings. + * @param {bool} nochangeupdate If true, the lastchange setting won't be updated. + * @returns {undefined} + */ +function setStorage(key, value, nochangeupdate) { + if (typeof nochangeupdate == 'undefined') { + nochangeupdate = false; + } + localStorage.setItem(key, value); + if (!nochangeupdate && !SETTINGS.synckeyblacklist.includes(key)) { + localStorage.setItem("lastchange", Date.now() / 1000); + } +} + +/** + * Get an item from persistent storage. + * @param {type} key + * @returns {DOMString} + */ +function getStorage(key) { + return localStorage.getItem(key); +} + +/** + * Check if an item is in the persistent storage. + * @param {string} key + * @returns {Boolean} + */ +function inStorage(key) { + return localStorage.getItem(key) != null; +} + +/** + * Get all item from persistent storage. + * @returns {Array} [{key: "", value: ""},...] + */ +function getAllStorage() { + var all = []; + for (var key in localStorage) { + if (localStorage.hasOwnProperty(key)) { + all.push({ + key: key, + value: getStorage(key) + }); + } + } + return all; +} \ No newline at end of file diff --git a/www/assets/js/sync.js b/www/assets/js/sync.js new file mode 100644 index 0000000..e762ed8 --- /dev/null +++ b/www/assets/js/sync.js @@ -0,0 +1,110 @@ +/* + * 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/. + */ + + +function gatherSyncData() { + var data = { + localStorage: {}, + changed: getStorage("lastchange") == null ? 0 : getStorage("lastchange") + }; + var allitems = getAllStorage(); + for (var i = 0; i < allitems.length; i++) { + var key = allitems[i].key; + var value = allitems[i].value; + if (SETTINGS.synckeyblacklist.includes(key)) { + continue; + } + data.localStorage[key] = value; + } + return data; +} + +function syncDataToLocalStorage(data) { + for (var key in data.localStorage) { + if (data.localStorage.hasOwnProperty(key)) { + setStorage(key, data.localStorage[key], true); + } + } +} + +function resolveSync(remotedata) { + var localchangetime = getStorage("lastchange"); + if (remotedata.changed == null) { + // The server has nothing, this is the first sync + return true; + } + if (localchangetime == null) { + // No local setting changes but since we've gotten this far, + // the server has stuff for us + syncDataToLocalStorage(remotedata); + return true; + } + if (localchangetime < remotedata.changed) { + // The server has newer stuff for us + syncDataToLocalStorage(remotedata); + return true; + } + if (localchangetime >= remotedata.changed) { + // Our local data is newer or the same as the server copy + return true; + } + return false; +} + +function syncNow(callback) { + var username = getStorage("username"); + var password = getStorage("password"); + if (username == null || password == null) { + return false; + } + var data = gatherSyncData(); + + $.post(SETTINGS.syncapi, { + username: username, + password: password, + data: JSON.stringify(data) + }, function (resp) { + if (resp.status == "OK") { + resolveSync(resp.data); + setStorage("lastsync", Date.now() / 1000); + if (typeof callback == "function") { + callback(); + } + } + }, "json"); + return true; +} + +function loadSettings() { + if (getStorage("darktheme") == "true") { + $("#app").addClass("theme-dark"); + } else { + $("#app").removeClass("theme-dark"); + } + + if (platform_type == "cordova") { + if (getStorage("wakelock") == "true") { + window.powerManagement.acquire(function () { + console.log("Info", 'Wakelock acquired'); + }, function () { + console.log("Warn", 'Failed to acquire wakelock'); + }); + } else { + window.powerManagement.release(function () { + console.log("Info", 'Wakelock released'); + }, function () { + console.log("Warn", 'Failed to release wakelock'); + }); + } + } +} + +syncNow(loadSettings); + +// Sync every two minutes +setInterval(function () { + syncNow(loadSettings); +}, 1000 * 60 * 2); \ No newline at end of file diff --git a/www/assets/js/toolbox_scanner.js b/www/assets/js/toolbox_scanner.js index 69419ef..14d1a09 100644 --- a/www/assets/js/toolbox_scanner.js +++ b/www/assets/js/toolbox_scanner.js @@ -189,12 +189,12 @@ function openEventTypePopup(eventname) { } function saveScanCode(code) { - if (localStorage.getItem("scanevents") == null) { - localStorage.setItem("scanevents", "[]"); + if (getStorage("scanevents") == null) { + setStorage("scanevents", "[]"); } - var events = JSON.parse(localStorage.getItem("scanevents")); + var events = JSON.parse(getStorage("scanevents")); events.push(code); - localStorage.setItem("scanevents", JSON.stringify(events)); + setStorage("scanevents", JSON.stringify(events)); } $(".view-main").off("click", "#codelist li.codelist-entry"); diff --git a/www/assets/js/toolbox_scannerentries.js b/www/assets/js/toolbox_scannerentries.js index 1140edd..67fb845 100644 --- a/www/assets/js/toolbox_scannerentries.js +++ b/www/assets/js/toolbox_scannerentries.js @@ -11,7 +11,7 @@ function confirmDeleteScanEntries() { "Clear Entries", function () { // clear - localStorage.setItem("scanevents", "[]"); + setStorage("scanevents", "[]"); router.navigate("/toolbox/scanner/entries", { reloadCurrent: true }); diff --git a/www/assets/js/toolbox_track.js b/www/assets/js/toolbox_track.js index 968950a..c804d74 100644 --- a/www/assets/js/toolbox_track.js +++ b/www/assets/js/toolbox_track.js @@ -88,7 +88,7 @@ function openTrackingHistory(code) { } // Keep last five tracking codes in history - var history = localStorage.getItem("trackingcodehistory"); + var history = getStorage("trackingcodehistory"); if (history == null) { history = []; } else { @@ -100,7 +100,7 @@ function openTrackingHistory(code) { while (history.length > 5) { history.shift(); } - localStorage.setItem("trackingcodehistory", JSON.stringify(history)); + setStorage("trackingcodehistory", JSON.stringify(history)); if (refresh) { router.navigate("/toolbox/track/info", { diff --git a/www/assets/js/toolbox_weather.js b/www/assets/js/toolbox_weather.js index cd8f4bc..3b93246 100644 --- a/www/assets/js/toolbox_weather.js +++ b/www/assets/js/toolbox_weather.js @@ -40,12 +40,12 @@ function loadWeather(reload) { } requestfinished = true; if (resp.status == "OK") { - var mintemp = (localStorage.getItem("units") == "metric" ? Math.round(ftoc(resp.temp.min)) + " °C" : Math.round(resp.temp.min) + " °F"); - var maxtemp = (localStorage.getItem("units") == "metric" ? Math.round(ftoc(resp.temp.max)) + " °C" : Math.round(resp.temp.max) + " °F"); + var mintemp = (getStorage("units") == "metric" ? Math.round(ftoc(resp.temp.min)) + " °C" : Math.round(resp.temp.min) + " °F"); + var maxtemp = (getStorage("units") == "metric" ? Math.round(ftoc(resp.temp.max)) + " °C" : Math.round(resp.temp.max) + " °F"); $("#lowtemp").html(mintemp); $("#hightemp").html(maxtemp); $("#precipchance").text(Math.round(resp.precipitation.chance * 100.0) + "% chance"); - if (localStorage.getItem("units") == "metric") { + if (getStorage("units") == "metric") { $("#windspeed").text(Math.round(resp.windspeed * 1.609344) + " km/h"); } else { $("#windspeed").text(Math.round(resp.windspeed) + " mph"); diff --git a/www/index.html b/www/index.html index b379f10..c24b5db 100644 --- a/www/index.html +++ b/www/index.html @@ -43,6 +43,8 @@ + + @@ -55,6 +57,7 @@ + \ No newline at end of file diff --git a/www/pages/login.html b/www/pages/login.html new file mode 100644 index 0000000..f6ea537 --- /dev/null +++ b/www/pages/login.html @@ -0,0 +1,24 @@ + + +
+ + + +
+ +
+ + +
\ No newline at end of file diff --git a/www/routes.js b/www/routes.js index 5cb8c0d..663211b 100644 --- a/www/routes.js +++ b/www/routes.js @@ -101,6 +101,16 @@ var routes = [ } } }, + { + path: '/login', + templateUrl: './pages/login.html', + name: 'login', + options: { + context: { + loginurl: SETTINGS.loginurl + } + } + }, { path: '/toolbox', url: './pages/toolbox.html', @@ -222,22 +232,62 @@ var routes = [ path: '/settings', name: 'settings', async: function (routeTo, routeFrom, resolve, reject) { - var settings = [ - { - setting: "alerts", - title: "Package Alerts", - text: "Change the alert sound, volume, and distance.", - onclick: "router.navigate('/settings/alerts')", - link: true - }, - { - setting: "maps", - title: "Map and Navigation", - text: "Change map settings and units.", - onclick: "router.navigate('/settings/maps')", - link: true + var settings = []; + if (localStorage.getItem("username") != null && localStorage.getItem("password") != null) { + var lastsync = localStorage.getItem("lastsync"); + if (lastsync == null) { + lastsync = "never"; + } else { + lastsync = timestampToDateTimeString(lastsync); } - ]; + settings.push( + { + setting: "account", + title: "Account", + text: "Logged in as " + localStorage.getItem("username") + "
" + "Last sync: " + lastsync + }, + { + setting: "syncnow", + title: "", + text: "Sync now", + link: true, + onclick: "resyncAndRestart()" + }, + { + setting: "logout", + title: "", + text: "Log out", + link: true, + onclick: "logout()" + }, + ); + } else { + settings.push( + { + setting: "login", + title: "Account", + text: "Log in to backup and sync your settings and data.", + onclick: "router.navigate('/login', {history: false})", + link: true + } + ); + } + settings.push( + { + setting: "alerts", + title: "Package Alerts", + text: "Change the alert sound, volume, and distance.", + onclick: "router.navigate('/settings/alerts')", + link: true + }, + { + setting: "maps", + title: "Map and Navigation", + text: "Change map settings and units.", + onclick: "router.navigate('/settings/maps')", + link: true + } + ); if (platform_type == "cordova" && cordova.platformId != "browser") { settings.push({ diff --git a/www/settings.js b/www/settings.js index 05c641b..a3f91b2 100644 --- a/www/settings.js +++ b/www/settings.js @@ -301,10 +301,19 @@ var SETTINGS = { ] } ], + synckeyblacklist: [ + "username", "password", "trackingcodehistory", "packages", + "user_latitude", "user_longitude", "geocode_cache", "scanevents", + "lastsync", "lastchange" + ], geocodecacheexpiry: 604800, // One week geocodeapi: "https://apis.netsyms.net/packagehelper/geocode.php", trackingapi: "https://apis.netsyms.net/packagehelper/track.php", weatherapi: "https://apis.netsyms.net/packagehelper/weather.php", geoipapi: "https://apis.netsyms.net/packagehelper/geoip.php", - sharelistapi: "https://apis.netsyms.net/packagehelper/sharepackagelist.php" + sharelistapi: "https://apis.netsyms.net/packagehelper/sharepackagelist.php", +// loginurl: "http://localhost/packagehelperapi/login/", +// syncapi: "http://localhost/packagehelperapi/sync.php" + loginurl: "https://apis.netsyms.net/packagehelper/login/", + syncapi: "https://apis.netsyms.net/packagehelper/sync.php" }