You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2777 lines
137 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/*
* Copyright (c) 2016 bluefox https://github.com/GermanBluefox
* Changed Creative Common Attribution-NonCommercial (CC BY-NC)
*
* http://creativecommons.org/licenses/by-nc/4.0/
*
* ![CC BY-NC License](https://github.com/GermanBluefox/DashUI/raw/master/images/cc-nc-by.png)
*
* Following was added to license text:
*
* It is **prohibited** to publish this app or modifications of this app in any kind of mobile application stores (Google App Store, Amazon App Store, ...)
* or make possible to download the app from some online resources (forums, web sites, ...).
* Even if the name of the app is modified and it is free of charge you **may not** publish it or let others to use it.
*
* Short content:
* Licensees may copy, distribute, display and perform the work and make derivative works based on it only if they give the author or licensor the credits in the manner specified by these.
* Licensees may copy, distribute, display, and perform the work and make derivative works based on it only for personal purposes.
* (Free for personal use).
*/
var socketUrl;
var socketSession;
systemLang = 'en';
$.extend(systemDictionary, {
'Ok': {'en': 'Ok', 'de': 'Ok', 'ru': 'Ok'},
'Cancel': {'en': 'Cancel', 'de': 'Abbrechen', 'ru': 'Отмена'},
'Settings': {'en': 'Settings', 'de': 'Einstellungen', 'ru': 'Настройки'},
'Language': {'en': 'Language', 'de': 'Language/Sprache', 'ru': 'Language/Язык'},
'Socket': {'en': 'yunkong2 socket', 'de': 'yunkong2 socket', 'ru': 'yunkong2 сокет'},
'System': {'en': 'system', 'de': 'System', 'ru': 'системный'},
'Reload': {'en': 'Reload', 'de': 'Neuladen', 'ru': 'Обновить'},
'Re-sync': {'en': 'Re-sync', 'de': 'Re-sync', 'ru': 'Синхр.'},
'Instance': {'en': 'Instance', 'de': 'Instanz', 'ru': 'Идентификатор'},
'Not found': {'en': 'Not found', 'de': 'Nicht gefunden', 'ru': 'не найден'},
'Connected': {'en': 'Connected', 'de': 'Verbunden', 'ru': 'Соединение'},
"Project": {"en": "Project", "de": "Projekt", "ru": "Проект"},
"yes": {"en": "yes", "de": "ja", "ru": "есть"},
"no": {"en": "no", "de": "nein", "ru": "нет"},
"Keyword": {"en": "Keyword", "de": "Schlüsselwort", "ru": "Ключевое слово"},
"WIFI": {"en": "WiFi Connection", "de": "WiFi Verbindung", "ru": "WiFi соединение"},
"WIFI SSID": {"en": "Network name (SSID)", "de": "SSID Name", "ru": "Имя сети (SSID)"},
"WIFI Socket": {"en": "Socket URL", "de": "Socket URL", "ru": "Socket URL"},
"WIFI User": {"en": "User", "de": "Anwender", "ru": "Пользователь"},
"WIFI Password": {"en": "Password", "de": "Kennwort", "ru": "Пароль"},
"WIFI Password repeat": {
"en": "Password repeat",
"de": "Kennwort-Wiederholung",
"ru": "Повтор пароля"
},
"Actual": {"en": "<=", "de": "<=", "ru": "<="},
"Device name": {"en": "Device name", "de": "Gerätname", "ru": "Имя устройства"},
"Battery and location": {
"en": "Battery and location",
"de": "Batterie und Position",
"ru": "Зарядка и координаты"
},
"Report battery status": {
"en": "Report battery status",
"de": "Teile Batteriezustand mit",
"ru": "Сообщать уровень заряда батареи"
},
"Position poll interval (sec)": {
"en": "Position poll interval (sec)",
"de": "Abfrageintervall für Position (Sek)",
"ru": "Инетрвал опроса координат (сек)"
},
"High accuracy position": {
"en": "High accuracy position",
"de": "Hohe Genauigkeit",
"ru": "Точность позиционирования"
},
"Sleep in background": {
"en": "Sleep in background",
"de": "Schlafen, falls inaktiv",
"ru": "Спать, если не активно"
},
"Fullscreen": {
"en": "Full screen",
"de": "Vollbild",
"ru": "Полноэкранный режим"
},
"reading...": {"en": "reading...", "de": "abfragen...", "ru": "считывание..."},
"Cell": {"en": "Cell Connection", "de": "Mobile Verbindung", "ru": "Мобильное соединение"},
"Cell Socket": {"en": "Socket URL", "de": "Socket URL", "ru": "Socket URL"},
"Cell User": {"en": "Cell User", "de": "Anwender", "ru": "Пользователь"},
"Cell Password": {"en": "Cell Password", "de": "Kennwort", "ru": "Пароль"},
"Cell Password repeat": {
"en": "Password repeat",
"de": "Kennwort-Wiederholung",
"ru": "Повтор пароля"
},
"Speech recognition": {
"en": "Speech recognition",
"de": "Spracherkennung",
"ru": "Распознавание речи"
},
"Speech recognition active": {
"en": "Speech recognition active",
"de": "Spracherkennung aktiviert",
"ru": "Распознавание речи активно"
},
"Orientation": {
"en": "Orientation",
"de": "Ausrichtung",
"ru": "Ориенитация"
},
"orientation_auto": {
"en": "auto",
"de": "Ausrichtung",
"ru": "авто"
},
"orientation_portrait": {
"en": "portrait",
"de": "vertikale",
"ru": "портретная"
},
"orientation_landscape": {
"en": "landscape",
"de": "horizontale",
"ru": "горизонтальная"
},
"Zoom Level Portrait": {
"en": "Zoom Level Portrait",
"de": "Zoom Level Portrait",
"ru": "Зум при верт. положении"
},
"Substitution URL": {
"en": "Substitution URL",
"de": "Austausch URL",
"ru": "Замена URL"
},
"Zoom Level Landscape": {
"en": "Zoom Level Landscape",
"de": "Zoom Level Landscape",
"ru": "Зум при гор. положении"
},
"Use yunkong2.pro": {"en": "Use yunkong2.pro", "de": "Benutze yunkong2.pro", "ru": "Использовать yunkong2.pro"},
"Allow self-signed certificates": {"en": "Allow self-signed certificates", "de": "Erlaube selbssignierte Zertifikate", "ru": "Разрешить самоподписанные сертификаты"},
"none": {"en": "none", "de": "nichts", "ru": "нет выбора"},
"Volume": {
"en": "Speech volume",
"de": "Sprachlautstärke",
"ru": "Громкость речи"
},
"Allow window move": {
"en": "Allow window move",
"de": "Erlaube Fensterverschiebung",
"ru": "Разрешить сдвиг окна"
},
"Prevent from sleep": {
"en": "Prevent from sleep",
"de": "Einschlafen verhindern",
"ru": "Не засыпать"
},
"Text2command": {"en": "Text2command instance", "de": "Text2command-Instanz", "ru": "Экземпляр Text2command"},
"Default room": {"en": "Default room", "de": "Default Raum", "ru": "Комната по умолчанию"},
"Response over TTS": {"en": "Response over TTS", "de": "Antworten mit TTS", "ru": "Отвечать голосом"},
"Message": {"en": "Message", "de": "Meldung", "ru": "Сообщение"},
"Discard changes?": {"en": "Discard changes?", "de": "Die Änderungen sind nicht gespeichert. Ignorieren?", "ru": "Игнорировать изменения?"},
"Local write timeout (ms)": {"en": "Local write timeout (ms)", "de": "Timeout für Sync (ms)", "ru": "Таймаут синхронизации (ms)"},
"Invalid username or password": {
"en": "Invalid username or password",
"de": "Username oder Kennwort ist falsch",
"ru": "Неправильные имя пользователя или пароль"
},
"Read always config from server": {
"en": "Read always config from server",
"de": "Immer vom Server alles laden",
"ru": "Не кешировать файлы"
},
"show_policy": {"en": "Show me User Data Policy", "de": "Datenschutz und Sicherheit Richtlinien", "ru": "Конфиденциальность и безопасность"}
});
var app = {
settings: {
socketUrl: 'http://localhost:8082',//10.0.2.2. for emulator
systemLang: navigator.language || navigator.userLanguage || 'en',
noSleep: false,
project: '',
resync: false,
instance: null,
allowMove: false,
dontCache: false,
fullscreen: false,
lockorientation: 0,
recognition: false,
socketPro: false,
text2command: 0,
defaultRoom: '',
volume: 80,
writeTimeout: 2000,
allowSelfSigned: false,
zoomLevelPortrait: 100,
zoomLevelLandscape: 100,
substitutionUrl: '',
noCommInBackground: false,
responseWithTts: true,
deviceName: 'app',
geoInterval: 0,
geoHighAccuracy: true,
readBattery: true
},
inBackground: false,
connection: '',
projects: [],
ssid: null,
localDir: null,
directory: (cordova && cordova.file) ? cordova.file.dataDirectory : null,
speaking: false,
connected: false,
totalFileCount: 0,
lastBatteryStatus: null,
lastPosition: null,
geoTimer: null,
exitApp: false,
currentUrl: '',
// Application Constructor
initialize: function () {
if (this.settings.systemLang.indexOf('-') !== -1) {
this.settings.systemLang = this.settings.systemLang.split('-')[0];
systemLang = this.settings.systemLang;
}
this.bindEvents();
},
// Bind Event Listeners
//
// Bind any events that are required on startup. Common events are:
// 'load', 'deviceready', 'offline', and 'online'.
onBackButtonSettings: function () {
$('#cordova_cancel').trigger('click');
},
onBackButtonGeneral: function (e) {
e.preventDefault();
if (this.exitApp) {
logout();
} else {
this.exitApp = true;
setTimeout(function () {
this.exitApp = false;
}.bind(this), 1000);
history.back(1);
}
},
bindEvents: function () {
document.addEventListener('deviceready', this.onDeviceReady.bind(this), false);
document.addEventListener('pause', this.onDevicePause.bind(this), false);
document.addEventListener('resume', this.onDeviceResume.bind(this), false);
document.addEventListener('menubutton', function () {
$('#cordova_menu').trigger('click');
}, false);
},
receivedEvent: function (event) {
console.log('Received Event: ' + event);
},
onDevicePause: function () {
this.inBackground = true;
if (this.settings.noCommInBackground) {
vis.conn._socket.close();
}
},
onDeviceResume: function () {
this.inBackground = false;
if (this.settings.noCommInBackground) {
window.location.reload();
}
},
getLocalDir: function (dir, create, cb, index) {
if (typeof create === 'function') {
index = cb;
cb = create;
create = true;
}
if (!this.directory) this.directory = cordova.file.dataDirectory;
if (!this.localDir) {
window.resolveLocalFileSystemURL(this.directory, function (dirHandler) {
this.localDir = dirHandler;
this.getLocalDir(dir, create, cb);
}.bind(this), function (error) {
console.error('Cannot get "' + this.directory + '": ' + error);
cb(error);
}.bind(this));
return;
}
if (create) {
index = index || 0;
var parts = dir.split('/');
this.localDir.getDirectory(parts[index], {
create: true,
exclusive: false
}, function (dirHandler) {
if (parts.length - 1 === index) {
cb(null, dirHandler);
} else {
this.getLocalDir(dir, create, cb, index + 1);
}
}.bind(this), function (error) {
cb(error);
});
} else {
this.localDir.getDirectory(dir, {
create: false,
exclusive: false
}, function (dirHandler) {
cb(null, dirHandler);
}, function (error) {
cb(error);
});
}
},
writeLocalFile: function (fileName, data, cb, _counter) {
var that = this;
_counter = _counter || 0;
var parts = fileName.split('/');
var fileN = parts.pop();
this.getLocalDir(parts.join('/'), true, function (error, dirHandler) {
if (error) console.error(error);
if (dirHandler) {
dirHandler.getFile(fileN, {create: true}, function (fileHandler) {
console.log('Store: ' + fileN);
var length = data.byteLength || data.length || 0;
try {
fileHandler.createWriter(function (fileWriter) {
// workaround. Sometimes onWrite do not return.
var writeTimer = setTimeout(function () {
if (_counter < 10) {
console.warn('Timeout by write of: ' + fileN + ', Attempt: ' + _counter);
that.writeLocalFile(fileName, data, cb, _counter + 1);
} else {
cb && cb('Timeout by write of "' + fileN + '"');
cb = null;
}
}, that.settings.writeTimeout);
try {
fileWriter.truncate(0);
fileWriter.onwrite = function (evt) {
if (writeTimer) {
clearTimeout(writeTimer);
writeTimer = null;
}
if (length && evt.target.position < length) {
writeTimer = setTimeout(function () {
if (_counter < 10) {
console.warn('Timeout by write of: ' + fileN + ', Attempt: ' + _counter);
that.writeLocalFile(fileName, data, cb, _counter + 1);
} else {
cb && cb('Timeout by _write of "' + fileN + '"');
cb = null;
}
}, that.settings.writeTimeout);
return;
}
console.log('write "' + fileN + '" success:' + JSON.stringify(evt));
cb && cb();
cb = null;
}.bind(this);
if (window.MozBlobBuilder || window.WebKitBlobBuilder || window.BlobBuilder) {
var bb = new (window.MozBlobBuilder || window.WebKitBlobBuilder || window.BlobBuilder)();
bb.append(data);
fileWriter.write(bb.getBlob());
} else {
fileWriter.write(new Blob([data]));
}
} catch (error) {
if (_counter < 10) {
console.warn('Error by write of: ' + fileN + ', Attempt: ' + _counter + ' [' + error + ']');
setTimeout(function () {
that.writeLocalFile(fileName, data, cb, _counter + 1);
}, 100);
} else {
console.error(fileWriter.nativeURL + ': ' + error);
cb && cb(error);
cb = null;
}
}
}.bind(this), function (error) {
if (_counter < 10) {
console.warn('Error by write of: ' + fileN + ', Attempt: ' + _counter + ' [' + error + ']');
setTimeout(function () {
that.writeLocalFile(fileName, data, cb, _counter + 1);
}, 100);
} else {
cb && cb(error);
cb = null;
console.error('Cannot write file: ' + JSON.stringify(error));
}
}.bind(this));
} catch (err) {
if (_counter < 10) {
console.warn('Error by write of: ' + fileN + ', Attempt: ' + _counter + ' [' + error + ']');
setTimeout(function () {
that.writeLocalFile(fileName, data, cb, _counter + 1);
}, 100);
} else {
cb && cb(error);
cb = null;
console.error('Cannot create file:' + err);
}
}
}.bind(this), function (error) {
if (_counter < 10) {
console.warn('Error by write of: ' + fileN + ', Attempt: ' + _counter + ' [' + error + ']');
setTimeout(function () {
that.writeLocalFile(fileName, data, cb, _counter + 1);
}, 100);
} else {
cb && cb(error);
cb = null;
console.error('Cannot create file: ' + error);
}
}.bind(this));
} else {
console.error('Directory "' + fileName + '" not found');
cb(error || 'Directory not found');
}
}.bind(this));
},
readLocalFile: function (fileName, cb) {
var parts = fileName.split('/');
var fileN = parts.pop();
this.getLocalDir(parts.join('/'), false, function (error, dir) {
if (dir) {
dir.getFile(fileN, {create: false}, function (fileEntry) {
fileEntry.file(function(file) {
var reader = new FileReader();
reader.onloadend = function(e) {
cb(null, this.result, fileName);
};
reader.readAsText(file);
});
}, function (error) {
if (fileName.indexOf('vis-views.json') !== -1) {
cb(_('Not found'), '', fileName);
} else {
cb(error, null, fileName);
console.error('Cannot read file "' + fileName + '": ' + JSON.stringify(error));
}
});
} else {
if (fileName.indexOf('vis-views.json') !== -1) {
cb(_('Not found'), '', fileName);
} else {
cb(error, null, fileName);
console.error('Cannot read file: ' + error);
}
}
});
},
deleteLocalFile: function (fileName, cb) {
var parts = fileName.split('/');
var fileN = parts.pop();
this.getLocalDir(parts.join('/'), true, function (error, dirHandler) {
if (error) console.error(error);
if (dirHandler) {
dirHandler.getFile(fileN, {create: false}, function (fileHandler) {
fileHandler.remove(function () {
cb();
}, function (error) {
cb(error);
console.error('Cannot delete file: ' + error);
});
}, function (error) {
cb(error);
console.error('Cannot create file')
});
}
});
},
onDeviceReady: function () {
this.receivedEvent('deviceready');
// allow unsecure certificates
/*if (cordova.plugins.certificates) {
cordova.plugins.certificates.trustUnsecureCerts(true);
}*/
// install listener on go-back button
document.addEventListener('backbutton', this.onBackButtonGeneral, false);
if (this.settings.readBattery) {
window.addEventListener('batterystatus', this.onBatteryStatus, false);
}
this.settings.geoInterval = parseInt(this.settings.geoInterval, 10);
this.settings.socketUrl = (this.settings.socketUrl || '').toLowerCase();
// add http://
if (this.settings.socketUrl && !this.settings.socketUrl.match(/^http:\/\/|^https:\/\//i)) {
this.settings.socketUrl = 'http://' + this.settings.socketUrl;
}
// remove last /
if (this.settings.socketUrl.match(/\/$/)) {
this.settings.socketUrl = this.settings.socketUrl.substring(0, this.settings.socketUrl.length - 1);
}
this.settings.socketUrlGSM = (this.settings.socketUrlGSM || '').toLowerCase();
// add http://
if (this.settings.socketUrlGSM && !this.settings.socketUrlGSM.match(/^http:\/\/|^https:\/\//i)) {
this.settings.socketUrlGSM = 'http://' + this.settings.socketUrlGSM;
}
// remove last /
if (this.settings.socketUrlGSM.match(/\/$/)) {
this.settings.socketUrlGSM = this.settings.socketUrlGSM.substring(0, this.settings.socketUrlGSM.length - 1);
}
/*this.writeLocalFile('main/imgavSony.png', 'text', function (error) {
this.readLocalFile('main/imgavSony.png', function (error, result) {
if (error) console.error(error);
if (!result || this.settings.resync) {
}
}.bind(this));
}.bind(this));*/
this.settings.writeTimeout = parseInt(this.settings.writeTimeout, 2000) || 2000;
if (this.settings.writeTimeout < 1000) this.settings.writeTimeout = 1000;
this.connection = navigator.network ? navigator.network.connection.type : undefined;
document.addEventListener('online', function () {
if (navigator.network && navigator.network.connection.type !== this.connection) {
window.location.reload();
}
}.bind(this), false);
this.loadSettings(function () {
if (window.plugins.insomnia) {
if (this.settings.noSleep) {
window.plugins.insomnia.keepAwake();
} else {
window.plugins.insomnia.allowSleepAgain();
}
}
this.installMenu();
// because of different translation
this.yes = _('yes');
this.no = _('no');
this.loadCss();
if (this.settings.project) {
if (!this.settings.dontCache) {
this.readLocalFile(this.settings.project + '/vis-views.json', function (error, result) {
if (error) console.error(error);
if (!result || this.settings.resync) {
this.syncVis(this.settings.project, function () {
this.settings.resync = false;
this.saveSettings();
if (!this.viewExists) {
window.alert(_('No views found in %s', this.settings.project));
} else {
window.location.reload();
}
}.bind(this));
}
}.bind(this));
}
}
if (!this.settings.project || this.settings.socketUrl === 'http://localhost:8082') {
$('#cordova_menu').trigger('click');
}
if (!this.settings.allowMove) {
$('#vis_container').css({
'-webkit-touch-callout': 'none',
'-ms-touch-select': 'none',
'-ms-touch-action': 'none',
'-webkit-tap-highlight-color': 'rgba(0,0,0,0)',
'touch-callout': 'none',
'touch-select': 'none',
'touch-action': 'none',
'-webkit-user-select': 'none',
'-khtml-user-select': 'none',
'-moz-user-select': 'none',
'-ms-user-select': 'none',
'user-select': 'none',
'border': 'none !important'
});
}
$('.vis-wait-text').css({left: 0, 'padding-left': '1em'});
this.settings.lockorientation = parseInt(this.settings.lockorientation, 10);
//alert ('Orientation: ' + this.settings.lockorientation )
if (this.settings.lockorientation === 1) {
window.plugins.orientationLock.lock('portrait');
} else if (this.settings.lockorientation === 2) {
window.plugins.orientationLock.lock('landscape');
} else {
window.plugins.orientationLock.unlock()
}
this.initSpeechRecognition();
this.manageDisplayRotation();
function successFunction() {
//console.info('It worked!');
}
function errorFunction(error) {
console.error(error);
}
/*function trace(value) {
console.log(value);
}*/
if (typeof AndroidFullScreen !== 'undefined') {
if (this.settings.fullscreen) {
AndroidFullScreen.immersiveMode(successFunction, errorFunction);
} else {
AndroidFullScreen.showSystemUI(successFunction, errorFunction);
}
}
// init vis
main(jQuery);
}.bind(this));
},
showProLogo: function (isError) {
var $pro = $('#yunkong2_pro');
if (!$pro.length) {
$('body').append('<div id="yunkong2_pro" style=" position: fixed; z-index: 5000; top: 5px;right: 5px; color: white; border-radius: 5px; padding: 1px 3px 1px 3px; font-family: Arial; font-size: 0.9em;">.pro</div>');
$pro = $('#yunkong2_pro');
}
$pro.show();
if (isError) {
$pro.css({background: '#b93f3f'});
} else {
$pro.css({background: '#3399CC'});
setTimeout(function () {
$('#yunkong2_pro').remove();
}, 10000);
}
},
setProCookies: function (cb) {
if (this.settings.socketPro) {
console.log('Connect via yunkong2.pro');
// By calling of this function, the wss cookie will be set and authentication will work.
$.ajax({
type: 'POST',
url: 'https://yunkong2.pro/login?app=true',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Referer': 'https://yunkong2.pro/login',
'Host': 'yunkong2.pro',
'Origin': 'https://yunkong2.pro'
},
data: {
username: this.settings.userGSM || this.settings.user,
password: this.settings.passwordGSM || this.settings.password
},
success: function (data, textStatus, request) {
if (data && typeof data === 'object' && data['connect.sid']) {
// hide dialog error
var $dialog = $('#dialog-message');
if ($dialog.is(':visible')) {
try {
$dialog.dialog('close');
} catch (e) {
}
}
this.showProLogo();
cb(null, true);
} else {
window.alert(_('Invalid username or password'));
if (!$('#cordova_menu').length) {
this.installMenu();
}
$('#cordova_menu').trigger('click');
}
}.bind(this),
error: function (request, textStatus, errorThrown) {
vis.showMessage(_('Cannot login to yunkong2.pro') + ': ' + textStatus);
this.showProLogo(true);
setTimeout(function () {
this.setProCookies(cb);
}.bind(this), 10000);
}.bind(this)
});
} else {
cb(null, false);
}
},
loadSettings: function (cb) {
if (typeof Storage !== 'undefined') {
var value = localStorage.getItem('cordova');
var delayed = false;
if (value) {
try {
value = JSON.parse(value);
} catch (error) {
console.error('Cannot parse settings');
value = {};
}
} else {
value = {};
}
this.settings = $.extend(this.settings, value);
// systemLang is global variable and defined in visLang.js
systemLang = this.settings.systemLang || navigator.language || navigator.userLanguage;
this.settings.lockorientation = this.settings.lockorientation || 0;
this.settings.zoomLevelPortrait = this.settings.zoomLevelPortrait || 100;
this.settings.zoomLevelLandscape = this.settings.zoomLevelLandscape || 100;
this.settings.substitutionUrl = this.settings.substitutionUrl || '';
if (((this.settings.socketUrlGSM || this.settings.socketPro) && !this.settings.socketUrl) ||
((this.settings.socketUrlGSM || this.settings.socketPro) && navigator.network && navigator.network.connection.type !== 'wifi')) {
delayed = true;
this.setProCookies(function (error, usePro) {
if (usePro) {
socketUrl = 'https://yunkong2.pro';
} else {
socketUrl = this.settings.socketUrlGSM;
}
this.currentUrl = socketUrl;
socketUrl += '/?key=nokey' + (this.settings.userGSM ? '&user=' + encodeURIComponent(this.settings.userGSM) + '&pass=' + encodeURIComponent(this.settings.passwordGSM) : '');
cb && cb();
}.bind(this));
} else {
try {
// If WIFI and SSID is set
if ((this.settings.socketUrlGSM || this.settings.socketPro) && this.settings.ssid) {
// convert into array of SSIDs
if (typeof this.settings.ssid === 'string') {
this.settings.ssid = this.settings.ssid.split(',');
for (var s = this.settings.ssid.length - 1; s >= 0; s--) {
this.settings.ssid[s] = this.settings.ssid[s].trim();
if (!this.settings.ssid[s]) this.settings.ssid.splice(s, 1);
}
}
// read SSID info
delayed = true;
if (typeof WifiWizard !== 'undefined') {
WifiWizard.getCurrentSSID(function (response) {
this.ssid = response.replace(/\"/g, '');
if (this.settings.ssid.indexOf(this.ssid) === -1) {
// other wifi network
this.setProCookies(function (error, usePro) {
if (usePro) {
socketUrl = 'https://yunkong2.pro';
} else {
socketUrl = this.settings.socketUrlGSM;
}
this.currentUrl = socketUrl;
socketUrl += '/?key=nokey' + (this.settings.userGSM ? '&user=' + encodeURIComponent(this.settings.userGSM) + '&pass=' + encodeURIComponent(this.settings.passwordGSM) : '');
cb && cb();
}.bind(this));
} else {
this.currentUrl = this.settings.socketUrl;
socketUrl = this.settings.socketUrl + '/?key=nokey' + (this.settings.user ? '&user=' + encodeURIComponent(this.settings.user) + '&pass=' + encodeURIComponent(this.settings.password) : '');
cb && cb();
}
}.bind(this), function (error){
this.currentUrl = this.settings.socketUrl;
socketUrl = this.settings.socketUrl + '/?key=nokey' + (this.settings.user ? '&user=' + encodeURIComponent(this.settings.user) + '&pass=' + encodeURIComponent(this.settings.password) : '');
console.error(error);
cb && cb();
}.bind(this));
}
} else {
this.currentUrl = this.settings.socketUrl;
socketUrl = this.settings.socketUrl + '/?key=nokey' + (this.settings.user ? '&user=' + encodeURIComponent(this.settings.user) + '&pass=' + encodeURIComponent(this.settings.password) : '');
}
} catch (err) {
this.currentUrl = this.settings.socketUrl;
delayed = false;
socketUrl = this.settings.socketUrl + '/?key=nokey' + (this.settings.user ? '&user=' + encodeURIComponent(this.settings.user) + '&pass=' + encodeURIComponent(this.settings.password) : '');
}
}
if (cordova.plugins.certificates) {
cordova.plugins.certificates.trustUnsecureCerts(this.settings.allowSelfSigned === true || this.settings.allowSelfSigned === 'true');
}
// generate new Instance
if (!this.settings.instance) {
this.settings.instance = (Math.random() * 4294967296).toString(16);
this.settings.instance = '0000000' + this.settings.instance;
this.settings.instance = this.settings.instance.substring(this.settings.instance.length - 8);
}
} else {
console.error('no Storage object!');
}
if (!delayed && cb) cb();
},
saveSettings: function () {
if (typeof(Storage) !== 'undefined') {
localStorage.setItem('cordova', JSON.stringify(this.settings));
}
},
onAuthError: function (err) {
window.alert(_('Invalid username or password'));
if (!$('#cordova_menu').length) {
app.installMenu();
}
$('#cordova_menu').trigger('click');
},
// creates vis states for battery and geolocation
createStates: function (cb) {
var that = this;
var count = 0;
if (this.settings.readBattery) {
count++;
vis.conn.getObject(vis.conn.namespace + '.' + this.settings.deviceName + '.battery.isPlugged', function (err, obj) {
if (!obj) {
vis.conn._socket.emit('setObject', vis.conn.namespace + '.' + that.settings.deviceName + '.battery.isPlugged', {
common: {
name: 'If device ' + that.settings.deviceName + ' plugged in',
type: 'boolean',
role: 'indicator.plugged',
write: false,
read: true
},
type: 'state',
native: {}
},function (err, obj) {
vis.conn.getObject(vis.conn.namespace + '.' + that.settings.deviceName + '.battery.level', function (err, obj) {
if (!obj) {
vis.conn._socket.emit('setObject', vis.conn.namespace + '.' + that.settings.deviceName + '.battery.level', {
common: {
name: 'Battery status for ' + that.settings.deviceName,
type: 'number',
role: 'battery',
write: false,
read: true,
min: 0,
max: 100,
unit: '%'
},
type: 'state',
native: {}
},function (err, obj) {
if (!--count) {
cb && cb();
}
});
} else if (!--count) {
cb && cb();
}
});
});
} else if (!--count) {
cb && cb();
}
});
}
if (this.settings.geoInterval) {
count++;
vis.conn.getObject(vis.conn.namespace + '.' + this.settings.deviceName + '.coords.latitude', function (err, obj) {
if (!obj) {
vis.conn._socket.emit('setObject', vis.conn.namespace + '.' + that.settings.deviceName + '.coords.latitude', {
common: {
name: 'Latitude of ' + that.settings.deviceName,
type: 'number',
role: 'gps.latitude',
unit: '°',
write: false,
read: true
},
type: 'state',
native: {}
},function (err, obj) {
var prefix = vis.conn.namespace + '.' + that.settings.deviceName + '.coords.';
vis.conn.getObject(prefix + 'longitude', function (err, obj) {
if (!obj) {
vis.conn._socket.emit('setObject', prefix + 'longitude', {
common: {
name: 'Longitude of ' + that.settings.deviceName,
type: 'number',
role: 'gps.longitude',
unit: '°',
write: false,
read: true
},
type: 'state',
native: {}
},function (err, obj) {
if (!--count) {
prefix = null;
cb && cb();
}
});
} else if (!--count) {
prefix = null;
cb && cb();
}
});
count++;
vis.conn.getObject(prefix + 'altitude', function (err, obj) {
if (!obj) {
vis.conn._socket.emit('setObject', prefix + 'altitude', {
common: {
name: 'Altitude of ' + that.settings.deviceName,
type: 'number',
role: 'gps.altitude',
unit: 'm',
write: false,
read: true
},
type: 'state',
native: {}
}, function (err, obj) {
if (!--count) {
prefix = null;
cb && cb();
}
});
} else if (!--count) {
prefix = null;
cb && cb();
}
});
count++;
vis.conn.getObject(prefix + 'accuracy', function (err, obj) {
if (!obj) {
vis.conn._socket.emit('setObject', prefix + 'accuracy', {
common: {
name: 'Accuracy of position for ' + that.settings.deviceName,
type: 'number',
role: 'gps.accuracy.position',
unit: 'm',
write: false,
read: true
},
type: 'state',
native: {}
}, function (err, obj) {
if (!--count) {
prefix = null;
cb && cb();
}
});
} else if (!--count) {
prefix = null;
cb && cb();
}
});
count++;
vis.conn.getObject(prefix + 'altitudeAccuracy', function (err, obj) {
if (!obj) {
vis.conn._socket.emit('setObject', prefix + 'altitudeAccuracy', {
common: {
name: 'Altitude accuracy of position for ' + that.settings.deviceName,
type: 'number',
role: 'gps.accuracy.altitude',
unit: 'm',
write: false,
read: true
},
type: 'state',
native: {}
}, function (err, obj) {
if (!--count) {
prefix = null;
cb && cb();
}
});
} else if (!--count) {
prefix = null;
cb && cb();
}
});
count++;
vis.conn.getObject(prefix + 'heading', function (err, obj) {
if (!obj) {
vis.conn._socket.emit('setObject', prefix + 'heading', {
common: {
name: 'Heading for ' + that.settings.deviceName,
type: 'number',
role: 'gps.heading',
unit: '°',
write: false,
read: true
},
type: 'state',
native: {}
}, function (err, obj) {
if (!--count) {
prefix = null;
cb && cb();
}
});
} else if (!--count) {
prefix = null;
cb && cb();
}
});
count++;
vis.conn.getObject(prefix + 'speed', function (err, obj) {
if (!obj) {
vis.conn._socket.emit('setObject', prefix + 'speed', {
common: {
name: 'Speed for ' + that.settings.deviceName,
type: 'number',
role: 'gps.speed',
unit: 'm/s',
write: false,
read: true
},
type: 'state',
native: {}
}, function (err, obj) {
if (!--count) {
prefix = null;
cb && cb();
}
});
} else if (!--count) {
prefix = null;
cb && cb();
}
});
count++;
vis.conn.getObject(prefix + 'speedKm', function (err, obj) {
if (!obj) {
vis.conn._socket.emit('setObject', prefix + 'speedKm', {
common: {
name: 'Speed for ' + that.settings.deviceName,
type: 'number',
role: 'gps.speed',
unit: 'km/h',
write: false,
read: true
},
type: 'state',
native: {}
}, function (err, obj) {
if (!--count) {
prefix = null;
cb && cb();
}
});
} else if (!--count) {
prefix = null;
cb && cb();
}
});
});
} else if (!--count && cb) cb();
});
}
},
onBatteryStatus: function (status) {
var that = app;
if (!status) return;
that.lastBatteryStatus = JSON.parse(JSON.stringify(status));
if (!that.connected) return;
var prefix = vis.conn.namespace + '.' + that.settings.deviceName + '.battery.';
vis.conn.setState(prefix + 'isPlugged', {val: status.isPlugged, ack: true});
vis.conn.setState(prefix + 'level', {val: status.level, ack: true});
},
onLocation: function (position) {
if (!position || !position.coords) return;
var that = app;
that.lastPosition = JSON.parse(JSON.stringify(position));
if (!that.connected) return;
var prefix = vis.conn.namespace + '.' + that.settings.deviceName + '.coords.';
var ts = position.timestamp;
vis.conn.setState(prefix + 'latitude', {ts: ts, ack: true, val: position.coords.latitude});
vis.conn.setState(prefix + 'longitude', {ts: ts, ack: true, val: position.coords.longitude});
vis.conn.setState(prefix + 'altitude', {ts: ts, ack: true, val: position.coords.altitude});
vis.conn.setState(prefix + 'accuracy', {ts: ts, ack: true, val: position.coords.accuracy});
vis.conn.setState(prefix + 'altitudeAccuracy', {ts: ts, ack: true, val: position.coords.altitudeAccuracy});
vis.conn.setState(prefix + 'heading', {ts: ts, ack: true, val: position.coords.heading});
vis.conn.setState(prefix + 'speed', {ts: ts, ack: true, val: position.coords.speed});
if (position.coords.speed !== null && position.coords.speed !== undefined) {
vis.conn.setState(prefix + 'speedKm', {ts: ts, ack: true, val: position.coords.speed * 3.6});
} else {
vis.conn.setState(prefix + 'speedKm', {ts: ts, ack: true, val: null});
}
},
startStopPollPosition: function (isStart) {
if (isStart && this.settings.geoInterval && navigator && navigator.geolocation && navigator.geolocation.getCurrentPosition) {
if (this.settings.geoInterval < 30) this.settings.geoInterval = 30;
if (!this.geoTimer) {
this.geoTimer = setInterval(function () {
navigator.geolocation.getCurrentPosition(app.onLocation, function (error) {
console.error(error);
});
}, this.settings.geoInterval * 1000);
}
if (!this.geoWatchID) {
this.geoWatchID = navigator.geolocation.watchPosition(this.onLocation, function (error) {
console.error(error);
}, {
enableHighAccuracy: !!this.settings.geoHighAccuracy,
maximumAge: 3000,
timeout: 5000
});
}
} else {
if (this.geoTimer) {
clearInterval(this.geoTimer);
this.geoTimer = null;
}
if (this.geoWatchID) {
navigator.geolocation.clearWatch(this.geoWatchID);
this.geoWatchID = null;
}
}
},
readProjectsHelper: function (project, cb) {
vis.conn.readFile(project + '/vis-views.json', function (error, data, filename) {
if (cb) {
project = data ? project : null;
// give time for other tasks
setTimeout(function () {
cb(project);
}, 50);
}
}, true);
},
readProjects: function (cb, attempt) {
attempt = attempt || 0;
if (attempt > 20) {
alert(_('Cannot read projects'));
cb && cb();
}
if (vis.conn && vis.conn.getIsConnected()) {
this.projects = [];
$('#cordova_project').html('<option>' + _('reading...') + '</option>').prop('disabled', true);
vis.conn.readDir('/vis.0', function (error, files) {
if (error) {
alert('Cannot read projects: ' + error);
}
var count = 0;
if (files) {
for (var f = 0; f < files.length; f++) {
if (files[f].isDir) {
count++;
this.readProjectsHelper(files[f].file, function (project) {
if (project) {
this.projects.push(project);
}
if (!--count) {
var text = '';
for (var p = 0; p < this.projects.length; p++) {
text += '<option value="' + this.projects[p] + '" ' + (this.projects[p] === this.settings.project ? 'selected' : '') + '>' + this.projects[p] + '</option>';
}
$('#cordova_project').html(text).prop('disabled', false);
cb && cb();
}
}.bind(this));
}
}
}
if (!count && cb) cb();
}.bind(this));
} else {
setTimeout(function () {
this.readProjects(cb, attempt++);
}.bind(this), 500);
}
},
replaceFilesInViews: function (viewsObj, total, files) {
var data = viewsObj.toString();
var m;
var newName;
var mm;
if (this.settings.substitutionUrl) {
// detect: this.settings.substitutionUrl/vis/, substitutionUrl/vis.0/, substitutionUrl/icon-blabla/, ...
var re = new RegExp('": "' + escapeRegExp(this.settings.substitutionUrl) + '\\\/[-_0-9\\w]+(?:.[-_0-9\\w]+)?\\/[^"^\']+\\.(?:png|jpg|jpeg|gif|wav|mp3|bmp|svg)+\\\\"', 'g');
m = data.match(re);
if (m) {
for (mm = 0; mm < m.length; mm++) {
//file:///data/data/net.yunkong2.vis/files/main/vis-user.css
//cdvfile://localhost/persistent
console.log ('Found:' + m [mm]);
var fn = m[mm].substring(this.settings.substitutionUrl.length + 5); // remove ": " + this.settings.substitutionUrl +"/"
var originalFileName = fn.replace(/"/g, ''); // remove last "
var p = fn.split('/');
var adapter = p.shift(); // remove vis.0 or whatever
fn = p.shift(); // keep only one subdirectory
fn += p.length ? '/' + p.join('') : '';// all other subdirectories combine in one name because of store bug
if (originalFileName[0] === '/') originalFileName = originalFileName.substring(1);
if (originalFileName[originalFileName.length - 1] === '"') originalFileName = originalFileName.substring(0, originalFileName.length - 1);
originalFileName = ('/' + originalFileName).replace('/vis.0/', '');
// files cannot be stored directly in root
if (adapter === 'vis.0' && fn.indexOf('/') !== -1) adapter = '';
// add to files
var found = false;
for (var ff_ = 0; ff_ < total.length; ff_++) {
if (typeof total[ff_] === 'string' && total[ff_] === originalFileName) {
found = true;
break;
}
if (typeof total[ff_] === 'object' && total[ff_].src === originalFileName) {
found = true;
break;
}
}
if (!found) { // if "vis.0/dir/otherProject.png"
files.push({src: originalFileName, dst: adapter + fn.replace(/\s/g, '_').replace(/\\"$/, '')});
}
data = data.replace(m[mm], '": "' + this.directory + adapter + fn.replace(/\s/g, '_'));
}
}
// detect: this.settings.substitutionUrl/vis/, substitutionUrl/vis.0/, substitutionUrl/icon-blabla/, ...
re = new RegExp('url\\(\\\\"' + escapeRegExp(this.settings.substitutionUrl) + '\\\/[-_0-9\\w]+(?:.[-_0-9\\w]+)?\\/[^"^\']+\\.(?:png|jpg|jpeg|gif|wav|mp3|bmp|svg)+\\\\"','g');
m = data.match(re);
if (m) {
for (mm = 0; mm < m.length; mm++) {
//file:///data/data/net.yunkong2.vis/files/main/vis-user.css
//cdvfile://localhost/persistent
var fn = m[mm].substring(this.settings.substitutionUrl.length + 7); // remove 'url(\"' + substitutionUrl +"/"
var originalFileName = fn.replace(/\\"/g, ''); // remove last "
var p = fn.split('/');
var adapter = p.shift(); // remove vis.0 or whatever
fn = p.shift(); // keep only one subdirectory
fn += p.length ? '/' + p.join('') : '';// all other subdirectories combine in one name because of store bug
if (originalFileName[0] === '/') originalFileName = originalFileName.substring(1);
if (originalFileName[originalFileName.length - 1] === '"') originalFileName = originalFileName.substring(0, originalFileName.length - 1);
originalFileName = ('/' + originalFileName).replace('/vis.0/', '');
// files cannot be stored directly in root
if (adapter === 'vis.0' && fn.indexOf('/') !== -1) adapter = '';
// add to files
var found = false;
for (var ff = 0; ff < total.length; ff++) {
if (typeof total[ff] === 'string' && total[ff] === originalFileName) {
found = true;
break;
}
if (typeof total[ff] === 'object' && total[ff].src === originalFileName) {
found = true;
break;
}
}
if (!found) { // if "vis.0/dir/otherProject.png"
files.push({src: originalFileName, dst: adapter + fn.replace(/\s/g, '_').replace(/\\"$/, '')});
}
data = data.replace(m[mm], 'url(\\"' + this.directory + adapter + fn.replace(/\s/g, '_'));
}
}
}
// detect: /vis/, /vis.0/, /icon-blabla/, ...
m = data.match(/": "\/[-_0-9\w]+(?:\.[-_0-9\w]+)?\/[^"^']+\.(?:png|jpg|jpeg|gif|wav|mp3|bmp|svg)+"/g);
if (m) {
for (mm = 0; mm < m.length; mm++) {
//file:///data/data/net.yunkong2.vis/files/main/vis-user.css
//cdvfile://localhost/persistent
var fn = m[mm].substring(5); // remove ": "/
var originalFileName = fn.replace(/\\"/g, ''); // remove last "
var p = fn.split('/');
var adapter = p.shift(); // remove vis.0 or whatever
fn = p.shift(); // keep only one subdirectory
fn += p.length ? '/' + p.join('') : '';// all other subdirectories combine in one name because of store bug
// ignore proxy requests.
if (adapter.match(/^proxy\.\d+$/)) {
// replace "/proxy.0/aaa.png" with http(s)://socketURL/proxy.0/aaa.png
data = data.replace(m[mm], '": "' + this.currentUrl + '/' + originalFileName);
continue;
}
// files cannot be stored directly in root
if (adapter === 'vis.0' && fn.indexOf('/') !== -1) adapter = '';
newName = originalFileName;
if (newName[0] === '/') newName = newName.substring(1);
if (newName[newName.length - 1] === '"') newName = newName.substring(0, newName.length - 1);
newName = ('/' + newName).replace('/vis.0/', '');
// add to files
var found = false;
for (var ff = 0; ff < total.length; ff++) {
if (typeof total[ff] === 'string' && total[ff] === newName) {
found = true;
break;
}
if (typeof total[ff] === 'object' && total[ff].src === newName) {
found = true;
break;
}
}
if (!found) { // if "vis.0/dir/otherProject.png"
files.push({src: newName, dst: adapter + fn.replace(/\s/g, '_').replace(/"$/, '')});
}
// remove spaces in names because they will be %20
data = data.replace(m[mm], '": "' + this.directory + adapter + fn.replace(/\s/g, '_'));
}
}
// try to replace <img src="/vis.0/main...">
m = data.match(/src=\\"\/[-_0-9\w]+(?:\.[-_0-9\w]+)?\/[^"^']+\.(?:png|jpg|jpeg|gif|wav|mp3|bmp|svg)+\\"/g);
if (m) {
for (mm = 0; mm < m.length; mm++) {
//file:///data/data/net.yunkong2.vis/files/main/vis-user.css
//cdvfile://localhost/persistent
var fn = m[mm].substring(7); // remove src=\"/
var originalFileName = fn.replace(/\\"/g, ''); // remove last "
var p = fn.split('/');
var adapter = p.shift(); // remove vis.0 or whatever
fn = p.shift(); // keep only one subdirectory
fn += p.length ? '/' + p.join('') : '';// all other subdirectories combine in one name because of store bug
newName = originalFileName;
if (newName[0] === '/') newName = newName.substring(1);
if (newName[newName.length - 1] === '"') newName = newName.substring(0, newName.length - 2);
newName = ('/' + newName).replace('/vis.0/', '');
// ignore proxy requests.
if (adapter.match(/^proxy\.\d+$/)) {
// replace "/proxy.0/aaa.png" with http(s)://socketURL/proxy.0/aaa.png
data = data.replace(m[mm], 'src=\\"' + this.currentUrl + '/' + originalFileName);
continue;
}
// files cannot be stored directly in root
if (adapter === 'vis.0' && fn.indexOf('/') !== -1) adapter = '';
// add to files
var found = false;
for (var ff = 0; ff < total.length; ff++) {
if (typeof total[ff] === 'string' && total[ff] === newName) {
found = true;
break;
}
if (typeof total[ff] === 'object' && total[ff].src === newName) {
found = true;
break;
}
}
if (!found) { // if "vis.0/dir/otherProject.png"
files.push({src: newName, dst: adapter + fn.replace(/\s/g, '_').replace(/\\"$/, '')});
}
// remove spaces in names because they will be %20
data = data.replace(m[mm], 'src=\\"' + this.directory + adapter + fn.replace(/\s/g, '_'));
}
}
// try to replace <img src='/vis.0/main...'>
m = data.match(/src='\/[-_0-9\w]+(?:\.[-_0-9\w]+)?\/[^"^']+\.(?:png|jpg|jpeg|gif|wav|mp3|bmp|svg)+'/g);
if (m) {
for (mm = 0; mm < m.length; mm++) {
//file:///data/data/net.yunkong2.vis/files/main/vis-user.css
//cdvfile://localhost/persistent
var fn = m[mm].substring(6); // remove src="/
var originalFileName = fn.replace(/'/g, ''); // remove last "
var p = fn.split('/');
var adapter = p.shift(); // remove vis.0 or whatever
fn = p.shift(); // keep only one subdirectory
fn += p.length ? '/' + p.join('') : '';// all other subdirectories combine in one name because of store bug
newName = originalFileName;
if (newName[0] === '/') newName = newName.substring(1);
if (newName[newName.length - 1] === "'") newName = newName.substring(0, newName.length - 1);
newName = ('/' + newName).replace('/vis.0/', '');
// ignore proxy requests.
if (adapter.match(/^proxy\.\d+$/)) {
// replace "/proxy.0/aaa.png" with http(s)://socketURL/proxy.0/aaa.png
data = data.replace(m[mm], "src='" + this.currentUrl + '/' + originalFileName);
continue;
}
// files cannot be stored directly in root
if (adapter === 'vis.0' && fn.indexOf('/') !== -1) adapter = '';
// add to files
var found = false;
for (var ff = 0; ff < total.length; ff++) {
if (typeof total[ff] === 'string' && total[ff] === newName) {
found = true;
break;
}
if (typeof total[ff] === 'object' && total[ff].src === newName) {
found = true;
break;
}
}
if (!found) { // if "vis.0/dir/otherProject.png"
files.push({src: newName, dst: adapter + fn.replace(/\s/g, '_').replace(/'$/, '')});
}
// remove spaces in names because they will be %20
data = data.replace(m[mm], "src='" + this.directory + adapter + fn.replace(/\s/g, '_'));
}
}
// try to replace <img src='/vis.0/main...'>
m = data.match(/url\(['"]?\/[-_0-9\w]+(?:\.[-_0-9\w]+)?\/[^"^']+\.(?:png|jpg|jpeg|gif|wav|mp3|bmp|svg)+['"]?\)/g);
if (m) {
for (mm = 0; mm < m.length; mm++) {
//file:///data/data/net.yunkong2.vis/files/main/vis-user.css
//cdvfile://localhost/persistent
var fn = m[mm].substring(4); // remove url(/
fn = fn.replace(/['")]+/g, '');
var originalFileName = fn;
var p = fn.split('/');
var adapter = p.shift(); // remove vis.0 or whatever
if (!adapter) adapter = p.shift();
fn = p.shift(); // keep only one subdirectory
fn += p.length ? '/' + p.join('') : '';// all other subdirectories combine in one name because of store bug
newName = originalFileName.replace('/vis.0/', '');
// ignore proxy requests.
if (adapter.match(/^proxy\.\d+$/)) {
// replace "/proxy.0/aaa.png" with http(s)://socketURL/proxy.0/aaa.png
data = data.replace(m[mm], 'url(' + this.currentUrl + '/' + originalFileName + ')');
continue;
}
// files cannot be stored directly in root
if (adapter === 'vis.0' && fn.indexOf('/') !== -1) adapter = '';
// add to files
var found = false;
for (var ff = 0; ff < total.length; ff++) {
if (typeof total[ff] === 'string' && total[ff] === newName) {
found = true;
break;
}
if (typeof total[ff] === 'object' && total[ff].src === newName) {
found = true;
break;
}
}
if (!found) { // if "vis.0/dir/otherProject.png"
files.push({src: newName, dst: adapter + fn.replace(/\s/g, '_')});
}
// remove spaces in names because they will be %20
data = data.replace(m[mm], 'url(' + this.directory + adapter + fn.replace(/\s/g, '_') + ')');
}
}
// set absolute path to local flot/rickshaw directory
data = data
.replace(/"\/flot\//g, '"file:///android_asset/www/flot/')
.replace(/'\/flot\//g, "'file:///android_asset/www/flot/")
.replace(/"\/rickshaw\//g, '"file:///android_asset/www/rickshaw/')
.replace(/'\/rickshaw\//g, "'file:///android_asset/www/rickshaw/");
return data;
},
replaceFilesInViewsWeb: function (viewsObj) {
var data = viewsObj.toString();
var m;
var mm;
// detect: /vis/, /vis.0/, /icon-blabla/, ...
m = data.match(/": "\/[-_0-9\w]+(?:\.[-_0-9\w]+)?\/[^"^']+\.(?:png|jpg|jpeg|gif|wav|mp3|bmp|svg)+"/g);
if (m) {
for (mm = 0; mm < m.length; mm++) {
var originalFileName = m[mm].substring(5);// remove ": "/
// remove spaces in names because they will be %20
data = data.replace(m[mm], '": "' + this.currentUrl + '/' + originalFileName);
}
}
// try to replace <img src="/vis.0/main...">
m = data.match(/src=\\"\/[-_0-9\w]+(?:\.[-_0-9\w]+)?\/[^"^']+\.(?:png|jpg|jpeg|gif|wav|mp3|bmp|svg)+\\"/g);
if (m) {
for (mm = 0; mm < m.length; mm++) {
var originalFileName = m[mm].substring(7); // remove src=\"/
// remove spaces in names because they will be %20
data = data.replace(m[mm], 'src=\\"' + this.currentUrl + '/' + originalFileName);
}
}
// try to replace <img src='/vis.0/main...'>
m = data.match(/src='\/[-_0-9\w]+(?:\.[-_0-9\w]+)?\/[^"^']+\.(?:png|jpg|jpeg|gif|wav|mp3|bmp|svg)+'/g);
if (m) {
for (mm = 0; mm < m.length; mm++) {
var originalFileName = m[mm].substring(6); // remove src="/
// remove spaces in names because they will be %20
data = data.replace(m[mm], "src='" + this.currentUrl + '/' + originalFileName);
}
}
// try to replace <img src='/vis.0/main...'>
m = data.match(/url\(['"]?\/[-_0-9\w]+(?:\.[-_0-9\w]+)?\/[^"^']+\.(?:png|jpg|jpeg|gif|wav|mp3|bmp|svg)+['"]?\)/g);
if (m) {
for (mm = 0; mm < m.length; mm++) {
var originalFileName = m[mm].substring(4); // remove url(/
if (originalFileName[0] === "'") {
data = data.replace(m[mm], "url('" + this.currentUrl + '/' + originalFileName.substring(1));
} else if (originalFileName[0] === '"') {
data = data.replace(m[mm], 'url("' + this.currentUrl + '/' + originalFileName.substring(1));
} else {
data = data.replace(m[mm], 'url(' + this.currentUrl + '/' + originalFileName);
}
}
}
// set absolute path to local flot/rickshaw directory
data = data
.replace(/"\/flot\//g, '"file:///android_asset/www/flot/')
.replace(/'\/flot\//g, "'file:///android_asset/www/flot/")
.replace(/"\/rickshaw\//g, '"file:///android_asset/www/rickshaw/')
.replace(/'\/rickshaw\//g, "'file:///android_asset/www/rickshaw/");
return data;
},
copyFilesToDevice: function (files, cb, total) {
if (total === undefined) total = files;
if (this.totalFileCount < total.length) this.totalFileCount = total.length;
if (!files || !files.length) {
if (cb) setTimeout(cb, 0);
return;
}
var file = files.pop();
console.log('Read file: ' + JSON.stringify(file));
var dest;
if (typeof file === 'object') {
dest = file.dst;
file = file.src;
}
vis.conn.readFile64(file, function (error, data, filename) {
if (error) console.error(error);
$('#cordova_progress_show').css('width', (100 - (files.length / this.totalFileCount) * 100) + '%');
$('#cordova_progress_info').text((this.totalFileCount - files.length) + '/' + this.totalFileCount + ' - ' + filename);
console.log('Progress files open: ' + files.length + ' Total: ' + this.totalFileCount);
if (!error && data !== undefined && data !== null) {
if ((data.mime.indexOf('text') === -1 && data.mime.indexOf('application') === -1)) {
var binary_string = window.atob(data.data);
var len = binary_string.length;
var bytes = new Uint8Array(len);
for (var i = 0; i < len; i++) {
bytes[i] = binary_string.charCodeAt(i);
}
data = bytes.buffer;
} else {
if (data.mime === 'application/json') {
data = decodeURIComponent(window.atob(data.data));
} else {
try {
data = window.atob(data.data || '');
} catch (err) {
data = data.data || '';
}
}
}
// modify vis-views.json
if (filename && filename.indexOf('vis-views.json') !== -1) {
this.viewExists = true;
data = this.replaceFilesInViews(data, total, files);
}
// modify vis-user.css
if (filename && filename.indexOf('vis-user.css') !== -1) {
data = this.replaceFilesInViews(data, total, files);
}
// remove sub-dirs
if (dest) {
filename = dest;
} else {
var p = filename.replace(/^\/[-_0-9\w]+(\.[-_0-9\w]+)?\//, '').split('/');
filename = p.shift();
filename += p.length ? '/' + p.join('') : '';
if (!p.length) {
p = file.split('/');
filename = (p[0] || p[1]) + '/' + filename;
}
// remove spaces in names because they will be %20
filename = filename.replace(/\s/g, '_');
}
console.log('writeLocalFile "' + file + '" as "' + filename + '"');
this.writeLocalFile(filename, data, function (error) {
if (error) console.error(error);
setTimeout(function () {
this.copyFilesToDevice(files, cb, total);
}.bind(this), 0);
}.bind(this));
} else {
setTimeout(function () {
this.copyFilesToDevice(files, cb, total);
}.bind(this), 0);
}
}.bind(this), true);
},
deleteFilesFromDevice: function (files, cb) {
if (!files || !files.length) {
if (cb) setTimeout(cb, 0);
return;
}
var file = files.pop();
this.deleteLocalFile(file, function (error) {
if (error) console.error(error);
setTimeout(function () {
this.deleteFilesFromDevice(files, cb);
}.bind(this), 0);
});
},
readRemoteProject: function (dir, cb, _files) {
dir = dir || '';
_files = _files || [];
// if start => reset flag
if (!dir || dir.indexOf('/') === -1) this.viewExists = false;
if (vis.conn && vis.conn.getIsConnected()) {
vis.conn.readDir('/vis.0/' + dir, function (error, files) {
if (files) {
var count = 0;
for (var f = 0; f < files.length; f++) {
if (files[f].isDir) {
count++;
this.readRemoteProject(dir + '/' + files[f].file, function () {
if (!--count) {
setTimeout(function () {
cb(_files);
}, 0);
}
}, _files);
} else {
_files.push(dir + '/' + files[f].file);
}
}
if (!count) {
setTimeout(function () {
cb(_files);
}, 0);
}
} else {
setTimeout(function () {
cb(_files);
}, 0);
}
}.bind(this));
} else {
// waiting till connected
setTimeout(function () {
this.readRemoteProject(dir, cb, _files);
}.bind(this), 500);
}
},
syncVis: function (project, cb) {
// hide dialog error
var $dialog = $('#dialog-message');
if ($dialog.is(':visible')) {
try {
$dialog.dialog('close');
} catch (e) {
}
}
// resize viewport
$('meta[name=viewport]').attr('content',
'width=' + (this.window ? this.window.width : window.innerWidth) + ',' +
'minimum-scale=1, maximum-scale=1');
if (!$('#cordova_progress').length) {
$('body').append(
'<div id="cordova_progress" style="position: absolute; z-index: 5003; top: 50%; left: 5%; width: 90%; height: 2em; background: gray">' +
'<div id="cordova_progress_show" style="height: 100%; width: 0; background: lightblue; z-index: 5004"></div></div>' +
'<div id="cordova_progress_info" style="position: absolute; z-index: 5005; top: calc(50% + 1.5em); left: 5%; width: 90%; height: 2em; overflow: hidden; text-align: left; font-size: 0.5em; padding-left: 0.5em"></div>');
}
if (vis.conn && vis.conn.getIsConnected()) {
$('#cordova_dialog_bg').show();
// let the menu button available
var timeout = setTimeout(function () {
$('#cordova_dialog_bg').hide();
}.bind(this), 4000);
// read common css file
vis.conn._socket.emit('readFile', 'vis', 'css/vis-common-user.css', function (err, data) {
setTimeout(function () {
// create empty file
this.writeLocalFile('vis-common-user.css', data || '', function (error) {
if (error) console.error(error);
this.readRemoteProject(project, function (files) {
this.totalFileCount = 0;
this.copyFilesToDevice(files, function () {
$('#cordova_progress').remove();
$('#cordova_progress_info').remove();
$('#cordova_dialog_bg').hide();
if (cb) cb();
});
}.bind(this));
}.bind(this));
}.bind(this), 0);
}.bind(this));
} else {
setTimeout(function () {
this.syncVis(project, cb);
}.bind(this), 500);
}
},
// deviceready Event Handler
//
// The scope of 'this' is the event. In order to call the 'receivedEvent'
// function, we must explicitly call 'app.receivedEvent(...);'
tts: function (data, cb) {
// text: 'hello, world!',
// locale: 'en-GB',
// rate: 0.1 - 10
// volume: from 0 to 100
// pitch: 0 -2
if (!this.ttsText) {
$('body').append('<div id="cordova_tts_text" style="border-radius: 1em; padding: 0.2em;position: absolute; z-index: 5000; background: lightgreen; top: 3em; left: 3em; font-size: 1.5em"></div>');
this.ttsText = $('#cordova_tts_text');
}
if (data[0] === '{') {
var obj;
try {
obj = JSON.parse(data);
} catch (err) {
}
if (obj) data = obj;
}
if (typeof data === 'string') {
if (data.indexOf(';') !== -1) {
var parts = data.split(';');
data = {};
for (var i = 0; i < parts.length; i++) {
if (parts[i] === 'en' || parts[i] === 'de' || parts[i] === 'ru') {
data.locale = parts[i];
} else if (parseInt(parts[i], 10) === parts[i]) {
data.volume = parseInt(parts[i], 10) / 100;
} else {
data.text = (data.text ? ';' : '') + parts[i];
}
}
} else {
data = {
text: data,
locale: this.settings.systemLang,
volume: this.settings.volume
};
}
}
data.volume = parseInt(data.volume || 100, 10) || 100;
if (data.language) data.locale = data.language;
if (data.lang) data.locale = data.lang;
if (data.locale === 'en') data.locale = 'en-GB';
if (data.locale === 'de') data.locale = 'de-DE';
if (data.locale === 'ru') data.locale = 'ru-RU';
if (this.settings.project && this.settings.recognition) {
this.menu.css('background', 'rgba(0, 0, 0, 0.1)');
this.recognition.stop();
}
if (this.ttsTextTimer) clearTimeout(this.ttsTextTimer);
this.ttsText.html(data.text).show();
this.ttsTextTimer = setTimeout(function () {
this.ttsText.hide();
this.ttsTextTimer = null;
}.bind(this), 3000);
if (window && window.system && window.system.setSystemVolume) {
window.system.setSystemVolume(data.volume / 100);
}
if (typeof TTS !== 'undefined') {
var d = new Date();
console.log('[' + d.getSeconds() + '.' + d.getMilliseconds() + '] Start speaking: ' + JSON.stringify(data));
this.speaking = true;
TTS.speak(data, function () {
var d = new Date();
console.log('[' + d.getSeconds() + '.' + d.getMilliseconds() + '] Stop speaking: ' + JSON.stringify(data));
this.speaking = false;
if (this.settings.project && this.settings.recognition) {
this.menu.css('background', 'rgba(0, 0, 128, 0.5)');
this.recognition.start();
}
cb && cb();
}.bind(this), function (reason) {
console.error(reason);
});
}
},
initSpeechRecognition: function () {
if (this.settings.project && this.settings.recognition && (this.settings.text2command || this.settings.text2command === 0)) {
$('body').append('<div id="cordova_show_recognized" style="display: none; padding: 0.2em; border-radius: 0.4em;position: absolute; z-index: 5000; background: lightskyblue; top: 1em; left: 3em; font-size: 1.5em;"></div>');
this.recText = $('#cordova_show_recognized');
this.recognition = new SpeechRecognition();
this.recognition.maxAlternatives = 3;
this.recognition.continuous = true;
this.recognition.interimResults = true;
this.recognition.lang = this.settings.systemLang;
if (this.settings.keyword) {
this.settings.keyword = this.settings.keyword.trim();
this.settings.keyword = this.settings.keyword.replace(/\s\s/g, ' ');
this.match = [
new RegExp('\\s' + this.settings.keyword + '\\s', 'i'),
new RegExp('^' + this.settings.keyword + '\\s', 'i'),
new RegExp('\\s' + this.settings.keyword + '$', 'i'),
new RegExp('^' + this.settings.keyword + '$', 'i')
];
}
this.recognition.onresult = function(event) {
var matched = false;
if (event.results.length > 0) {
var text = event.results[0][0].transcript;
if (event.results[0][0].final) {
// start analyse
if (this.match) {
for (var k = 0; k < this.match.length; k++) {
if (this.match[k].test(text)) {
text = text.replace(this.match[k], '').replace(/\s\s/g, ' ').trim();
// Key phrase found
matched = true;
break;
}
}
} else {
matched = true;
}
if (matched) {
this.recText.css('background: lightblue');
this.recText.html(text).show();
if (this.settings.defaultRoom) {
text = text + ' [' + this.settings.defaultRoom + ']';
if (!this.defaultRoomRegExp) this.defaultRoomRegExp = new RegExp('\\s\\[' + this.settings.defaultRoom + '\\]', 'i');
}
// restart recognition if text2command inactive
var timeout = setTimeout(function () {
if (!this.settings.noCommInBackground || !this.inBackground) {
this.menu.css('background', 'rgba(0, 0, 128, 0.5)');
if (!this.speaking) this.recognition.start(false);
}
}.bind(this), 1000);
vis.conn._socket.emit('sendTo', 'text2command.' + this.settings.text2command, 'send', text, function (response) {
// stop timeout if no text2command
if (timeout) {
clearTimeout(timeout);
timeout = null;
}
response.response = response.response || '';
if (this.settings.defaultRoom) {
response.response = response.response.replace(this.defaultRoomRegExp, '');
}
if (this.settings.responseWithTts) {
// say answer
this.tts(response.response, function () {
// Start recognition
setTimeout(function () {
if (!this.settings.noCommInBackground || !this.inBackground) {
this.menu.css('background', 'rgba(0, 0, 128, 0.5)');
if (!this.speaking) this.recognition.start(false);
}
}.bind(this), 500);
}.bind(this));
} else {
setTimeout(function () {
if (!this.settings.noCommInBackground || !this.inBackground) {
this.menu.css('background', 'rgba(0, 0, 128, 0.5)');
if (!this.speaking) this.recognition.start(false);
}
}.bind(this), 200);
}
}.bind(this));
}
} else {
if (this.match) {
for (var m = 0; m < this.match.length; m++) {
if (this.match[m].test(text)) {
text = text.replace(this.match[m], '').replace(/\s\s/g, ' ').trim();
// Key phrase found
matched = true;
break;
}
}
}
if (!this.match || matched) {
this.recText.html(text).show();
this.recText.css('background: darkblue');
}
}
if (this.recTextTimeout) clearTimeout(this.recTextTimeout);
this.recTextTimeout = setTimeout(function () {
this.recTextTimeout = null;
this.recText.hide();
}.bind(this), 2000);
}
if (!matched) {
if (!this.settings.noCommInBackground || !this.inBackground) {
setTimeout(function () {
this.menu.css('background', 'rgba(0, 0, 128, 0.5)');
if (!this.speaking) this.recognition.start(false);
}.bind(this), 100);
}
}
}.bind(this);
this.recognition.onend = function(event) {
this.menu.css('background', 'rgba(0, 0, 0, 0.1)');
}.bind(this);
this.recognition.onerror = function(event) {
var d = new Date();
console.log('[' + d.getSeconds() + '.' + d.getMilliseconds() + '] Error by recognizing: ' + JSON.stringify(event));
this.menu.css('background', 'rgba(0, 0, 0, 0.1)');
if (event !== 'Speech recognition is not present or enabled') {
if (!this.settings.noCommInBackground || !this.inBackground) {
setTimeout(function () {
this.menu.css('background', 'rgba(0, 0, 128, 0.5)');
if (!this.speaking) this.recognition.start(true);
}.bind(this), 300);
}
} else {
window.alert(_('Speech recognition is not present or enabled. Google Search must be installed and enabled'));
}
}.bind(this);
this.recognition.ondebug = function (event) {
console.log(JSON.stringify(event));
};
this.menu = $('#cordova_menu');
this.menu.css('background', 'rgba(0, 0, 128, 0.5)');
if (!this.speaking) this.recognition.start(false);
}
},
manageDisplayRotation: function () {
var orientation = window.orientation !== undefined ? window.orientation : window.screen.orientation.angle;
// Manage rotation
this.window = {
orientation: orientation,
width: window.innerWidth,
height: window.innerHeight
};
window.onorientationchange = function () {
var viewportScale;
var orientation = window.orientation !== undefined ? window.orientation : window.screen.orientation.angle;
if (orientation !== 0 && orientation !== 180) {
viewportScale = this.settings.zoomLevelLandscape / 100;
// resize menu button
$('#cordova_menu').css({
width: Math.round(2800 / this.settings.zoomLevelLandscape),
height: Math.round(2200 / this.settings.zoomLevelLandscape),
'font-size': Math.round(1600 / this.settings.zoomLevelLandscape) + 'px'
})
} else {
viewportScale = this.settings.zoomLevelPortrait / 100;
// resize menu button
$('#cordova_menu').css({
width: Math.round(2800 / this.settings.zoomLevelPortrait),
height: Math.round(2200 / this.settings.zoomLevelPortrait),
'font-size': Math.round(1600 / this.settings.zoomLevelPortrait) + 'px'
})
}
if (!$('#cordova_dialog').is(':visible')) {
// resize viewport
$('meta[name=viewport]').attr('content',
'width=' + this.window.width + ',' +
'minimum-scale=' + viewportScale + ', maximum-scale=' + viewportScale + ',initial-scale=' + viewportScale + ', user-scalable=no');
}
}.bind(this);
var viewportScale;
if (orientation !== 0 && orientation !== 180) {
viewportScale = this.settings.zoomLevelLandscape / 100;
} else {
viewportScale = this.settings.zoomLevelPortrait / 100;
}
if (!$('#cordova_dialog').is(':visible')) {
// resize viewport
$('meta[name=viewport]').attr('content',
'width=' + this.window.width + ',' +
'minimum-scale=' + viewportScale + ', maximum-scale=' + viewportScale + ',initial-scale=' + viewportScale + ', user-scalable=no');
}
},
loadCss: function () {
if (this.settings.project) {
this.readLocalFile(this.settings.project + '/vis-user.css', function (error, data) {
if (data) {
$('head').append('<style id="vis-user" class="vis-user">' + data + '</style>');
}
$(document).trigger('vis-user');
});
}
},
installMenu: function () {
var w;
var h;
var f;
var orientation = window.orientation !== undefined ? window.orientation : window.screen.orientation.angle;
if (orientation !== 0 && orientation !== 180) {
w = Math.round(2800 / this.settings.zoomLevelLandscape);
h = Math.round(2200 / this.settings.zoomLevelLandscape);
f = Math.round(1600 / this.settings.zoomLevelLandscape);
} else {
w = Math.round(2800 / this.settings.zoomLevelPortrait);
h = Math.round(2200 / this.settings.zoomLevelPortrait);
f = Math.round(1600 / this.settings.zoomLevelPortrait);
}
var $body = $('body');
// install menu button
$body.append('<div id="cordova_menu" style="top: 0.5em; left: 0.5em; text-align: center; font-size: ' + f + 'px;padding-left: 0.5em; padding-right: 0.5em; width: ' + w + 'px; height: ' + h + 'px; position: fixed; background: rgba(0,0,0,0.1); border-radius: 20px; z-index: 15002" id="cordova_menu">...</div>');
$body.append('<div id="cordova_dialog_bg" style="display: none"></div>' +
'<div id="cordova_dialog">' +
'<div style="padding-left: 1em; font-size: 2em; font-weight: bold; padding-top: 0.5em">' + _('Settings') +
'<span style="padding-left: 1em; font-size: 0.5em" id="cordova_version"></span>' + '</div>' +
'<table style="width: 100%; padding: 1em">' +
'<tr><td colspan="2"><div class="button-group">' +
'<div class="left">' +
'<button id="cordova_reload" style="font-size: 14px;">&#8634;' + _('Reload') + '</button>' +
'<button id="cordova_resync" style="font-size: 14px;">⇔' + _('Re-sync') + '</button>' +
'</div><div class="right">' +
'<button id="cordova_ok" style="font-size: 14px;">✔' + _('Ok') + '</button>' +
'<button id="cordova_cancel" style="font-size: 14px;">&#10060;' + _('Cancel') + '</button>' +
'</div></div></td></tr>' +
// Indicate Connected
'<tr><td class="cordova-settings-label">' + _('Connected') + ':</td></td><tr>' +
'<tr><td class="cordova-settings-value"><div id="cordova_connected"></div></td></tr>' +
// WIFI
'<tr><td class="cordova-settings-label section-legend"><span>' + _('WIFI') + '</span><div class="cordova_toggle" data-group="ssid">▶</div></td></tr>' +
'<tr class="cordova-setting-ssid"><td>' + _('WIFI SSID') + ':</td></tr>' +
'<tr class="cordova-setting-ssid"><td><input class="cordova-setting" data-name="ssid" style="width: calc(100% - 4em)" id="cordova_ssid"/><button id="cordova_ssid_button" style="width: 3em; height: 2.3em;">' + _('Actual') + '</button></td></tr>' +
'<tr class="cordova-setting-ssid"><td class="cordova-settings-label">' + _('WIFI Socket') + ':</td></tr>' +
'<tr class="cordova-setting-ssid"><td><input class="cordova-setting" data-name="socketUrl" style="width: 100%"/></td></tr>' +
'<tr class="cordova-setting-ssid"><td class="cordova-settings-label">' + _('WIFI User') + ':</td></tr>' +
'<tr class="cordova-setting-ssid"><td><input class="cordova-setting" data-name="user" style="width: 100%"/></td></tr>' +
'<tr class="cordova-setting-ssid"><td class="cordova-settings-label">' + _('WIFI Password') + ':</td></tr>' +
'<tr class="cordova-setting-ssid"><td><input class="cordova-setting" data-name="password" type="password" id="cordova-password" style="width: 100%"/></td></tr>' +
'<tr class="cordova-setting-ssid"><td class="cordova-settings-label">' + _('WIFI Password repeat') + ':</td></tr>' +
'<tr class="cordova-setting-ssid"><td><input id="cordova-password-repeat" type="password" style="width: 100%"/></td></tr>' +
'<tr class="cordova-setting-ssid"><td class="cordova-settings-label">' + _('Local write timeout (ms)') + ':</td></tr>' +
'<tr class="cordova-setting-ssid"><td><input class="cordova-setting" data-name="writeTimeout" type="number" min="1000" max="60000" style="width: 100%"/></td></tr>' +
// Project
'<tr><td class="cordova-settings-label">' + _('Project') + ':</td></tr>' +
'<tr><td class="cordova-settings-value"><select class="cordova-setting" data-name="project" id="cordova_project" style="width: 100%"></select></td></tr>' +
// Language
'<tr><td class="cordova-settings-label">' + _('Language') + ':</td></tr>' +
'<tr><td class="cordova-settings-value"><select data-name="systemLang" class="cordova-setting">' +
'<option value="">' + _('System') + '</option>' +
'<option value="en">english</option>' +
'<option value="de">deutsch</option>' +
'<option value="ru">русский</option>' +
'</select></td></tr>' +
// Orientation
'<tr><td class="cordova-settings-label">' + _('Orientation') + ':</td></tr>' +
'<tr><td class="cordova-settings-value"><select data-name="lockorientation" class="cordova-setting">' +
'<option value="0">' + _('orientation_auto') + '</option>' +
'<option value="1">' + _('orientation_portrait') + '</option>' +
'<option value="2">' + _('orientation_landscape') + '</option>' +
'</select></td></tr>' +
// Settings
'<tr><td class="cordova-settings-label"><label for="noSleep">' + _('Prevent from sleep') + ':</label></td></tr>' +
'<tr><td><input id="noSleep" class="cordova-setting" data-name="noSleep" type="checkbox"/><label for="noSleep" class="checkbox">&#8226;</label></td></tr>' +
'<tr><td class="cordova-settings-label"><label for="allowMove">' + _('Allow window move') + ':</label></td></tr>' +
'<tr><td><input id="allowMove" class="cordova-setting" data-name="allowMove" type="checkbox"/><label for="allowMove" class="checkbox">&#8226;</label></td></tr>' +
'<tr class="cordova-settings-dont-cache"><td class="cordova-settings-label"><label for="dontCache">' + _('Read always config from server') + ':</label></td></tr>' +
'<tr class="cordova-settings-dont-cache"><td><input id="dontCache" class="cordova-setting" data-name="dontCache" type="checkbox"/><label for="dontCache" class="checkbox">&#8226;</label></td></tr>' +
'<tr><td class="cordova-settings-label"><label for="fullscreen">' + _('Fullscreen') + ':</label></td></tr>' +
'<tr><td><input id="fullscreen" class="cordova-setting" data-name="fullscreen" type="checkbox"/><label for="fullscreen" class="checkbox">&#8226;</label></td></tr>' +
'<tr class="cordova-settings-label"><td>' + _('Zoom Level Portrait') + ':</td></tr>' +
'<tr class="cordova-settings-value"><td><input type="number" min="20" max="500" class="cordova-setting" data-name="zoomLevelPortrait" style="width: 80px"/><input type="range" min="20" max="500" class="cordova-setting" data-name="zoomLevelPortrait" style="width: calc(100% - 85px)"/></td></tr>' +
'<tr class="cordova-settings-label"><td>' + _('Zoom Level Landscape') + ':</td></tr>' +
'<tr class="cordova-settings-value"><td><input type="number" min="20" max="500" class="cordova-setting" data-name="zoomLevelLandscape" style="width: 80px"><input type="range" min="20" max="500" class="cordova-setting" data-name="zoomLevelLandscape" style="width: calc(100% - 85px)"/></td></tr>' +
'<tr class="cordova-settings-label"><td>' + _('Substitution URL') + ':</td></tr>' +
'<tr class="cordova-setting-value"><td><input class="cordova-setting" data-name="substitutionUrl" style="width: 100%"/></td></tr>' +
'<tr><td class="cordova-settings-label">' + _('Instance') + ':</td></tr>' +
'<tr><td><input class="cordova-setting" data-name="instance" style="width: 100%"/></td></tr>' +
'<tr><td class="cordova-settings-label"><label for="noCommInBackground">' + _('Sleep in background') + ':</label></td></tr>' +
'<tr><td><input id="noCommInBackground" class="cordova-setting" data-name="noCommInBackground" type="checkbox"/><label for="noCommInBackground" class="checkbox">&#8226;</label></td></tr>' +
'<tr><td class="cordova-settings-label section-legend"><span>' + _('Speech recognition') + '</span><div class="cordova_toggle" data-group="speech">▶</div></td></tr>' +
'<tr class="cordova-setting-speech"><td class="cordova-settings-label"><label for="recognition">' + _('Speech recognition active') + ':</label></td></tr>' +
'<tr class="cordova-setting-speech"><td><input id="recognition" class="cordova-setting" data-name="recognition" type="checkbox"/><label for="recognition" class="checkbox">&#8226;</label></td></tr>' +
'<tr class="cordova-setting-speech cordova-settings-label speech"><td>' + _('Keyword') + ':</td></tr>' +
'<tr class="cordova-setting-speech speech"><td><input class="cordova-setting" data-name="keyword" style="width: 100%"/></td></tr>' +
'<tr class="cordova-setting-speech cordova-settings-label speech"><td>' + _('Text2command') + ':</td></tr>' +
'<tr class="cordova-setting-speech speech"><td><select id="text2command" class="cordova-setting" data-name="text2command" style="width: 100%"></select></td></tr>' +
'<tr class="cordova-setting-speech cordova-settings-label speech"><td>' + _('Volume') + ':</td></tr>' +
'<tr class="cordova-setting-speech speech"><td><input type="range" min="0" max="100" class="cordova-setting" data-name="volume" style="width: 100%"/></td></tr>' +
'<tr class="cordova-setting-speech cordova-settings-label speech"><td>' + _('Default room') + ':</td></tr>' +
'<tr class="cordova-setting-speech speech"><td><select id="defaultRoom" class="cordova-setting" data-name="defaultRoom" style="width: 100%"></select></td></tr>' +
'<tr class="cordova-setting-speech cordova-settings-label speech"><td><label for="responseWithTts">' + _('Response over TTS') + ':</label></td></tr>' +
'<tr class="cordova-setting-speech speech"><td><input id="responseWithTts" class="cordova-setting" data-name="responseWithTts" type="checkbox"/><label for="responseWithTts" class="checkbox">&#8226;</label></td></tr>' +
// Mobile connection
'<tr><td class="cordova-settings-label section-legend"><span>' + _('Cell') + '</span><div class="cordova_toggle" data-group="cell">▶</div></td></tr>' +
'<tr class="cordova-setting-cell"><td><label for="socketPro">' + _('Use yunkong2.pro') + ':</label></td></tr>' +
'<tr class="cordova-setting-cell"><td><input id="socketPro" class="cordova-setting" data-name="socketPro" type="checkbox"/><label for="socketPro" class="checkbox">&#8226;</label></td></tr>' +
'<tr class="cordova-setting-cell cordova-setting-cell-socket"><td class="cordova-settings-label">' + _('Cell Socket') + ':</td></tr>' +
'<tr class="cordova-setting-cell cordova-setting-cell-socket"><td><input class="cordova-setting" data-name="socketUrlGSM" style="width: 100%"/></td></tr>' +
'<tr class="cordova-setting-cell"><td class="cordova-settings-label">' + _('Cell User') + ':</td></tr>' +
'<tr class="cordova-setting-cell"><td><input class="cordova-setting" data-name="userGSM" style="width: 100%"/></td></tr>' +
'<tr class="cordova-setting-cell"><td class="cordova-settings-label">' + _('Cell Password') + ':</td></tr>' +
'<tr class="cordova-setting-cell"><td><input class="cordova-setting" data-name="passwordGSM" type="password" id="cordova-password-gsm" style="width: 100%"/></td></tr>' +
'<tr class="cordova-setting-cell"><td class="cordova-settings-label">' + _('Cell Password repeat') + ':</td></tr>' +
'<tr class="cordova-setting-cell"><td><input id="cordova-password-repeat-gsm" type="password" style="width: 100%"/></td></tr>' +
'<tr class="cordova-setting-cell"><td class="cordova-settings-label"><label for="allowSelfSigned">' + _('Allow self-signed certificates') + ':</label></td></tr>' +
'<tr class="cordova-setting-cell"><td><input id="allowSelfSigned" class="cordova-setting" data-name="allowSelfSigned" type="checkbox"/><label for="allowSelfSigned" class="checkbox">&#8226;</label></td></tr>' +
// Battery and location
'<tr><td class="cordova-settings-label section-legend"><span>' + _('Battery and location') + '</span><div class="cordova_toggle" data-group="battery">▶</div></td></tr>' +
'<tr class="cordova-setting-battery"><td class="cordova-settings-label">' + _('Device name') + ':</td></tr>' +
'<tr class="cordova-setting-battery"><td><input class="cordova-setting" data-name="deviceName" style="width: 100%"/></td></tr>' +
'<tr class="cordova-setting-battery"><td class="cordova-settings-label">' + _('Report battery status') + ':</td></tr>' +
'<tr class="cordova-setting-battery"><td><input id="readBattery" class="cordova-setting" data-name="readBattery" type="checkbox"/><label for="readBattery" class="checkbox">&#8226;</label></td></tr>' +
'<tr class="cordova-setting-battery"><td class="cordova-settings-label">' + _('Position poll interval (sec)') + ':</td></tr>' +
'<tr class="cordova-setting-battery"><td><input type="number" min="0" max="1800" class="cordova-setting" data-name="geoInterval" style="width: 100%"></td></tr>' +
'<tr class="cordova-setting-battery"><td class="cordova-settings-label">' + _('High accuracy position') + ':</td></tr>' +
'<tr class="cordova-setting-battery"><td><input id="geoHighAccuracy" class="cordova-setting" data-name="geoHighAccuracy" type="checkbox"/><label for="geoHighAccuracy" class="checkbox">&#8226;</label></td></tr>' +
'<tr><td>&nbsp;</td></tr>' +
'<tr><td><a href="https://yunkong2.net/apppolicy_' + this.settings.systemLang + '/" target="_blank">' + _('show_policy') + '</a></td></tr>' +
'</select></td></tr>' +
'</table></div>');
cordova.getAppVersion.getVersionNumber().then(function (version) {
$('#cordova_version').text(version);
});
var $dialog = $('#cordova_dialog');
var $settings = $dialog.find('.cordova-setting');
// install sync for zoomLevelPortrait and zoomLevelLandscape
$dialog.find('input[data-name="zoomLevelPortrait"]').change(function() {
if ($(this).attr('type') === 'number') {
$dialog.find('input[data-name="zoomLevelPortrait"][type="range"]').val($(this).val());
} else {
$dialog.find('input[data-name="zoomLevelPortrait"][type="number"]').val($(this).val());
}
}).keyup(function () {
$(this).trigger('change');
}).on('input', function () {
$(this).trigger('change');
});
$dialog.find('input[data-name="zoomLevelLandscape"]').change(function() {
if ($(this).attr('type') === 'number') {
$dialog.find('input[data-name="zoomLevelLandscape"][type="range"]').val($(this).val());
} else {
$dialog.find('input[data-name="zoomLevelLandscape"][type="number"]').val($(this).val());
}
}).keyup(function () {
$(this).trigger('change');
}).on('input', function () {
$(this).trigger('change');
});
$dialog.find('input[data-name="geoInterval"]').change(function() {
if ($(this).attr('type') === 'number') {
$dialog.find('input[data-name="geoInterval"][type="range"]').val($(this).val());
} else {
$dialog.find('input[data-name="geoInterval"][type="number"]').val($(this).val());
}
}).keyup(function () {
$(this).trigger('change');
}).on('input', function () {
$(this).trigger('change');
});
var that = this;
$('#cordova_menu').click(function () {
$('#vis_container').hide();
document.removeEventListener('backbutton', that.onBackButtonGeneral, false);
document.addEventListener('backbutton', that.onBackButtonSettings, false);
// resize viewport
$('meta[name=viewport]').attr('content',
'width=' + (that.window ? that.window.width : window.innerWidth) + ',' +
'minimum-scale=1, maximum-scale=1');
// load settings
$settings.each(function () {
var settingName = $(this).data('name');
if ($(this).attr('type') === 'checkbox') {
$(this).prop('checked', that.settings[settingName]);
if (settingName === 'recognition' && !that.settings.recognition) {
$('.speech').hide();
}
} else {
$(this).val(that.settings[settingName]);
}
});
if ((!that.settings.socketUrl || that.settings.socketUrl === 'http://localhost:8082') && !that.settings.socketPro) {
if (!$('.cordova-setting-ssid').is(':visible')) {
setTimeout(function () {
$('.cordova_toggle[data-group="ssid"]').trigger('click');
}, 1000);
}
}
// read text2command instances
if (typeof vis !== 'undefined' && vis.conn) {
vis.conn._socket.emit('getObjectView', 'system', 'instance', {startkey: 'system.adapter.text2command.', endkey: 'system.adapter.text2command.\u9999'}, function (err, res) {
if (!err && res.rows.length) {
var text = '<option value="">' + _('none') + '</option>';
for (var i = 0; i < res.rows.length; i++) {
text += '<option value="' + res.rows[i].id.substring('system.adapter.text2command.'.length) + '">' + res.rows[i].id.substring('system.adapter.text2command.'.length) + '</option>';
}
$('#text2command').html(text).val(app.settings.text2command);
}
vis.conn._socket.emit('getObjectView', 'system', 'enum', {startkey: 'enum.rooms.', endkey: 'enum.rooms.\u9999'}, function (err, res) {
if (!err && res.rows.length) {
var text = '<option value="">' + _('none') + '</option>';
for (var i = 0; i < res.rows.length; i++) {
text += '<option value="' + res.rows[i].value.common.name + '">' + res.rows[i].value.common.name + '</option>';
}
$('#defaultRoom').html(text).val(app.settings.defaultRoom);
}
});
});
}
if (typeof WifiWizard !== 'undefined') {
WifiWizard.getCurrentSSID(function (response) {
that.ssid = response.replace(/\"/g, '');
if (that.ssid) {
$('#cordova_ssid_button').show();
$('#cordova_ssid').css('width', 'calc(100% - 4em)');
} else {
$('#cordova_ssid_button').hide();
$('#cordova_ssid').css('width', '100%');
}
});
}
if (that.settings.socketPro) {
$('.cordova-setting-cell-socket').hide();
$('#dontCache').prop('checked', false);
$('.cordova-settings-dont-cache').hide();
} else {
$('.cordova-setting-cell-socket').show();
$('.cordova-settings-dont-cache').show();
}
$('.cordova_toggle').unbind('click').click(function () {
if ($(this).html() === '▶') {
$('.cordova-setting-' + $(this).data('group')).show();
$(this).html('▼');
if ($('#socketPro').prop('checked')) {
$('.cordova-setting-cell-socket').hide();
} else {
$('.cordova-setting-cell-socket').show();
}
} else {
$('.cordova-setting-' + $(this).data('group')).hide();
$(this).html('▶');
}
});
$('#socketPro').unbind('change').change(function () {
if ($(this).prop('checked')) {
$('.cordova-setting-cell-socket').hide();
$('#dontCache').prop('checked', false).trigger('change');
$('.cordova-settings-dont-cache').hide();
} else {
$('.cordova-setting-cell-socket').show();
$('.cordova-settings-dont-cache').show();
}
});
$('.cordova-setting-ssid').hide();
$('.cordova-setting-cell').hide();
$('.cordova-setting-speech').hide();
$('.cordova-setting-battery').hide();
$('#cordova-password-repeat').val($('#cordova-password').val());
$('#cordova-password-repeat-gsm').val($('#cordova-password-gsm').val());
$('input[data-name="recognition"]').unbind('change').change(function () {
if ($(this).prop('checked')) {
$('.speech').show();
} else {
$('.speech').hide();
}
});
$('#cordova_ssid_button').unbind('click').click(function () {
$('#cordova_ssid').val(that.ssid);
});
$('#cordova_cancel').unbind('click').click(function () {
document.removeEventListener('backbutton', that.onBackButtonSettings, false);
document.addEventListener('backbutton', that.onBackButtonGeneral, false);
$('#cordova_dialog_bg').hide();
$('#cordova_dialog').hide();
// reset view port scale
$(window).trigger('orientationchange');
$('#vis_container').show();
}).css({height: '2em'});
$('#cordova_reload').unbind('click').click(function () {
document.removeEventListener('backbutton', that.onBackButtonSettings, false);
document.addEventListener('backbutton', that.onBackButtonGeneral, false);
var changed = false;
// save settings
$settings.each(function() {
if ($(this).attr('type') === 'checkbox') {
if (that.settings[$(this).data('name')] != $(this).prop('checked')) {
changed = true;
return false;
}
} else {
if (that.settings[$(this).data('name')] != $(this).val()) {
changed = true;
return false;
}
}
});
if (changed && !window.confirm(_('Discard changes?'))) return;
$('#cordova_dialog_bg').hide();
$('#cordova_dialog').hide();
// reset view port scale
$(window).trigger('orientationchange');
$('#vis_container').show();
window.location.reload();
}).css({height: '2em'});
$('#cordova_resync').unbind('click').click(function () {
document.removeEventListener('backbutton', that.onBackButtonSettings, false);
document.addEventListener('backbutton', that.onBackButtonGeneral, false);
var changed = false;
// save settings
$settings.each(function() {
if ($(this).attr('type') === 'checkbox') {
if (that.settings[$(this).data('name')] != $(this).prop('checked')) {
changed = true;
return false;
}
} else {
if (that.settings[$(this).data('name')] != $(this).val()) {
changed = true;
return false;
}
}
});
//if (changed && !window.confirm(_('Discard changes?'))) return;
that.settings.resync = true;
/*$('#cordova_dialog_bg').hide();
$('#cordova_dialog').hide();
$('#vis_container').show();
that.saveSettings();
window.location.reload();*/
$('#cordova_ok').trigger('click');
}).css({height: '2em'});
$('#cordova_ok').unbind('click').click(function () {
document.removeEventListener('backbutton', that.onBackButtonSettings, false);
if ($('#cordova-password').val() !== $('#cordova-password-repeat').val()) {
window.alert(_('WIFI password repeat does not equal to repeat'));
return;
}
if ($('#cordova-password-gsm').val() !== $('#cordova-password-repeat-gsm').val()) {
window.alert(_('Cell password repeat does not equal to repeat'));
return;
}
$('#cordova_dialog_bg').hide();
$('#cordova_dialog').hide();
// reset view port scale
$(window).trigger('orientationchange');
$('#vis_container').show();
var changed = false;
var projectChanged = false;
// save settings
$settings.each(function() {
if ($(this).attr('type') === 'checkbox') {
if (that.settings[$(this).data('name')] != $(this).prop('checked')) {
that.settings[$(this).data('name')] = $(this).prop('checked');
changed = true;
}
} else {
if (that.settings[$(this).data('name')] != $(this).val()) {
that.settings[$(this).data('name')] = $(this).val();
changed = true;
if ($(this).data('name') === 'project') projectChanged = true;
}
}
});
if (changed || that.settings.resync) {
// If project name changed
if ((projectChanged || that.settings.resync) && vis.conn && vis.conn.getIsConnected()) {
// try to load all files
that.syncVis(that.settings.project, function () {
that.settings.resync = false;
that.saveSettings();
if (!that.viewExists) {
window.alert(_('No views found in %s', that.settings.project));
} else {
window.location.reload();
}
});
} else {
that.saveSettings();
window.location.reload();
}
}
}).css({height: '2em'});
if (!that.projects.length && that.connected) that.readProjects();
$('#cordova_dialog_bg').show();
$('#cordova_dialog').show();
});
},
onConnChange: function (connected) {
this.connected = connected;
this.startStopPollPosition(connected);
if (connected) {
$('#cordova_connected').html('<span style="color: green">' + this.yes +'</span>');
// load projects only if menu is opened
if (!this.projects.length && $('#cordova_dialog').is(':visible')) this.readProjects();
if (this._connectInterval) {
clearInterval(this._connectInterval);
this._connectInterval = null;
}
if (this._countInterval) {
clearInterval(this._countInterval);
this._countInterval = null;
}
this.createStates();
this.onLocation(this.lastPosition);
this.onBatteryStatus(this.lastBatteryStatus);
} else {
$('#cordova_connected').html('<span style="color: red">' + this.no +'</span>');
if (this._connectInterval) {
clearInterval(this._connectInterval);
this._connectInterval = null;
}
if (this._countInterval) {
clearInterval(this._countInterval);
this._countInterval = null;
}
// force reconnection
if (!this.settings.noCommInBackground || !this.inBackground) {
// reconnect
this._connectInterval = setInterval(function () {
console.log('Trying connect...');
vis.conn._socket.connect();
this._countDown = 10;
$('.splash-screen-text').html(this._countDown + '...').css('color', 'red');
}.bind(this), 10000);
this._countDown = 10;
$('.splash-screen-text').html(this._countDown + '...');
this._countInterval = setInterval(function () {
this._countDown--;
$('.splash-screen-text').html(this._countDown + '...');
}.bind(this), 1000);
}
}
},
// used in basic.html
replaceFilePathJson: function (data) {
if (typeof data === 'object') data = JSON.stringify(data);
//console.log ('data: ' + data);
var m;
var newName;
var mm;
if (typeof data === 'string') {
// try to replace <img src="/vis.0/main...">
m = data.match(/src=\\"\/[-_0-9\w]+(?:\.[-_0-9\w]+)?\/[^"^']+[-_0-9\w\.]+\.(?:png|jpg|jpeg|gif|wav|mp3|bmp|svg)+\\"/g);
if (m) {
for (mm = 0; mm < m.length; mm++) {
//file:///data/data/net.yunkong2.vis/files/main/vis-user.css
//cdvfile://localhost/persistent
var fn = m[mm].substring(7); // remove src=\"/
var originalFileName = fn.replace(/\\"/g, ''); // remove last "
var p = fn.split('/');
var adapter = p.shift(); // remove vis.0 or whatever
fn = p.shift(); // keep only one subdirectory
fn += p.length ? '/' + p.join('') : '';// all other subdirectories combine in one name because of store bug
newName = originalFileName;
if (newName[0] === '/') newName = newName.substring(1);
if (newName[newName.length - 1] === '"') newName = newName.substring(0, newName.length - 2);
newName = ('/' + newName).replace('/vis.0/', '');
// ignore proxy requests.
if (adapter.match(/^proxy\.\d+$/)) {
// replace "/proxy.0/aaa.png" with http(s)://socketURL/proxy.0/aaa.png
data = data.replace(m[mm], 'src=\\"' + this.currentUrl + '/' + originalFileName);
continue;
}
// files cannot be stored directly in root
if (adapter === 'vis.0' && fn.indexOf('/') !== -1) adapter = '';
// remove spaces in names because they will be %20
data = data.replace(m[mm], 'src=\\"' + this.directory + adapter + fn.replace(/\s/g, '_'));
}
}
// try to replace <img src='/vis.0/main...'>
m = data.match(/src='\/[-_0-9\w]+(?:\.[-_0-9\w]+)?\/[^"^']+[-_0-9\w\.]+\.(?:png|jpg|jpeg|gif|wav|mp3|bmp|svg)+'/g);
if (m) {
for (mm = 0; mm < m.length; mm++) {
//file:///data/data/net.yunkong2.vis/files/main/vis-user.css
//cdvfile://localhost/persistent
var fn = m[mm].substring(6); // remove src="/
var originalFileName = fn.replace(/'/g, ''); // remove last "
var p = fn.split('/');
var adapter = p.shift(); // remove vis.0 or whatever
fn = p.shift(); // keep only one subdirectory
fn += p.length ? '/' + p.join('') : '';// all other subdirectories combine in one name because of store bug
// ignore proxy requests.
if (adapter.match(/^proxy\.\d+$/)) {
// replace "/proxy.0/aaa.png" with http(s)://socketURL/proxy.0/aaa.png
data = data.replace(m[mm], "src='" + this.currentUrl + '/' + originalFileName);
continue;
}
newName = originalFileName;
if (newName[0] === '/') newName = newName.substring(1);
if (newName[newName.length - 1] === "'") newName = newName.substring(0, newName.length - 1);
newName = ('/' + newName).replace('/vis.0/', '');
// files cannot be stored directly in root
if (adapter === 'vis.0' && fn.indexOf('/') !== -1) adapter = '';
// remove spaces in names because they will be %20
data = data.replace(m[mm], "src='" + this.directory + adapter + fn.replace(/\s/g, '_'));
}
}
}
//console.log ('data2: ' + data);
return data;
},
replaceFilePathSrc: function (data) {
var m;
var newName;
var mm;
if (typeof data === 'string') {
// try to replace <img src="/vis.0/main...">
m = data.match(/src="\/[-_0-9\w]+(?:\.[-_0-9\w]+)?\/[^"^']+[-_0-9\w\.]+\.(?:png|jpg|jpeg|gif|wav|mp3|bmp|svg)+"/g);
if (m) {
for (mm = 0; mm < m.length; mm++) {
//file:///data/data/net.yunkong2.vis/files/main/vis-user.css
//cdvfile://localhost/persistent
var fn = m[mm].substring(6); // remove src="/
var originalFileName = fn.replace(/"/g, ''); // remove last "
var p = fn.split('/');
var adapter = p.shift(); // remove vis.0 or whatever
fn = p.shift(); // keep only one subdirectory
fn += p.length ? '/' + p.join('') : '';// all other subdirectories combine in one name because of store bug
newName = originalFileName;
if (newName[0] === '/') newName = newName.substring(1);
if (newName[newName.length - 1] === '"') newName = newName.substring(0, newName.length - 2);
newName = ('/' + newName).replace('/vis.0/', '');
// ignore proxy requests.
if (adapter.match(/^proxy\.\d+$/)) {
// replace "/proxy.0/aaa.png" with http(s)://socketURL/proxy.0/aaa.png
data = data.replace(m[mm], 'src="' + this.currentUrl + '/' + originalFileName);
continue;
}
// files cannot be stored directly in root
if (adapter === 'vis.0' && fn.indexOf('/') !== -1) adapter = '';
// remove spaces in names because they will be %20
data = data.replace(m[mm], 'src="' + this.directory + adapter + fn.replace(/\s/g, '_'));
}
}
// try to replace <img src='/vis.0/main...'>
m = data.match(/src='\/[-_0-9\w]+(?:\.[-_0-9\w]+)?\/[^"^']+[-_0-9\w\.]+\.(?:png|jpg|jpeg|gif|wav|mp3|bmp|svg)+'/g);
if (m) {
for (mm = 0; mm < m.length; mm++) {
//file:///data/data/net.yunkong2.vis/files/main/vis-user.css
//cdvfile://localhost/persistent
var fn = m[mm].substring(6); // remove src="/
var originalFileName = fn.replace(/'/g, ''); // remove last "
var p = fn.split('/');
var adapter = p.shift(); // remove vis.0 or whatever
fn = p.shift(); // keep only one subdirectory
fn += p.length ? '/' + p.join('') : '';// all other subdirectories combine in one name because of store bug
// ignore proxy requests.
if (adapter.match(/^proxy\.\d+$/)) {
// replace "/proxy.0/aaa.png" with http(s)://socketURL/proxy.0/aaa.png
data = data.replace(m[mm], "src='" + this.currentUrl + '/' + originalFileName);
continue;
}
newName = originalFileName;
if (newName[0] === '/') newName = newName.substring(1);
if (newName[newName.length - 1] === "'") newName = newName.substring(0, newName.length - 1);
newName = ('/' + newName).replace('/vis.0/', '');
// files cannot be stored directly in root
if (adapter === 'vis.0' && fn.indexOf('/') !== -1) adapter = '';
// remove spaces in names because they will be %20
data = data.replace(m[mm], "src='" + this.directory + adapter + fn.replace(/\s/g, '_'));
}
}
}
return data;
},
replaceFilePathImg: function (data) {
var m;
var newName;
var mm;
if (typeof data === 'string') {
// try to replace /vis.0/main...
m = data.match(/^\/[-_0-9\w]+(?:\.[-_0-9\w]+)?\/[^"^']+[-_0-9\w\.]+\.(?:png|jpg|jpeg|gif|wav|mp3|bmp|svg)+$/g);
if (m) {
for (mm = 0; mm < m.length; mm++) {
//file:///data/data/net.yunkong2.vis/files/main/vis-user.css
//cdvfile://localhost/persistent
var fn = m[mm].substring(6); // remove src="/
var originalFileName = fn; // remove last "
var p = fn.split('/');
var adapter = p.shift(); // remove vis.0 or whatever
fn = p.shift(); // keep only one subdirectory
fn += p.length ? '/' + p.join('') : '';// all other subdirectories combine in one name because of store bug
newName = originalFileName;
if (newName[0] === '/') newName = newName.substring(1);
if (newName[newName.length - 1] === '"') newName = newName.substring(0, newName.length - 2);
newName = ('/' + newName).replace('/vis.0/', '');
// ignore proxy requests.
if (adapter.match(/^proxy\.\d+$/)) {
// replace "/proxy.0/aaa.png" with http(s)://socketURL/proxy.0/aaa.png
data = data.replace(m[mm], 'src="' + this.currentUrl + '/' + originalFileName);
continue;
}
// files cannot be stored directly in root
if (adapter === 'vis.0' && fn.indexOf('/') !== -1) adapter = '';
// remove spaces in names because they will be %20
data = data.replace(m[mm], this.directory + adapter + fn.replace(/\s/g, '_'));
}
}
}
return data;
}
};
function logout() {
window.close(); // workaround for blocking windows
navigator.app.exitApp();
}
function escapeRegExp(str) {
return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&');
}
app.initialize();