Working: initial setup tool, app list, using Apps
@ -1,4 +1,5 @@
|
||||
nbproject/private
|
||||
platforms
|
||||
plugins
|
||||
node_modules
|
||||
node_modules
|
||||
/www/old/
|
@ -0,0 +1,119 @@
|
||||
/* 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/. */
|
||||
|
||||
.mobile-app-hide {
|
||||
display: none;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.mobile-app-show {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.mobile-app-display {
|
||||
display: initial;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 767px) {
|
||||
#navbar-collapse {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
#swipe-nav {
|
||||
display: none;
|
||||
visibility: visible;
|
||||
overflow-y: scroll;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
width: 60%;
|
||||
z-index: 9999999;
|
||||
max-width: 300px;
|
||||
min-width: 200px;
|
||||
background-color: #fafafa;
|
||||
box-shadow: 5px 0px 15px 0px rgba(0,0,0,0.5);
|
||||
}
|
||||
|
||||
#swipe-nav #swipe-header {
|
||||
height: 150px;
|
||||
background-color: #eeeeee;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#swipe-nav #swipe-header #swipe-username {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
padding-left: 10px;
|
||||
padding-bottom: 10px;
|
||||
font-size: 110%;
|
||||
}
|
||||
|
||||
#swipe-nav #swipe-header #swipe-appicon {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
padding-left: 20px;
|
||||
padding-top: 20px;
|
||||
height: 80px;
|
||||
}
|
||||
|
||||
#swipe-nav #swipe-header #swipe-username .fa {
|
||||
font-size: 120%;
|
||||
}
|
||||
|
||||
#swipe-nav #swipe-pages {
|
||||
padding-bottom: 10px;
|
||||
border-bottom: 1px solid #eeeeee;
|
||||
}
|
||||
|
||||
#swipe-shader {
|
||||
position: fixed;
|
||||
display: none;
|
||||
visibility: visible;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
background-color: rgba(0,0,0,0.5);
|
||||
z-index: 9999998;
|
||||
}
|
||||
|
||||
#swipe-nav .swipe-list {
|
||||
margin-top: 5px;
|
||||
margin-bottom: 10px;
|
||||
padding-left: 0px;
|
||||
list-style-type: none;
|
||||
padding: 3px;
|
||||
}
|
||||
|
||||
#swipe-nav .swipe-list .nav-item {
|
||||
color: #424242;
|
||||
padding-top: 5px;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
|
||||
#swipe-nav .swipe-list .nav-item a:focus,a:active {
|
||||
background-color: #e0e0e0;
|
||||
}
|
||||
|
||||
#swipe-nav .swipe-list .nav-item i.fa {
|
||||
font-size: 120%;
|
||||
margin-right: 10px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
#swipe-nav .swipe-list .nav-item a {
|
||||
display: inline-block;
|
||||
color: #424242;
|
||||
font-size: 110%;
|
||||
text-decoration: none;
|
||||
width: 100%;
|
||||
padding-top: 15px;
|
||||
padding-bottom: 15px;
|
||||
}
|
||||
|
||||
#swipe-nav .swipe-list .nav-item a:hover {
|
||||
text-decoration: none;
|
||||
}
|
@ -1,148 +0,0 @@
|
||||
/* 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/. */
|
||||
|
||||
html, body {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.app-dock-container {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.app-dock {
|
||||
margin: 0 auto 10px auto;
|
||||
display: flex;
|
||||
justify-content: space-evenly;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.app-icon {
|
||||
border: 1px solid grey;
|
||||
border-radius: 20%;
|
||||
}
|
||||
|
||||
.app-dock-item {
|
||||
padding: 0px 10px 2px 10px;
|
||||
min-width: 100px;
|
||||
max-width: 50%;
|
||||
width: 120px;
|
||||
margin: 15px;
|
||||
}
|
||||
|
||||
.app-dock-item p {
|
||||
margin-bottom: 0px;
|
||||
font-size: 120%;
|
||||
color: #555;
|
||||
}
|
||||
|
||||
.app-dock-item p img {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
display: block;
|
||||
background: url(../img/app-icon-bg.svg) no-repeat;
|
||||
background-size: 90%;
|
||||
background-position: 50%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.app-dock-item p span {
|
||||
display: block;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* https://stackoverflow.com/a/23536146 */
|
||||
|
||||
.navbar-collapse.collapse {
|
||||
display: block!important;
|
||||
}
|
||||
|
||||
.navbar-nav>li, .navbar-nav {
|
||||
float: left !important;
|
||||
}
|
||||
|
||||
.navbar-nav.navbar-right:last-child {
|
||||
margin-right: -15px !important;
|
||||
}
|
||||
|
||||
.navbar-right {
|
||||
float: right!important;
|
||||
}
|
||||
|
||||
/* /stackoverflow */
|
||||
|
||||
|
||||
.nav {
|
||||
color: white;
|
||||
margin-right: 0px;
|
||||
height: 30px;
|
||||
margin-top: -4px;
|
||||
font-size: 20px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.navbar-right span {
|
||||
color: white;
|
||||
font-size: 18px;
|
||||
margin-top: -4px;
|
||||
}
|
||||
|
||||
.navbar-brand img {
|
||||
margin-right: 15px;
|
||||
height: 30px;
|
||||
margin-top: -4px;
|
||||
margin-left: -10px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.navbar-right li a img {
|
||||
height: 30px;
|
||||
margin-top: 6px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.navbar-right {
|
||||
margin-top: -6px;
|
||||
}
|
||||
|
||||
.navbar-right li a img {
|
||||
margin-top: -1px;
|
||||
}
|
||||
}
|
||||
|
||||
#manual_setup {
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
#navbar {
|
||||
min-height: 56px;
|
||||
}
|
||||
|
||||
.loading-text {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.circle-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
align-content: center;
|
||||
border-radius: 50%;
|
||||
height: 5rem;
|
||||
width: 5rem;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
margin: 2rem;
|
||||
z-index: 99999;
|
||||
}
|
||||
|
||||
.circle-btn img {
|
||||
height: 3rem;
|
||||
width: 3rem;
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
@font-face {
|
||||
font-family: 'Material Icons';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Material Icons'),
|
||||
local('MaterialIcons-Regular'),
|
||||
url(./MaterialIcons-Regular.woff2) format('woff2'),
|
||||
url(./MaterialIcons-Regular.woff) format('woff');
|
||||
}
|
||||
|
||||
.material-icons {
|
||||
font-family: 'Material Icons';
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-size: 24px; /* Preferred icon size */
|
||||
display: inline-block;
|
||||
line-height: 1;
|
||||
text-transform: none;
|
||||
letter-spacing: normal;
|
||||
word-wrap: normal;
|
||||
white-space: nowrap;
|
||||
direction: ltr;
|
||||
|
||||
/* Support for all WebKit browsers. */
|
||||
-webkit-font-smoothing: antialiased;
|
||||
/* Support for Safari and Chrome. */
|
||||
text-rendering: optimizeLegibility;
|
||||
|
||||
/* Support for Firefox. */
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
@ -1,332 +1,154 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
/*
|
||||
* 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 shown_notifications = [];
|
||||
|
||||
/**
|
||||
* Switches the app to the given screen.
|
||||
* @param {String} screenname The name of the screen to show.
|
||||
* @param {String} effect FADE, SLIDE, or nothing
|
||||
* @returns {undefined}
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
function openscreen(screenname, effect) {
|
||||
if (effect === 'FADE') {
|
||||
$('#content-zone').fadeOut(300, function () {
|
||||
$('#content-zone').load("views/" + screenname + ".html", function () {
|
||||
$('#content-zone').fadeIn(300);
|
||||
});
|
||||
});
|
||||
} else if (effect === 'SLIDE') {
|
||||
$('#content-zone').slideToggle('400', function () {
|
||||
$('#content-zone').load("views/" + screenname + ".html", function () {
|
||||
$('#content-zone').slideToggle('400');
|
||||
});
|
||||
});
|
||||
} else {
|
||||
$('#content-zone').load("views/" + screenname + ".html");
|
||||
}
|
||||
currentscreen = screenname;
|
||||
}
|
||||
|
||||
|
||||
function openfragment(fragment, target, effect) {
|
||||
if (effect === 'FADE') {
|
||||
$(target).fadeOut('slow', function () {
|
||||
$(target).load("views/" + fragment + ".html", function () {
|
||||
$(target).fadeIn('slow');
|
||||
});
|
||||
});
|
||||
} else if (effect === 'SLIDE') {
|
||||
$(target).slideToggle('400', function () {
|
||||
$(target).load("views/" + fragment + ".html", function () {
|
||||
$(target).slideToggle('400');
|
||||
});
|
||||
});
|
||||
} else {
|
||||
$(target).load("views/" + fragment + ".html");
|
||||
}
|
||||
}
|
||||
|
||||
var historyctr = -1;
|
||||
/**
|
||||
* Add button to the top navbar.
|
||||
* @param String screenid openscreen(screenid)
|
||||
* @param String icon The filename of the icon to show: <img src="icons/icon"...
|
||||
* @param String title Text to show next to the icon on large screens.
|
||||
* @returns {undefined}
|
||||
*/
|
||||
function addnavbarbtn(screenid, icon, title) {
|
||||
$('#navbar-buttons').append('<li><a onclick="openscreen(\'' + screenid + '\', \'FADE\')"><img src="icons/' + icon + '" alt="" /> <span class="hidden-xs">' + title + '</span></a></li>');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the navbar options.
|
||||
*
|
||||
* @param String title Text to display
|
||||
* @param boolean showarrow True if the back arrow should be visible
|
||||
* @param Stringn backscreen The screen to open when the title is pressed, false or null for none
|
||||
* @returns {undefined}
|
||||
*/
|
||||
function setnavbartitle(title, showarrow, backscreen) {
|
||||
var arrow = "";
|
||||
if (showarrow === true) {
|
||||
arrow = '<img src="icons/ic_arrow-back.svg" />';
|
||||
}
|
||||
var onclick = "";
|
||||
if (backscreen !== null && backscreen !== false) {
|
||||
onclick = ' onclick=\'openscreen("' + backscreen + '", "FADE");\'';
|
||||
}
|
||||
$("#navbar-header").html('<span class="navbar-brand" id="navbar-title" style="color: white;"' + onclick + '>' + arrow + title + '</span>');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the navbar.
|
||||
* @param {String,boolean} type false if no navbar, "home" for the home screen,
|
||||
* "settings" for settings, "app" for a custom title, or anything else for
|
||||
* a simple one.
|
||||
* @param {String} screentitle The title to show if type == "app"
|
||||
* @param {String} returnscreen Where to go back to. Defaults to "home".
|
||||
* @returns {undefined}
|
||||
*/
|
||||
function setnavbar(type, screentitle, returnscreen) {
|
||||
var navbar = $('#navbar-header');
|
||||
var btns = $('#navbar-buttons');
|
||||
if (type == false) {
|
||||
$('#navbar').css('display', 'none');
|
||||
$('#content-zone').css('margin-top', '0px');
|
||||
} else {
|
||||
if (cordova.platformId == 'android') {
|
||||
StatusBar.backgroundColorByHexString("#1976d2");
|
||||
window.plugins.headerColor.tint("#2196f3");
|
||||
} else {
|
||||
StatusBar.backgroundColorByHexString("#2196f3");
|
||||
}
|
||||
$('#navbar').css('display', 'initial');
|
||||
$('#content-zone').css('margin-top', '75px');
|
||||
if (returnscreen === undefined) {
|
||||
returnscreen = "home";
|
||||
_returnscreen = null;
|
||||
} else {
|
||||
_returnscreen = returnscreen;
|
||||
}
|
||||
btns.html("");
|
||||
switch (type) {
|
||||
case "home":
|
||||
setnavbartitle("Business", false, false);
|
||||
addnavbarbtn("mobilecode", "ic_desktop_windows.svg", "Code Login");
|
||||
addnavbarbtn("otp", "ic_vpn_key.svg", "2-factor Auth");
|
||||
addnavbarbtn("settings", "ic_settings.svg", "Settings");
|
||||
break;
|
||||
case "setup":
|
||||
setnavbartitle("Business", false, false);
|
||||
addnavbarbtn("otp", "ic_vpn_key.svg", "2-factor Auth");
|
||||
addnavbarbtn("settings", "ic_settings.svg", "Settings");
|
||||
break;
|
||||
case "settings":
|
||||
setnavbartitle("Settings", true, "home");
|
||||
break;
|
||||
case "otp":
|
||||
setnavbartitle("Auth Keys", true, "home");
|
||||
break;
|
||||
case "app":
|
||||
setnavbartitle(screentitle, true, returnscreen);
|
||||
break;
|
||||
default:
|
||||
setnavbartitle("Business", false, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Thanks to https://stackoverflow.com/a/13542669
|
||||
* @param {type} color
|
||||
* @param {type} percent
|
||||
* @returns {String}
|
||||
*/
|
||||
function shadeColor2(color, percent) {
|
||||
var f = parseInt(color.slice(1), 16), t = percent < 0 ? 0 : 255, p = percent < 0 ? percent * -1 : percent, R = f >> 16, G = f >> 8 & 0x00FF, B = f & 0x0000FF;
|
||||
return "#" + (0x1000000 + (Math.round((t - R) * p) + R) * 0x10000 + (Math.round((t - G) * p) + G) * 0x100 + (Math.round((t - B) * p) + B)).toString(16).slice(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the app.html view and open an app with native Android UI elements
|
||||
* @param String id Application ID
|
||||
* Open an app with native Android UI elements
|
||||
* @param String api Path to the mobile API
|
||||
* @param String url Base URL of the app
|
||||
* @param String icon URL to the app icon
|
||||
* @param String title Friendly app name
|
||||
* @param boolean injectcode (optional, default true) Whether or not to inject UI modification code into the app
|
||||
* @param boolean shownavbar (optional, default false) Whether or not to show the navbar at the top of the screen.
|
||||
* @returns {undefined}
|
||||
*/
|
||||
function openapp(id, api, url, icon, title, injectcode, shownavbar) {
|
||||
$('#content-zone').fadeOut(300, function () {
|
||||
$('#content-zone').load("views/app.html", function () {
|
||||
$('#content-zone').fadeIn(300, function () {
|
||||
launchapp(id, api, url, icon, title, injectcode, shownavbar);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
function launchapp(api, url, icon, title) {
|
||||
app.dialog.progress("Loading...").setText(title);
|
||||
|
||||
/**
|
||||
* Opens a modal dialog over the top of everything else.
|
||||
* @param {String} filename views/[filename].html
|
||||
* @param {String} modalselector [#id-of-the-modal]
|
||||
* @returns {undefined}
|
||||
*/
|
||||
function openmodal(filename, modalselector) {
|
||||
$('#modal-load-box').load("views/" + filename + ".html", null, function (x) {
|
||||
$(modalselector).css('z-index', 9999999);
|
||||
$(modalselector).modal('show');
|
||||
router.navigate({
|
||||
name: 'app'
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Close a modal (see openmodal)
|
||||
* @param {String} modalselector
|
||||
* @returns {undefined}
|
||||
*/
|
||||
function closemodal(modalselector) {
|
||||
$(modalselector).modal('hide');
|
||||
}
|
||||
|
||||
function restartApplication() {
|
||||
navigator.splashscreen.show();
|
||||
// We're doing the timeout so we don't run afoul of server-side rate limiting
|
||||
setTimeout(function () {
|
||||
window.location = "index.html";
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
function displayNotifications(callback) {
|
||||
$.post(localStorage.getItem("syncurl"), {
|
||||
$.post(url + api, {
|
||||
username: localStorage.getItem("username"),
|
||||
key: localStorage.getItem("key"),
|
||||
action: "checknotifications"
|
||||
password: localStorage.getItem("password"),
|
||||
action: "start_session"
|
||||
}, function (data) {
|
||||
if (data.status === 'OK') {
|
||||
for (var i = 0; i < data.notifications.length; i++) {
|
||||
var n = data.notifications[i];
|
||||
if (n.seen || shown_notifications.includes(n.id)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
cordova.plugins.notification.local.schedule([{
|
||||
title: n.title,
|
||||
text: n.content,
|
||||
actions: [
|
||||
{id: 'mark_read', title: "Mark Read"}
|
||||
],
|
||||
id: n.id,
|
||||
lockscreen: !n.sensitive
|
||||
}]);
|
||||
|
||||
shown_notifications.push(n.id);
|
||||
}
|
||||
}
|
||||
if (typeof callback == 'function') {
|
||||
callback();
|
||||
$('#appframe').on("load", function () {
|
||||
app.dialog.close();
|
||||
historyctr++;
|
||||
// Do this right away so it's a bit harder to glitch
|
||||
$('#appframe').contents().find('.navbar-right').html("<li><a onclick='quitapp()'><i class='fas fa-sign-out-alt fa-fw'></i> Back to Menu</a></li>");
|
||||
|
||||
$.get("js/polyfills.js", function (script) {
|
||||
$('#appframe').contents().find('body').append("<script>" + script + "<\/script>");
|
||||
$.get("vendor/js/jquery-ui.min.js", function (script) {
|
||||
$('#appframe').contents().find('body').append("<script>" + script + "<\/script>");
|
||||
$.get("vendor/js/hammer.min.js", function (script) {
|
||||
$('#appframe').contents().find('body').append("<script>" + script + "<\/script>");
|
||||
$.get("js/app-inject.js", function (script) {
|
||||
script = script.replace("__USERNAME__", userinfo.realname);
|
||||
script = script.replace("__LOGO__", icon);
|
||||
$('#appframe').contents().find('body').append("<script>" + script + "<\/script>");
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
$('#appframe').attr('src', url);
|
||||
} else {
|
||||
navigator.notification.alert(data.msg, null, "Error", 'Dismiss');
|
||||
router.back();
|
||||
}
|
||||
}, "json").fail(function () {
|
||||
if (typeof callback == 'function') {
|
||||
callback();
|
||||
}
|
||||
navigator.notification.alert("Could not connect to the server. Try again later.", null, "Error", 'Dismiss');
|
||||
router.back();
|
||||
});
|
||||
}
|
||||
|
||||
// Handle back button to close things
|
||||
document.addEventListener("backbutton", function (event) {
|
||||
if (isconfigvalid()) {
|
||||
if ($("#appframe").length && historyctr > 0) {
|
||||
console.log("going back");
|
||||
var iframe = document.getElementById("appframe");
|
||||
iframe.contentWindow.postMessage("goback", "*");
|
||||
historyctr--;
|
||||
} else if (_returnscreen != null) {
|
||||
openscreen(_returnscreen, "FADE");
|
||||
_returnscreen = null;
|
||||
} else {
|
||||
openscreen("home", "FADE");
|
||||
}
|
||||
} else {
|
||||
if (_returnscreen != null) {
|
||||
openscreen(_returnscreen, "FADE");
|
||||
_returnscreen = null;
|
||||
}
|
||||
}
|
||||
}, false);
|
||||
function navigateApp(src) {
|
||||
$('#appframe').attr('src', './' + src);
|
||||
}
|
||||
|
||||
document.addEventListener("deviceready", function () {
|
||||
if (cordova.platformId == 'android') {
|
||||
StatusBar.backgroundColorByHexString("#1976d2");
|
||||
var scanningactive = false;
|
||||
var dedup = [];
|
||||
window.addEventListener('message', function (event) {
|
||||
console.log("app event: " + event.data);
|
||||
setTimeout(function () {
|
||||
dedup = [];
|
||||
}, 500);
|
||||
if (dedup.includes(event.data)) {
|
||||
return;
|
||||
}
|
||||
|
||||
cordova.plugins.notification.local.setDefaults({
|
||||
led: true,
|
||||
color: '#2196F3',
|
||||
vibrate: true,
|
||||
smallIcon: "res://ic_notification"
|
||||
});
|
||||
cordova.plugins.notification.local.on("mark_read", function (notification) {
|
||||
$.post(localStorage.getItem("syncurl"), {
|
||||
username: localStorage.getItem("username"),
|
||||
key: localStorage.getItem("key"),
|
||||
password: localStorage.getItem("password"),
|
||||
action: "readnotification",
|
||||
id: notification.id
|
||||
});
|
||||
});
|
||||
|
||||
// Enable/disable jQuery animations depending on user preference
|
||||
$.fx.off = !(localStorage.getItem("animations") === null || localStorage.getItem("animations") === "true");
|
||||
|
||||
/* Fade out alerts */
|
||||
$(".alert .close").click(function (e) {
|
||||
$(this).parent().fadeOut("slow");
|
||||
});
|
||||
|
||||
if (isconfigvalid()) {
|
||||
getuserinfo(function () {
|
||||
openscreen("home");
|
||||
|
||||
setInterval(displayNotifications, 30 * 1000);
|
||||
if (typeof cordova.plugins.notification.local.launchDetails === 'undefined') {
|
||||
displayNotifications();
|
||||
dedup.push(event.data);
|
||||
if (event.data == "quit") {
|
||||
router.back();
|
||||
if (cordova.platformId == 'android') {
|
||||
StatusBar.backgroundColorByHexString("#1976d2");
|
||||
} else {
|
||||
StatusBar.backgroundColorByHexString("#2196f3");
|
||||
}
|
||||
} else if (event.data == "done_loading") {
|
||||
app.dialog.close();
|
||||
} else if (event.data == "goneback") {
|
||||
historyctr -= 1;
|
||||
} else if (event.data.startsWith("load_css ")) {
|
||||
var nav_breakpoint = event.data.split(" ", 2)[1];
|
||||
$.get("css/app-inject.css", function (style) {
|
||||
var break_px = "767";
|
||||
switch (nav_breakpoint) {
|
||||
case "sm":
|
||||
break_px = "575";
|
||||
break;
|
||||
case "md":
|
||||
break_px = "767";
|
||||
break;
|
||||
case "lg":
|
||||
break_px = "991";
|
||||
break;
|
||||
case "xl":
|
||||
break_px = "1199";
|
||||
break;
|
||||
}
|
||||
|
||||
var BackgroundFetch = window.BackgroundFetch;
|
||||
|
||||
// Your background-fetch handler.
|
||||
var fetchCallback = function () {
|
||||
console.log('[js] BackgroundFetch event received');
|
||||
displayNotifications(function () {
|
||||
BackgroundFetch.finish();
|
||||
});
|
||||
};
|
||||
|
||||
var failureCallback = function (error) {
|
||||
console.log('- BackgroundFetch failed', error);
|
||||
};
|
||||
|
||||
BackgroundFetch.configure(fetchCallback, failureCallback, {
|
||||
minimumFetchInterval: 1,
|
||||
stopOnTerminate: false,
|
||||
startOnBoot: true,
|
||||
forceReload: false,
|
||||
enableHeadless: true
|
||||
});
|
||||
style = style.replace("max-width: 767px", "max-width: " + break_px + "px");
|
||||
$('#appframe').contents().find('head').append("<style>" + style + "</style>");
|
||||
});
|
||||
} else {
|
||||
// Try to recover data from NativeStorage back to localStorage
|
||||
recoveraccounts(function (ok) {
|
||||
if (ok) {
|
||||
restartApplication();
|
||||
} else {
|
||||
openscreen("setup1");
|
||||
} else if (event.data.startsWith("setcolor ")) {
|
||||
var color = event.data.split(" ", 2)[1];
|
||||
if (cordova.platformId == 'android') {
|
||||
window.plugins.headerColor.tint(color);
|
||||
for (var swatch in _PALETTE) {
|
||||
if (color == _PALETTE[swatch]["shade_500"]) {
|
||||
StatusBar.backgroundColorByHexString(_PALETTE[swatch]["shade_700"]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
StatusBar.backgroundColorByHexString(shadeColor2(color, -0.1));
|
||||
} else {
|
||||
StatusBar.backgroundColorByHexString(color);
|
||||
}
|
||||
} else if (event.data.startsWith("scancode ")) {
|
||||
var callbackcode = event.data.split(" ").slice(1).join(" ");
|
||||
console.log("got scancode " + callbackcode);
|
||||
try {
|
||||
if (scanningactive) {
|
||||
console.log("Scanner already active, ignoring request.");
|
||||
return;
|
||||
}
|
||||
})
|
||||
scanningactive = true;
|
||||
cordova.plugins.barcodeScanner.scan(
|
||||
function (result) {
|
||||
scanningactive = false;
|
||||
if (!result.cancelled) {
|
||||
var iframe = document.getElementById("appframe");
|
||||
iframe.contentWindow.postMessage("coderesult~|~" + callbackcode + "~|~" + result.text, "*");
|
||||
}
|
||||
},
|
||||
function (error) {
|
||||
scanningactive = false;
|
||||
navigator.notification.alert("Scanning failed: " + error, null, "Error", 'Dismiss');
|
||||
},
|
||||
{
|
||||
"showFlipCameraButton": true,
|
||||
"prompt": "Scan Code"
|
||||
}
|
||||
);
|
||||
} catch (ex) {
|
||||
scanningactive = false;
|
||||
navigator.notification.alert(ex.message, null, "Error", 'Dismiss');
|
||||
}
|
||||
}
|
||||
setTimeout(navigator.splashscreen.hide, 500);
|
||||
}, false);
|
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 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 loadHomePage() {
|
||||
$.post(localStorage.getItem("syncurl"), {
|
||||
username: localStorage.getItem("username"),
|
||||
key: localStorage.getItem("key"),
|
||||
action: "listapps"
|
||||
}, function (data) {
|
||||
if (data.status === 'OK') {
|
||||
loadingProgressDialog.setProgress(80);
|
||||
var appcards = [];
|
||||
Object.keys(data.apps).forEach(function (k) {
|
||||
var app = data.apps[k];
|
||||
var iconurl = app.icon;
|
||||
if (!app.icon.startsWith("http")) {
|
||||
iconurl = app.url + app.icon;
|
||||
}
|
||||
if (!app.card) {
|
||||
return;
|
||||
}
|
||||
appcards.push({
|
||||
api: app.mobileapi,
|
||||
url: app.url,
|
||||
icon: iconurl,
|
||||
title: app.title,
|
||||
text: app.card.string,
|
||||
color: app.card.color
|
||||
});
|
||||
});
|
||||
loadingProgressDialog.setProgress(90);
|
||||
router.navigate("/home", {
|
||||
context: {
|
||||
appcards: appcards
|
||||
}
|
||||
});
|
||||
$(".view-main").on("click", "#applist .applist-item", function () {
|
||||
launchapp($(this).data("api"), $(this).data("url"), $(this).data("icon"), $(this).data("title"));
|
||||
});
|
||||
loadingProgressDialog.setProgress(100);
|
||||
loadingProgressDialog.close();
|
||||
} else {
|
||||
loadingProgressDialog.close();
|
||||
app.dialog.alert(data.msg, "Error", function () {
|
||||
restartApplication();
|
||||
});
|
||||
}
|
||||
}, "json").fail(function () {
|
||||
loadingProgressDialog.close();
|
||||
app.dialog.alert("Could not connect to the server. Try again later.", "Error", function () {
|
||||
restartApplication();
|
||||
});
|
||||
});
|
||||
|
||||
}
|
@ -0,0 +1,127 @@
|
||||
/* 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 shown_notifications = [];
|
||||
|
||||
var app = new Framework7({
|
||||
root: "#app",
|
||||
name: "Business",
|
||||
id: "com.netsyms.BusinessMobile",
|
||||
routes: routes,
|
||||
dialog: {
|
||||
buttonOK: "Dismiss"
|
||||
}
|
||||
});
|
||||
|
||||
var router = app.router;
|
||||
|
||||
var mainView = app.views.create('.view-main', {
|
||||
url: "/"
|
||||
});
|
||||
|
||||
var loadingProgressDialog;
|
||||
|
||||
/**
|
||||
* Thanks to https://stackoverflow.com/a/13542669
|
||||
* @param {type} color
|
||||
* @param {type} percent
|
||||
* @returns {String}
|
||||
*/
|
||||
function shadeColor2(color, percent) {
|
||||
var f = parseInt(color.slice(1), 16), t = percent < 0 ? 0 : 255, p = percent < 0 ? percent * -1 : percent, R = f >> 16, G = f >> 8 & 0x00FF, B = f & 0x0000FF;
|
||||
return "#" + (0x1000000 + (Math.round((t - R) * p) + R) * 0x10000 + (Math.round((t - G) * p) + G) * 0x100 + (Math.round((t - B) * p) + B)).toString(16).slice(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the app.html view and open an app with nativeish Android UI elements
|
||||
* @param String id Application ID
|
||||
* @param String api Path to the mobile API
|
||||
* @param String url Base URL of the app
|
||||
* @param String icon URL to the app icon
|
||||
* @param String title Friendly app name
|
||||
* @param boolean injectcode (optional, default true) Whether or not to inject UI modification code into the app
|
||||
* @param boolean shownavbar (optional, default false) Whether or not to show the navbar at the top of the screen.
|
||||
* @returns {undefined}
|
||||
*/
|
||||
function openapp(id, api, url, icon, title, injectcode, shownavbar) {
|
||||
$('#content-zone').fadeOut(300, function () {
|
||||
$('#content-zone').load("views/app.html", function () {
|
||||
$('#content-zone').fadeIn(300, function () {
|
||||
launchapp(id, api, url, icon, title, injectcode, shownavbar);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function restartApplication() {
|
||||
navigator.splashscreen.show();
|
||||
// We're doing the timeout so we don't run afoul of server-side rate limiting
|
||||
setTimeout(function () {
|
||||
window.location = "index.html";
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
// Handle back button to close things
|
||||
document.addEventListener("backbutton", function (event) {
|
||||
if (isconfigvalid()) {
|
||||
if ($("#appframe").length && historyctr > 0) {
|
||||
console.log("going back");
|
||||
var iframe = document.getElementById("appframe");
|
||||
iframe.contentWindow.postMessage("goback", "*");
|
||||
historyctr--;
|
||||
} else if (_returnscreen != null) {
|
||||
openscreen(_returnscreen, "FADE");
|
||||
_returnscreen = null;
|
||||
} else {
|
||||
openscreen("home", "FADE");
|
||||
}
|
||||
} else {
|
||||
if (_returnscreen != null) {
|
||||
openscreen(_returnscreen, "FADE");
|
||||
_returnscreen = null;
|
||||
}
|
||||
}
|
||||
}, false);
|
||||
|
||||
document.addEventListener("deviceready", function () {
|
||||
|
||||
loadingProgressDialog = app.dialog.progress('Loading...', 0);
|
||||
loadingProgressDialog.setText('');
|
||||
if (cordova.platformId == 'android') {
|
||||
StatusBar.backgroundColorByHexString("#1976d2");
|
||||
}
|
||||
|
||||
// Enable/disable jQuery animations depending on user preference
|
||||
$.fx.off = !(localStorage.getItem("animations") === null || localStorage.getItem("animations") === "true");
|
||||
|
||||
if (isconfigvalid()) {
|
||||
loadingProgressDialog.setProgress(20);
|
||||
loadingProgressDialog.setText('Account');
|
||||
getuserinfo(function () {
|
||||
loadingProgressDialog.setProgress(50);
|
||||
loadingProgressDialog.setText('Notifications');
|
||||
|
||||
// Setup notification sync
|
||||
initNotifications();
|
||||
loadingProgressDialog.setProgress(60);
|
||||
// Load homepage/dashboard
|
||||
loadingProgressDialog.setText('Apps');
|
||||
loadHomePage();
|
||||
});
|
||||
} else {
|
||||
// Try to recover data from NativeStorage back to localStorage
|
||||
recoveraccounts(function (ok) {
|
||||
if (ok) {
|
||||
// Success, restart app to reload from localStorage
|
||||
restartApplication();
|
||||
} else {
|
||||
// No account data found, open setup
|
||||
router.navigate({
|
||||
name: 'setup1'
|
||||
});
|
||||
}
|
||||
})
|
||||
}
|
||||
setTimeout(navigator.splashscreen.hide, 500);
|
||||
}, false);
|
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* 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 displayNotifications(callback) {
|
||||
$.post(localStorage.getItem("syncurl"), {
|
||||
username: localStorage.getItem("username"),
|
||||
key: localStorage.getItem("key"),
|
||||
action: "checknotifications"
|
||||
}, function (data) {
|
||||
if (data.status === 'OK') {
|
||||
for (var i = 0; i < data.notifications.length; i++) {
|
||||
var n = data.notifications[i];
|
||||
if (n.seen || shown_notifications.includes(n.id)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
cordova.plugins.notification.local.schedule([{
|
||||
title: n.title,
|
||||
text: n.content,
|
||||
actions: [
|
||||
{id: 'mark_read', title: "Mark Read"}
|
||||
],
|
||||
id: n.id,
|
||||
lockscreen: !n.sensitive
|
||||
}]);
|
||||
|
||||
shown_notifications.push(n.id);
|
||||
}
|
||||
}
|
||||
if (typeof callback == 'function') {
|
||||
callback();
|
||||
}
|
||||
}, "json").fail(function () {
|
||||
if (typeof callback == 'function') {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function initForegroundNotifications() {
|
||||
cordova.plugins.notification.local.setDefaults({
|
||||
led: true,
|
||||
color: '#2196F3',
|
||||
vibrate: true,
|
||||
smallIcon: "res://ic_notification"
|
||||
});
|
||||
cordova.plugins.notification.local.on("mark_read", function (notification) {
|
||||
$.post(localStorage.getItem("syncurl"), {
|
||||
username: localStorage.getItem("username"),
|
||||
key: localStorage.getItem("key"),
|
||||
password: localStorage.getItem("password"),
|
||||
action: "readnotification",
|
||||
id: notification.id
|
||||
});
|
||||
});
|
||||
|
||||
setInterval(displayNotifications, 30 * 1000);
|
||||
if (typeof cordova.plugins.notification.local.launchDetails === 'undefined') {
|
||||
displayNotifications();
|
||||
}
|
||||
}
|
||||
|
||||
function initBackgroundNotifications() {
|
||||
var BackgroundFetch = window.BackgroundFetch;
|
||||
|
||||
// Your background-fetch handler.
|
||||
var fetchCallback = function () {
|
||||
console.log('[js] BackgroundFetch event received');
|
||||
displayNotifications(function () {
|
||||
BackgroundFetch.finish();
|
||||
});
|
||||
};
|
||||
|
||||
var failureCallback = function (error) {
|
||||
console.log('- BackgroundFetch failed', error);
|
||||
};
|
||||
|
||||
BackgroundFetch.configure(fetchCallback, failureCallback, {
|
||||
minimumFetchInterval: 1,
|
||||
stopOnTerminate: false,
|
||||
startOnBoot: true,
|
||||
forceReload: false,
|
||||
enableHeadless: true
|
||||
});
|
||||
}
|
||||
|
||||
function initNotifications() {
|
||||
initForegroundNotifications();
|
||||
initBackgroundNotifications();
|
||||
}
|
@ -0,0 +1,126 @@
|
||||
/*
|
||||
* 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/.
|
||||
*/
|
||||
|
||||
|
||||
setupusername = "";
|
||||
setuppassword = "";
|
||||
setupsynckey = "";
|
||||
setupsyncurl = "";
|
||||
|
||||
if (localStorage.getItem("firstrun") === null) {
|
||||
$("#setuptitle").text("Setup");
|
||||
$(".firstrun-only").css("display", "");
|
||||
}
|
||||
|
||||
$('#use-security').click(function () {
|
||||
if (this.checked) {
|
||||
$('#protocol-select').text("https://");
|
||||
} else {
|
||||
$('#protocol-select').text("http://");
|
||||
}
|
||||
});
|
||||
|
||||
/* Detect if the user typed "http[s]://" into the URL box and correct for it */
|
||||
$("#syncurl").blur(function () {
|
||||
if ($('#syncurl').val().toLowerCase().startsWith("https://")) {
|
||||
$('#syncurl').val($('#syncurl').val().replace(/https\:\/\//ig, ""));
|
||||
$('#protocol-select').text("https://");
|
||||
$('#use-security').prop('checked', true);
|
||||
} else if ($('#syncurl').val().toLowerCase().startsWith("http://")) {
|
||||
$('#syncurl').val($('#syncurl').val().replace(/http\:\/\//ig, ""));
|
||||
$('#protocol-select').text("http://");
|
||||
$('#use-security').prop('checked', false);
|
||||
}
|
||||
});
|
||||
|
||||
$("#key").on("keyup", function () {
|
||||
if (window.getSelection().toString() !== '') {
|
||||
return;
|
||||
}
|
||||
var text = $('#key').val().replace(/\s+/g, '');
|
||||
var formatted = "";
|
||||
for (var i = 1; i <= text.length; i++) {
|
||||
formatted = formatted + text[i - 1];
|
||||
if (i % 5 == 0 && i > 1 && i < text.length) {
|
||||
// add a space every 5 characters,
|
||||
// unless it's the first character
|
||||
// or the last character
|
||||
formatted = formatted + " ";
|
||||
}
|
||||
}
|
||||
$('#key').val(formatted.toUpperCase());
|
||||
});
|
||||
|
||||
$('#username').on("keyup", function () {
|
||||
$('#username').val($('#username').val().toLowerCase());
|
||||
});
|
||||
|
||||
function manualsetup() {
|
||||
if ($('#syncurl').val().toLowerCase().startsWith("http")) {
|
||||
var syncurl = $('#syncurl').val();
|
||||
} else {
|
||||
var syncurl = $('#protocol-select').text() + $('#syncurl').val();
|
||||
}
|
||||
var username = $('#username').val();
|
||||
var key = $('#key').val().replace(/\s+/g, '');
|
||||
checkAndSave(syncurl, username, key);
|
||||
}
|
||||
|
||||
function manualshow() {
|
||||
$('#manual_setup').css('display', 'block');
|
||||
}
|
||||
|
||||
function checkAndSave(syncurl, username, key) {
|
||||
$.post(syncurl, {
|
||||
username: username,
|
||||
key: key,
|
||||
action: "check_key"
|
||||
}, function (data) {
|
||||
if (data.status === 'OK') {
|
||||
setupusername = username;
|
||||
setupsyncurl = syncurl;
|
||||
setupsynckey = key;
|
||||
router.navigate({
|
||||
name: 'setup2'
|
||||
});
|
||||
} else {
|
||||
navigator.notification.alert(data.msg, null, "Error", 'Dismiss');
|
||||
}
|
||||
}, "json").fail(function () {
|
||||
navigator.notification.alert("Could not connect to the server. Try again.", null, "Error", 'Dismiss');
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function scanCode() {
|
||||
try {
|
||||
cordova.plugins.barcodeScanner.scan(
|
||||
function (result) {
|
||||
if (!result.cancelled) {
|
||||
if (!result.text.startsWith("bizsync://")) {
|
||||
navigator.notification.alert("Invalid sync code. Try again.", null, "Error", 'Dismiss');
|
||||
return;
|
||||
}
|
||||
var url = result.text.replace("bizsync://", "");
|
||||
var parts = url.split("/");
|
||||
var syncurl = parts[0].replace(/\\/g, "/");
|
||||
var username = parts[1];
|
||||
var key = parts[2];
|
||||
checkAndSave(syncurl, username, key);
|
||||
}
|
||||
},
|
||||
function (error) {
|
||||
navigator.notification.alert("Scanning failed: " + error, null, "Error", 'Dismiss');
|
||||
},
|
||||
{
|
||||
"showFlipCameraButton": false,
|
||||
"prompt": "Scan mobile sync QR code."
|
||||
}
|
||||
);
|
||||
} catch (ex) {
|
||||
navigator.notification.alert(ex.message, null, "Error", 'Dismiss');
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
/* 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/. */
|
||||
|
||||
|
||||
.app-icon {
|
||||
border: 1px solid grey;
|
||||
border-radius: 20%;
|
||||
}
|
Before Width: | Height: | Size: 199 B After Width: | Height: | Size: 199 B |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 274 B After Width: | Height: | Size: 274 B |
Before Width: | Height: | Size: 389 B After Width: | Height: | Size: 389 B |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 320 B After Width: | Height: | Size: 320 B |
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
@ -0,0 +1,320 @@
|
||||
/*
|
||||
Based on the file
|
||||
https://github.com/srekanui/google-material-color-palette-json/blob/master/lib/palette.json
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2016 Sravan Kumar Rekandar
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
_PALETTE = {
|
||||
"red": {
|
||||
"shade_50": "#ffebee",
|
||||
"shade_100": "#ffcdd2",
|
||||
"shade_200": "#ef9a9a",
|
||||
"shade_300": "#e57373",
|
||||
"shade_400": "#ef5350",
|
||||
"shade_500": "#f44336",
|
||||
"shade_600": "#e53935",
|
||||
"shade_700": "#d32f2f",
|
||||
"shade_800": "#c62828",
|
||||
"shade_900": "#b71c1c",
|
||||
"shade_A100": "#ff8a80",
|
||||
"shade_A200": "#ff5252",
|
||||
"shade_A400": "#ff1744",
|
||||
"shade_A700": "#d50000"
|
||||
},
|
||||
"pink": {
|
||||
"shade_50": "#fce4ec",
|
||||
"shade_100": "#f8bbd0",
|
||||
"shade_200": "#f48fb1",
|
||||
"shade_300": "#f06292",
|
||||
"shade_400": "#ec407a",
|
||||
"shade_500": "#e91e63",
|
||||
"shade_600": "#d81b60",
|
||||
"shade_700": "#c2185b",
|
||||
"shade_800": "#ad1457",
|
||||
"shade_900": "#880e4f",
|
||||
"shade_A100": "#ff80ab",
|
||||
"shade_A200": "#ff4081",
|
||||
"shade_A400": "#f50057",
|
||||
"shade_A700": "#c51162"
|
||||
},
|
||||
"purple": {
|
||||
"shade_50": "#f3e5f5",
|
||||
"shade_100": "#e1bee7",
|
||||
"shade_200": "#ce93d8",
|
||||
"shade_300": "#ba68c8",
|
||||
"shade_400": "#ab47bc",
|
||||
"shade_500": "#9c27b0",
|
||||
"shade_600": "#8e24aa",
|
||||
"shade_700": "#7b1fa2",
|
||||
"shade_800": "#6a1b9a",
|
||||
"shade_900": "#4a148c",
|
||||
"shade_A100": "#ea80fc",
|
||||
"shade_A200": "#e040fb",
|
||||
"shade_A400": "#d500f9",
|
||||
"shade_A700": "#aa00ff"
|
||||
},
|
||||
"deepPurple": {
|
||||
"shade_50": "#ede7f6",
|
||||
"shade_100": "#d1c4e9",
|
||||
"shade_200": "#b39ddb",
|
||||
"shade_300": "#9575cd",
|
||||
"shade_400": "#7e57c2",
|
||||
"shade_500": "#673ab7",
|
||||
"shade_600": "#5e35b1",
|
||||
"shade_700": "#512da8",
|
||||
"shade_800": "#4527a0",
|
||||
"shade_900": "#311b92",
|
||||
"shade_A100": "#b388ff",
|
||||
"shade_A200": "#7c4dff",
|
||||
"shade_A400": "#651fff",
|
||||
"shade_A700": "#6200ea"
|
||||
},
|
||||
"indigo": {
|
||||
"shade_50": "#e8eaf6",
|
||||
"shade_100": "#c5cae9",
|
||||
"shade_200": "#9fa8da",
|
||||
"shade_300": "#7986cb",
|
||||
"shade_400": "#5c6bc0",
|
||||
"shade_500": "#3f51b5",
|
||||
"shade_600": "#3949ab",
|
||||
"shade_700": "#303f9f",
|
||||
"shade_800": "#283593",
|
||||
"shade_900": "#1a237e",
|
||||
"shade_A100": "#8c9eff",
|
||||
"shade_A200": "#536dfe",
|
||||
"shade_A400": "#3d5afe",
|
||||
"shade_A700": "#304ffe"
|
||||
},
|
||||
"blue": {
|
||||
"shade_50": "#e3f2fd",
|
||||
"shade_100": "#bbdefb",
|
||||
"shade_200": "#90caf9",
|
||||
"shade_300": "#64b5f6",
|
||||
"shade_400": "#42a5f5",
|
||||
"shade_500": "#2196f3",
|
||||
"shade_600": "#1e88e5",
|
||||
"shade_700": "#1976d2",
|
||||
"shade_800": "#1565c0",
|
||||
"shade_900": "#0d47a1",
|
||||
"shade_A100": "#82b1ff",
|
||||
"shade_A200": "#448aff",
|
||||
"shade_A400": "#2979ff",
|
||||
"shade_A700": "#2962ff"
|
||||
},
|
||||
"lightBlue": {
|
||||
"shade_50": "#e1f5fe",
|
||||
"shade_100": "#b3e5fc",
|
||||
"shade_200": "#81d4fa",
|
||||
"shade_300": "#4fc3f7",
|
||||
"shade_400": "#29b6f6",
|
||||
"shade_500": "#03a9f4",
|
||||
"shade_600": "#039be5",
|
||||
"shade_700": "#0288d1",
|
||||
"shade_800": "#0277bd",
|
||||
"shade_900": "#01579b",
|
||||
"shade_A100": "#80d8ff",
|
||||
"shade_A200": "#40c4ff",
|
||||
"shade_A400": "#00b0ff",
|
||||
"shade_A700": "#0091ea"
|
||||
},
|
||||
"cyan": {
|
||||
"shade_50": "#e0f7fa",
|
||||
"shade_100": "#b2ebf2",
|
||||
"shade_200": "#80deea",
|
||||
"shade_300": "#4dd0e1",
|
||||
"shade_400": "#26c6da",
|
||||
"shade_500": "#00bcd4",
|
||||
"shade_600": "#00acc1",
|
||||
"shade_700": "#0097a7",
|
||||
"shade_800": "#00838f",
|
||||
"shade_900": "#006064",
|
||||
"shade_A100": "#84ffff",
|
||||
"shade_A200": "#18ffff",
|
||||
"shade_A400": "#00e5ff",
|
||||
"shade_A700": "#00b8d4"
|
||||
},
|
||||
"teal": {
|
||||
"shade_50": "#e0f2f1",
|
||||
"shade_100": "#b2dfdb",
|
||||
"shade_200": "#80cbc4",
|
||||
"shade_300": "#4db6ac",
|
||||
"shade_400": "#26a69a",
|
||||
"shade_500": "#009688",
|
||||
"shade_600": "#00897b",
|
||||
"shade_700": "#00796b",
|
||||
"shade_800": "#00695c",
|
||||
"shade_900": "#004d40",
|
||||
"shade_A100": "#a7ffeb",
|
||||
"shade_A200": "#64ffda",
|
||||
"shade_A400": "#1de9b6",
|
||||
"shade_A700": "#00bfa5"
|
||||
},
|
||||
"green": {
|
||||
"shade_50": "#e8f5e9",
|
||||
"shade_100": "#c8e6c9",
|
||||
"shade_200": "#a5d6a7",
|
||||
"shade_300": "#81c784",
|
||||
"shade_400": "#66bb6a",
|
||||
"shade_500": "#4caf50",
|
||||
"shade_600": "#43a047",
|
||||
"shade_700": "#388e3c",
|
||||
"shade_800": "#2e7d32",
|
||||
"shade_900": "#1b5e20",
|
||||
"shade_A100": "#b9f6ca",
|
||||
"shade_A200": "#69f0ae",
|
||||
"shade_A400": "#00e676",
|
||||
"shade_A700": "#00c853"
|
||||
},
|
||||
"lightGreen": {
|
||||
"shade_50": "#f1f8e9",
|
||||
"shade_100": "#dcedc8",
|
||||
"shade_200": "#c5e1a5",
|
||||
"shade_300": "#aed581",
|
||||
"shade_400": "#9ccc65",
|
||||
"shade_500": "#8bc34a",
|
||||
"shade_600": "#7cb342",
|
||||
"shade_700": "#689f38",
|
||||
"shade_800": "#558b2f",
|
||||
"shade_900": "#33691e",
|
||||
"shade_A100": "#ccff90",
|
||||
"shade_A200": "#b2ff59",
|
||||
"shade_A400": "#76ff03",
|
||||
"shade_A700": "#64dd17"
|
||||
},
|
||||
"lime": {
|
||||
"shade_50": "#f9fbe7",
|
||||
"shade_100": "#f0f4c3",
|
||||
"shade_200": "#e6ee9c",
|
||||
"shade_300": "#dce775",
|
||||
"shade_400": "#d4e157",
|
||||
"shade_500": "#cddc39",
|
||||
"shade_600": "#c0ca33",
|
||||
"shade_700": "#afb42b",
|
||||
"shade_800": "#9e9d24",
|
||||
"shade_900": "#827717",
|
||||
"shade_A100": "#f4ff81",
|
||||
"shade_A200": "#eeff41",
|
||||
"shade_A400": "#c6ff00",
|
||||
"shade_A700": "#aeea00"
|
||||
},
|
||||
"yellow": {
|
||||
"shade_50": "#fffde7",
|
||||
"shade_100": "#fff9c4",
|
||||
"shade_200": "#fff59d",
|
||||
"shade_300": "#fff176",
|
||||
"shade_400": "#ffee58",
|
||||
"shade_500": "#ffeb3b",
|
||||
"shade_600": "#fdd835",
|
||||
"shade_700": "#fbc02d",
|
||||
"shade_800": "#f9a825",
|
||||
"shade_900": "#f57f17",
|
||||
"shade_A100": "#ffff8d",
|
||||
"shade_A200": "#ffff00",
|
||||
"shade_A400": "#ffea00",
|
||||
"shade_A700": "#ffd600"
|
||||
},
|
||||
"amber": {
|
||||
"shade_50": "#fff8e1",
|
||||
"shade_100": "#ffecb3",
|
||||
"shade_200": "#ffe082",
|
||||
"shade_300": "#ffd54f",
|
||||
"shade_400": "#ffca28",
|
||||
"shade_500": "#ffc107",
|
||||
"shade_600": "#ffb300",
|
||||
"shade_700": "#ffa000",
|
||||
"shade_800": "#ff8f00",
|
||||
"shade_900": "#ff6f00",
|
||||
"shade_A100": "#ffe57f",
|
||||
"shade_A200": "#ffd740",
|
||||
"shade_A400": "#ffc400",
|
||||
"shade_A700": "#ffab00"
|
||||
},
|
||||
"orange": {
|
||||
"shade_50": "#fff3e0",
|
||||
"shade_100": "#ffe0b2",
|
||||
"shade_200": "#ffcc80",
|
||||
"shade_300": "#ffb74d",
|
||||
"shade_400": "#ffa726",
|
||||
"shade_500": "#ff9800",
|
||||
"shade_600": "#fb8c00",
|
||||
"shade_700": "#f57c00",
|
||||
"shade_800": "#ef6c00",
|
||||
"shade_900": "#e65100",
|
||||
"shade_A100": "#ffd180",
|
||||
"shade_A200": "#ffab40",
|
||||
"shade_A400": "#ff9100",
|
||||
"shade_A700": "#ff6d00"
|
||||
},
|
||||
"deepOrange": {
|
||||
"shade_50": "#fbe9e7",
|
||||
"shade_100": "#ffccbc",
|
||||
"shade_200": "#ffab91",
|
||||
"shade_300": "#ff8a65",
|
||||
"shade_400": "#ff7043",
|
||||
"shade_500": "#ff5722",
|
||||
"shade_600": "#f4511e",
|
||||
"shade_700": "#e64a19",
|
||||
"shade_800": "#d84315",
|
||||
"shade_900": "#bf360c",
|
||||
"shade_A100": "#ff9e80",
|
||||
"shade_A200": "#ff6e40",
|
||||
"shade_A400": "#ff3d00",
|
||||
"shade_A700": "#dd2c00"
|
||||
},
|
||||
"brown": {
|
||||
"shade_50": "#efebe9",
|
||||
"shade_100": "#d7ccc8",
|
||||
"shade_200": "#bcaaa4",
|
||||
"shade_300": "#a1887f",
|
||||
"shade_400": "#8d6e63",
|
||||
"shade_500": "#795548",
|
||||
"shade_600": "#6d4c41",
|
||||
"shade_700": "#5d4037",
|
||||
"shade_800": "#4e342e",
|
||||
"shade_900": "#3e2723"
|
||||
},
|
||||
"grey": {
|
||||
"shade_50": "#fafafa",
|
||||
"shade_100": "#f5f5f5",
|
||||
"shade_200": "#eeeeee",
|
||||
"shade_300": "#e0e0e0",
|
||||
"shade_400": "#bdbdbd",
|
||||
"shade_500": "#9e9e9e",
|
||||
"shade_600": "#757575",
|
||||
"shade_700": "#616161",
|
||||
"shade_800": "#424242",
|
||||
"shade_900": "#212121"
|
||||
},
|
||||
"blueGrey": {
|
||||
"shade_50": "#eceff1",
|
||||
"shade_100": "#cfd8dc",
|
||||
"shade_200": "#b0bec5",
|
||||
"shade_300": "#90a4ae",
|
||||
"shade_400": "#78909c",
|
||||
"shade_500": "#607d8b",
|
||||
"shade_600": "#546e7a",
|
||||
"shade_700": "#455a64",
|
||||
"shade_800": "#37474f",
|
||||
"shade_900": "#263238"
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
<!-- 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/. -->
|
||||
<div class="page" data-name="app">
|
||||
<iframe id="appframe" src="" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: 0px;"></iframe>
|
||||
</div>
|
@ -0,0 +1,42 @@
|
||||
<!-- 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/. -->
|
||||
<div class="page" data-name="home">
|
||||
|
||||
<div class="navbar">
|
||||
<div class="navbar-inner">
|
||||
<div class="title">Business</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--<div class="toolbar">
|
||||
<div class="toolbar-inner">
|
||||
<a href="#" class="link">Link 1</a>
|
||||
<a href="#" class="link">Link 2</a>
|
||||
</div>
|
||||
</div>-->
|
||||
|
||||
<div class="page-content">
|
||||
<div class="card">
|
||||
<div class="card-header">Apps</div>
|
||||
<div class="card-content">
|
||||
<div class="list media-list">
|
||||
<ul id="applist">
|
||||
{{#each appcards}}
|
||||
<li class="item-content applist-item" data-api="{{api}}" data-url="{{url}}" data-icon="{{icon}}" data-title="{{title}}" >
|
||||
<div class="item-media"><img src="{{icon}}" width="44"/></div>
|
||||
<div class="item-inner">
|
||||
<div class="item-title-row">
|
||||
<div class="item-title">{{title}}</div>
|
||||
</div>
|
||||
<div class="item-subtitle">{{text}}</div>
|
||||
</div>
|
||||
</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
@ -0,0 +1,78 @@
|
||||
<!-- 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/. -->
|
||||
|
||||
<div class="page" data-name="setup1">
|
||||
|
||||
<div class="navbar">
|
||||
<div class="navbar-inner">
|
||||
<div class="title">Link Account</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="page-content">
|
||||
|
||||
<div class="block">
|
||||
<p>Open AccountHub on another device and go to Sync settings. Generate a mobile sync code, then press the button below to scan it.</p>
|
||||
|
||||
<div class="row">
|
||||
<button class="col button button-fill" onclick="scanCode()" id="scancodebtn">Scan Code</button>
|
||||
<button class="col button" onclick="manualshow()" id="manualsetupbtn">Manual Setup</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="manual_setup" class="block" style="display: none;">
|
||||
|
||||
<div class="list">
|
||||
<ul>
|
||||
<li class="item-content item-input">
|
||||
<div class="item-inner">
|
||||
<div class="item-input-wrap">
|
||||
<input type="text" id="username" placeholder="Username" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" />
|
||||
<span class="input-clear-button"></span>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="item-content item-input">
|
||||
<div class="item-inner">
|
||||
<div class="item-input-wrap">
|
||||
<input type="text" id="key" class="form-control" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" />
|
||||
<span class="input-clear-button"></span>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="item-content item-input">
|
||||
<div class="item-inner">
|
||||
<div class="item-title item-floating-label" id="protocol-select">https://</div>
|
||||
<div class="item-input-wrap">
|
||||
<input type="url" id="syncurl" placeholder="URL" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" />
|
||||
<span class="input-clear-button"></span>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<label class="item-checkbox item-content">
|
||||
<input type="checkbox" id="use-security" checked="checked" />
|
||||
<i class="icon icon-checkbox"></i>
|
||||
<span class="item-inner">
|
||||
<span class="item-title">Use secure connection</span>
|
||||
</span>
|
||||
</label>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="button button-fill" onclick="manualsetup()">
|
||||
Continue
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<script src="js/setup1.js"></script>
|
||||
|
||||
</div>
|
@ -0,0 +1,61 @@
|
||||
<!-- 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/. -->
|
||||
|
||||
<div class="page" data-name="setup2">
|
||||
|
||||
<div class="navbar">
|
||||
<div class="navbar-inner">
|
||||
<div class="title">Link Account</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="page-content">
|
||||
|
||||
<div class="block">
|
||||
<p>Enter your password, then tap Finish.</p>
|
||||
|
||||
<div class="list">
|
||||
<ul>
|
||||
<li class="item-content item-input">
|
||||
<div class="item-media"><i class="fas fa-key"></i></div>
|
||||
<div class="item-inner">
|
||||
<div class="item-input-wrap">
|
||||
<input type="password" id="passbox" placeholder="Password">
|
||||
<span class="input-clear-button"></span>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<button class="button button-fill" onclick="savePassword()">Finish</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function savePassword() {
|
||||
$.post(setupsyncurl, {
|
||||
username: setupusername,
|
||||
key: setupsynckey,
|
||||
password: $('#passbox').val(),
|
||||
action: "check_password"
|
||||
}, function (data) {
|
||||
if (data.status === 'OK') {
|
||||
setuppassword = $('#passbox').val();
|
||||
var accid = addaccount(setupusername, setuppassword, setupsyncurl, setupsynckey);
|
||||
switchaccount(accid);
|
||||
localStorage.setItem("firstrun", "1");
|
||||
navigator.notification.alert("Account connected!", null, "Success", 'Continue');
|
||||
restartApplication();
|
||||
} else {
|
||||
navigator.notification.alert(data.msg, null, "Error", 'Dismiss');
|
||||
}
|
||||
}, "json").fail(function () {
|
||||
navigator.notification.alert("Could not connect to the server. Try again later.", null, "Error", 'Dismiss');
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</div>
|
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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 routes = [
|
||||
{
|
||||
path: '/home',
|
||||
templateUrl: './pages/home.html',
|
||||
name: 'home'
|
||||
},
|
||||
{
|
||||
path: '/setup/1',
|
||||
url: './pages/setup1.html',
|
||||
name: 'setup1'
|
||||
},
|
||||
{
|
||||
path: '/setup/2',
|
||||
url: './pages/setup2.html',
|
||||
name: 'setup2'
|
||||
},
|
||||
{
|
||||
path: '/app',
|
||||
url: './pages/app.html',
|
||||
name: 'app'
|
||||
}
|
||||
];
|
@ -1,174 +0,0 @@
|
||||
<!-- 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/. -->
|
||||
<iframe id="appframe" src="" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: 0px;"></iframe>
|
||||
<iframe id="loadframe" src="views/appspinner.html" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: 0px; z-index: 999999;"></iframe>
|
||||
|
||||
<script src="js/material-palette.js"></script>
|
||||
<script>
|
||||
var historyctr = -1;
|
||||
/**
|
||||
* Open an app with native Android UI elements
|
||||
* @param String id Application ID
|
||||
* @param String api Path to the mobile API
|
||||
* @param String url Base URL of the app
|
||||
* @param String icon URL to the app icon
|
||||
* @param String title Friendly app name
|
||||
* @param boolean injectcode (optional, default true) Whether or not to inject UI modification code into the app
|
||||
* @param boolean shownavbar (optional, default false) Whether or not to show the navbar at the top of the screen.
|
||||
* @returns {undefined}
|
||||
*/
|
||||
function launchapp(id, api, url, icon, title, injectcode, shownavbar) {
|
||||
if (typeof shownavbar === 'undefined' || shownavbar === false) {
|
||||
setnavbar(false);
|
||||
} else {
|
||||
setnavbar("app", title);
|
||||
$('#appframe').css('top', '75px');
|
||||
}
|
||||
$.post(url + api, {
|
||||
username: localStorage.getItem("username"),
|
||||
key: localStorage.getItem("key"),
|
||||
password: localStorage.getItem("password"),
|
||||
action: "start_session"
|
||||
}, function (data) {
|
||||
if (data.status === 'OK') {
|
||||
document.getElementById("loadframe").contentWindow.postMessage("loginok", "*");
|
||||
if (typeof injectcode === 'undefined' || injectcode === true) {
|
||||
$('#appframe').on("load", function () {
|
||||
$("#loadframe").fadeOut(300);
|
||||
historyctr++;
|
||||
// Do this right away so it's a bit harder to glitch
|
||||
$('#appframe').contents().find('.navbar-right').html("<li><a onclick='quitapp()'><i class='fa fa-sign-out fa-fw'></i> Back to Menu</a></li>");
|
||||
// Moved BS4 code to sidemenu.js
|
||||
$.get("css/sidemenu.css", function (style) {
|
||||
$('#appframe').contents().find('head').append("<style>" + style + "</style>");
|
||||
$.get("js/polyfills.js", function (script) {
|
||||
$('#appframe').contents().find('body').append("<script>" + script + "<\/script>");
|
||||
$.get("js/jquery-ui.min.js", function (script) {
|
||||
$('#appframe').contents().find('body').append("<script>" + script + "<\/script>");
|
||||
$.get("js/hammer.min.js", function (script) {
|
||||
$('#appframe').contents().find('body').append("<script>" + script + "<\/script>");
|
||||
$.get("js/sidemenu.js", function (script) {
|
||||
script = script.replace("__JQUERYFXOFF__", !(localStorage.getItem("animations") === null || localStorage.getItem("animations") === "true"));
|
||||
script = script.replace("__USERNAME__", userinfo.realname);
|
||||
script = script.replace("__LOGO__", icon);
|
||||
$('#appframe').contents().find('body').append("<script>" + script + "<\/script>");
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
} else {
|
||||
// Only inject minimal CSS
|
||||
$('#appframe').on("load", function () {
|
||||
$.get("css/inject_mini.css", function (style) {
|
||||
$('#appframe').contents().find('head').append("<style>" + style + "</style>");
|
||||
});
|
||||
});
|
||||
}
|
||||
$('#appframe').attr('src', url);
|
||||
} else {
|
||||
navigator.notification.alert(data.msg, null, "Error", 'Dismiss');
|
||||
openscreen("home");
|
||||
}
|
||||
}, "json").fail(function () {
|
||||
navigator.notification.alert("Could not connect to the server. Try again later.", null, "Error", 'Dismiss');
|
||||
openscreen("home");
|
||||
});
|
||||
}
|
||||
|
||||
var scanningactive = false;
|
||||
var dedup = [];
|
||||
window.addEventListener('message', function (event) {
|
||||
console.log("app event: " + event.data);
|
||||
setTimeout(function () {
|
||||
dedup = [];
|
||||
}, 500);
|
||||
if (dedup.includes(event.data)) {
|
||||
return;
|
||||
}
|
||||
dedup.push(event.data);
|
||||
if (event.data == "quit") {
|
||||
openscreen("home");
|
||||
} else if (event.data == "goneback") {
|
||||
historyctr -= 1;
|
||||
} else if (event.data.startsWith("load_bs_version ")) {
|
||||
var bootstrap_version = event.data.split(" ")[1];
|
||||
var nav_breakpoint = event.data.split(" ")[2];
|
||||
var bs_file = "bs3";
|
||||
if (bootstrap_version.startsWith("4")) {
|
||||
bs_file = "bs4";
|
||||
}
|
||||
$.get("css/sidemenu-" + bs_file + ".css", function (style) {
|
||||
if (bs_file == "bs4") {
|
||||
var break_px = "767";
|
||||
switch (nav_breakpoint) {
|
||||
case "sm":
|
||||
break_px = "575";
|
||||
break;
|
||||
case "md":
|
||||
break_px = "767";
|
||||
break;
|
||||
case "lg":
|
||||
break_px = "991";
|
||||
break;
|
||||
case "xl":
|
||||
break_px = "1199";
|
||||
break;
|
||||
}
|
||||
style = style.replace("max-width: 767px", "max-width: " + break_px + "px");
|
||||
}
|
||||
$('#appframe').contents().find('head').append("<style>" + style + "</style>");
|
||||
});
|
||||
} else if (event.data.startsWith("setcolor ")) {
|
||||
var color = event.data.split(" ", 2)[1];
|
||||
if (cordova.platformId == 'android') {
|
||||
window.plugins.headerColor.tint(color);
|
||||
for (var swatch in _PALETTE) {
|
||||
if (color == _PALETTE[swatch]["shade_500"]) {
|
||||
StatusBar.backgroundColorByHexString(_PALETTE[swatch]["shade_700"]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
StatusBar.backgroundColorByHexString(shadeColor2(color, -0.1));
|
||||
} else {
|
||||
StatusBar.backgroundColorByHexString(color);
|
||||
}
|
||||
} else if (event.data.startsWith("scancode ")) {
|
||||
var callbackcode = event.data.split(" ").slice(1).join(" ");
|
||||
console.log("got scancode " + callbackcode);
|
||||
try {
|
||||
if (scanningactive) {
|
||||
console.log("Scanner already active, ignoring request.");
|
||||
return;
|
||||
}
|
||||
scanningactive = true;
|
||||
cordova.plugins.barcodeScanner.scan(
|
||||
function (result) {
|
||||
scanningactive = false;
|
||||
if (!result.cancelled) {
|
||||
var iframe = document.getElementById("appframe");
|
||||
iframe.contentWindow.postMessage("coderesult~|~" + callbackcode + "~|~" + result.text, "*");
|
||||
}
|
||||
},
|
||||
function (error) {
|
||||
scanningactive = false;
|
||||
navigator.notification.alert("Scanning failed: " + error, null, "Error", 'Dismiss');
|
||||
},
|
||||
{
|
||||
"showFlipCameraButton": true,
|
||||
"prompt": "Scan Code"
|
||||
}
|
||||
);
|
||||
} catch (ex) {
|
||||
scanningactive = false;
|
||||
navigator.notification.alert(ex.message, null, "Error", 'Dismiss');
|
||||
}
|
||||
}
|
||||
}, false);
|
||||
|
||||
if (userinfo == null) {
|
||||
getuserinfo();
|
||||
}
|
||||
</script>
|
@ -1,76 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<!-- 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/. -->
|
||||
|
||||
<title>Loading</title>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<style>
|
||||
html, body {
|
||||
height: 100%;
|
||||
background-color: white;
|
||||
font-family: "Roboto","Helvetica Neue",Helvetica,Arial,sans-serif;
|
||||
}
|
||||
|
||||
body {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
#statustext {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#giveup {
|
||||
display: none;
|
||||
margin-top: 5px;
|
||||
border: none;
|
||||
border-radius: 3px;
|
||||
box-shadow: 1px 1px 4px rgba(0,0,0,0.4);
|
||||
padding: 6px 16px;
|
||||
font-size: 13px;
|
||||
line-height: 1.846;
|
||||
color: #fff;
|
||||
background-color: #2196f3;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
touch-action: manipulation;
|
||||
white-space: nowrap;
|
||||
text-decoration: none;
|
||||
box-sizing: border-box;
|
||||
text-transform: uppercase;
|
||||
position: relative;
|
||||
}
|
||||
</style>
|
||||
|
||||
<img src="cdvfile://localhost/assets/www/img/loader.gif" style="width: 65px; height: 65px;" alt="" onerror="this.onerror=null;this.src='cdvfile://localhost/bundle/www/img/loader.gif';"/>
|
||||
|
||||
<p id="statustext">Logging in...</p>
|
||||
<br />
|
||||
<div id="giveup" onclick="parent.postMessage('quit', '*');">Give up</div>
|
||||
<script>
|
||||
window.addEventListener('message', function (event) {
|
||||
if (event.data == "loginok") {
|
||||
document.getElementById("statustext").innerHTML = "Loading...";
|
||||
setTimeout(function () {
|
||||
document.getElementById("statustext").innerHTML = "Still loading...";
|
||||
}, 5000);
|
||||
setTimeout(function () {
|
||||
document.getElementById("statustext").innerHTML = "Just a moment...";
|
||||
document.getElementById("giveup").style.display = "inline-block";
|
||||
}, 10000);
|
||||
setTimeout(function () {
|
||||
document.getElementById("statustext").innerHTML = "Well this is awkward.";
|
||||
}, 20000);
|
||||
setTimeout(function () {
|
||||
document.getElementById("statustext").innerHTML = "[fidgets nervously]";
|
||||
}, 25000);
|
||||
setTimeout(function () {
|
||||
document.getElementById("statustext").innerHTML = "Either something is broken or your connection is too slow.";
|
||||
}, 30000);
|
||||
}
|
||||
});
|
||||
</script>
|
@ -1,49 +0,0 @@
|
||||
<!-- 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/. -->
|
||||
<div class="app-dock-container">
|
||||
<div class="app-dock" id="app-dock">
|
||||
<div style="margin-top: 50px;">
|
||||
<img src="img/loader.gif" style="width: 65px; height: 65px;" alt=""/>
|
||||
</div>
|
||||
<div style="width: 100%;"></div>
|
||||
<p class="loading-text">Loading...</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function loadapps() {
|
||||
$(".loading-text").html("Loading Apps...");
|
||||
$.post(localStorage.getItem("syncurl"), {
|
||||
username: localStorage.getItem("username"),
|
||||
key: localStorage.getItem("key"),
|
||||
action: "listapps"
|
||||
}, function (data) {
|
||||
if (data.status === 'OK') {
|
||||
$("#loading-text").text("One moment...");
|
||||
$('#app-dock').html("");
|
||||
Object.keys(data.apps).forEach(function (k) {
|
||||
var app = data.apps[k];
|
||||
var iconurl = app.icon;
|
||||
if (!app.icon.startsWith("http")) {
|
||||
iconurl = app.url + app.icon;
|
||||
}
|
||||
$("<div class=\"app-dock-item\" onclick=\"openapp('" + k + "', '" + app.mobileapi + "', '" + app.url + "', '" + iconurl + "', '" + app.title + "')\"><p><img src=\"" + iconurl + "\" class=\"img-responsive app-icon\" /><span>" + app.title + "</span></p></div>").hide().appendTo("#app-dock").fadeIn(200);
|
||||
});
|
||||
} else {
|
||||
navigator.notification.alert(data.msg, null, "Error", 'Dismiss');
|
||||
openscreen("homeloaderror");
|
||||
}
|
||||
}, "json").fail(function () {
|
||||
navigator.notification.alert("Could not connect to the server. Try again later.", null, "Error", 'Dismiss');
|
||||
openscreen("homeloaderror");
|
||||
});
|
||||
}
|
||||
|
||||
if (isconfigvalid()) {
|
||||
setnavbar("home");
|
||||
loadapps();
|
||||
} else {
|
||||
openscreen("setup1");
|
||||
}
|
||||
</script>
|
@ -1,163 +0,0 @@
|
||||
<!-- 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/. -->
|
||||
<br />
|
||||
<div class="panel panel-blue">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title" id="setuptitle">Add Account</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p>
|
||||
<span class="firstrun-only" style="display: none;">
|
||||
Welcome! There's a few things we need to do to get everything ready.
|
||||
<br /><br />
|
||||
</span>
|
||||
Open AccountHub on another device and go to Sync settings. Generate a mobile sync code, then press the button below to scan it.
|
||||
</p>
|
||||
<span class="btn btn-primary" onclick="scanCode()" id="scancodebtn">
|
||||
<i class="fa fa-qrcode"></i> Scan Code
|
||||
</span>
|
||||
<span class="btn btn-link" onclick="manualshow()" id="manualsetupbtn">
|
||||
Manual Setup
|
||||
</span>
|
||||
<div id="manual_setup" class="well" style="display: none;">
|
||||
<input type="text" id="username" class="form-control" placeholder="Username" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" /> <br />
|
||||
<input type="text" id="key" class="form-control" placeholder="Sync key" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" /> <br />
|
||||
<div class="input-group" style="margin-left: -20px;">
|
||||
<span class="input-group-addon" id="protocol-select">https://</span>
|
||||
<input type="text" id="syncurl" class="form-control" placeholder="URL" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" />
|
||||
</div> <br />
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" id="use-security" checked > Use secure connection
|
||||
</label>
|
||||
</div>
|
||||
<br />
|
||||
<div class="btn btn-primary" onclick="manualsetup()">
|
||||
Continue
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
setupusername = "";
|
||||
setuppassword = "";
|
||||
setupsynckey = "";
|
||||
setupsyncurl = "";
|
||||
|
||||
if (localStorage.getItem("firstrun") === null) {
|
||||
$("#setuptitle").text("Setup");
|
||||
$(".firstrun-only").css("display", "");
|
||||
}
|
||||
|
||||
$('#use-security').click(function () {
|
||||
if (this.checked) {
|
||||
$('#protocol-select').text("https://");
|
||||
} else {
|
||||
$('#protocol-select').text("http://");
|
||||
}
|
||||
});
|
||||
|
||||
/* Detect if the user typed "http[s]://" into the URL box and correct for it */
|
||||
$("#syncurl").blur(function () {
|
||||
if ($('#syncurl').val().toLowerCase().startsWith("https://")) {
|
||||
$('#syncurl').val($('#syncurl').val().replace(/https\:\/\//ig, ""));
|
||||
$('#protocol-select').text("https://");
|
||||
$('#use-security').prop('checked', true);
|
||||
} else if ($('#syncurl').val().toLowerCase().startsWith("http://")) {
|
||||
$('#syncurl').val($('#syncurl').val().replace(/http\:\/\//ig, ""));
|
||||
$('#protocol-select').text("http://");
|
||||
$('#use-security').prop('checked', false);
|
||||
}
|
||||
});
|
||||
|
||||
$("#key").on("keyup", function () {
|
||||
if (window.getSelection().toString() !== '') {
|
||||
return;
|
||||
}
|
||||
var text = $('#key').val().replace(/\s+/g, '');
|
||||
var formatted = "";
|
||||
for (var i = 1; i <= text.length; i++) {
|
||||
formatted = formatted + text[i - 1];
|
||||
if (i % 5 == 0 && i > 1 && i < text.length) {
|
||||
// add a space every 5 characters,
|
||||
// unless it's the first character
|
||||
// or the last character
|
||||
formatted = formatted + " ";
|
||||
}
|
||||
}
|
||||
$('#key').val(formatted.toUpperCase());
|
||||
});
|
||||
|
||||
$('#username').on("keyup", function () {
|
||||
$('#username').val($('#username').val().toLowerCase());
|
||||
});
|
||||
|
||||
function manualsetup() {
|
||||
if ($('#syncurl').val().toLowerCase().startsWith("http")) {
|
||||
var syncurl = $('#syncurl').val();
|
||||
} else {
|
||||
var syncurl = $('#protocol-select').text() + $('#syncurl').val();
|
||||
}
|
||||
var username = $('#username').val();
|
||||
var key = $('#key').val().replace(/\s+/g, '');
|
||||
checkAndSave(syncurl, username, key);
|
||||
}
|
||||
|
||||
function manualshow() {
|
||||
$('#manual_setup').css('display', 'block');
|
||||
}
|
||||
|
||||
function checkAndSave(syncurl, username, key) {
|
||||
$.post(syncurl, {
|
||||
username: username,
|
||||
key: key,
|
||||
action: "check_key"
|
||||
}, function (data) {
|
||||
if (data.status === 'OK') {
|
||||
setupusername = username;
|
||||
setupsyncurl = syncurl;
|
||||
setupsynckey = key;
|
||||
openscreen("setup2");
|
||||
} else {
|
||||
navigator.notification.alert(data.msg, null, "Error", 'Dismiss');
|
||||
}
|
||||
}, "json").fail(function () {
|
||||
navigator.notification.alert("Could not connect to the server. Try again.", null, "Error", 'Dismiss');
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function scanCode() {
|
||||
try {
|
||||
cordova.plugins.barcodeScanner.scan(
|
||||
function (result) {
|
||||
if (!result.cancelled) {
|
||||
if (!result.text.startsWith("bizsync://")) {
|
||||
navigator.notification.alert("Invalid sync code. Try again.", null, "Error", 'Dismiss');
|
||||
return;
|
||||
}
|
||||
var url = result.text.replace("bizsync://", "");
|
||||
var parts = url.split("/");
|
||||
var syncurl = parts[0].replace(/\\/g, "/");
|
||||
var username = parts[1];
|
||||
var key = parts[2];
|
||||
checkAndSave(syncurl, username, key);
|
||||
}
|
||||
},
|
||||
function (error) {
|
||||
navigator.notification.alert("Scanning failed: " + error, null, "Error", 'Dismiss');
|
||||
},
|
||||
{
|
||||
"showFlipCameraButton": false,
|
||||
"prompt": "Scan mobile sync QR code."
|
||||
}
|
||||
);
|
||||
} catch (ex) {
|
||||
navigator.notification.alert(ex.message, null, "Error", 'Dismiss');
|
||||
}
|
||||
}
|
||||
|
||||
setnavbar("setup");
|
||||
</script>
|