/* * 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('
.pro
'); $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('').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 += ''; } $('#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 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 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 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 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 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 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( '
' + '
' + '
'); } 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('
'); 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(''); 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(''); } $(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('
...
'); $body.append('' + '
' + '
' + _('Settings') + '' + '
' + '' + '' + // Indicate Connected '' + '' + // WIFI '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + // Project '' + '' + // Language '' + '' + // Orientation '' + '' + // Settings '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + // Mobile connection '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + // Battery and location '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '
' + '
' + '' + '' + '
' + '' + '' + '
' + _('Connected') + ':
' + _('WIFI') + '
' + _('WIFI SSID') + ':
' + _('WIFI Socket') + ':
' + _('WIFI User') + ':
' + _('WIFI Password') + ':
' + _('WIFI Password repeat') + ':
' + _('Local write timeout (ms)') + ':
' + _('Project') + ':
' + _('Language') + ':
' + _('Orientation') + ':
' + _('Zoom Level Portrait') + ':
' + _('Zoom Level Landscape') + ':
' + _('Substitution URL') + ':
' + _('Instance') + ':
' + _('Speech recognition') + '
' + _('Keyword') + ':
' + _('Text2command') + ':
' + _('Volume') + ':
' + _('Default room') + ':
' + _('Cell') + '
' + _('Cell Socket') + ':
' + _('Cell User') + ':
' + _('Cell Password') + ':
' + _('Cell Password repeat') + ':
' + _('Battery and location') + '
' + _('Device name') + ':
' + _('Report battery status') + ':
' + _('Position poll interval (sec)') + ':
' + _('High accuracy position') + ':
 
' + _('show_policy') + '
'); 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 = ''; for (var i = 0; i < res.rows.length; i++) { text += ''; } $('#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 = ''; for (var i = 0; i < res.rows.length; i++) { text += ''; } $('#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('' + this.yes +''); // 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('' + this.no +''); 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 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 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 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 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();