diff --git a/install.sh b/install.sh
index d402325e6..31c12eefb 100644
--- a/install.sh
+++ b/install.sh
@@ -2,8 +2,8 @@
alias=r1
-# 20220810
-! grep -q bluez-utils /etc/pacman.conf && sed -i '/#IgnorePkg/ a\IgnorePkg = bluez-utils' /etc/pacman.conf
+# 20220814
+sed -i '/bluez-utils/ d' /etc/pacman.conf
# 20220805
dirdata=/srv/http/data
diff --git a/srv/http/assets/css/info.css b/srv/http/assets/css/info.css
index e88189aa4..dd87936b5 100644
--- a/srv/http/assets/css/info.css
+++ b/srv/http/assets/css/info.css
@@ -276,6 +276,7 @@ hr {
}
#infoContent .bklabel {
height: auto;
+ line-height: 30px;
}
#infoTopBg {
width: 100%;
diff --git a/srv/http/assets/css/simple-keyboard-3.4.81.min.css b/srv/http/assets/css/simple-keyboard-3.4.139.min.css
similarity index 100%
rename from srv/http/assets/css/simple-keyboard-3.4.81.min.css
rename to srv/http/assets/css/simple-keyboard-3.4.139.min.css
diff --git a/srv/http/assets/js/context.js b/srv/http/assets/js/context.js
index 658aa218c..bb3e0778c 100644
--- a/srv/http/assets/js/context.js
+++ b/srv/http/assets/js/context.js
@@ -31,12 +31,7 @@ function bookmarkNew() {
}
, ok : function() {
var name = infoVal();
- $.post( cmdphp, {
- cmd : 'bookmark'
- , path : path
- , name : name
- , coverart : coverart
- }, function( std ) {
+ bash( [ 'bookmarkadd', name, path, coverart ], function( std ) {
if ( std == -1 ) {
bannerHide();
info( {
@@ -46,9 +41,10 @@ function bookmarkNew() {
+'
'+ path +''
+'
'+ name +' already exists.'
} );
+ } else {
+ banner( 'Bookmark Added', path, 'bookmark' );
}
} );
- banner( 'Bookmark Added', path, 'bookmark' );
}
} );
} );
@@ -630,19 +626,26 @@ $( '.contextmenu a, .contextmenu .submenu' ).click( function() {
case 'wrdirdelete':
var path = G.list.li.find( '.lipath' ).text();
info( {
- icon : 'webradio'
- , title : 'Web Radio Delete'
+ icon : G.mode
+ , title : 'Delete Folder'
, message : 'Folder:'
+'
'+ path +''
, oklabel : 'Delete'
, okcolor : red
, ok : function() {
- bash( [ 'wrdirdelete', path ], function( std ) {
+ bash( [ 'wrdirdelete', path, G.mode ], function( std ) {
if ( std == -1 ) {
info( {
icon : 'webradio'
, title : 'Web Radio Delete'
- , message : 'Folder '+ path +' not empty.'
+ , message : 'Folder not empty:'
+ +'
'+ path +''
+ +'
Confirm delete?'
+ , oklabel : 'Delete'
+ , okcolor : red
+ , ok : function() {
+ bash( [ 'wrdirdelete', path, G.mode, 'noconfirm' ] );
+ }
} );
}
} );
@@ -654,8 +657,8 @@ $( '.contextmenu a, .contextmenu .submenu' ).click( function() {
var name = path.pop();
var path = path.join( '/' );
info( {
- icon : 'webradio'
- , title : 'Web Radio Rename'
+ icon : G.mode
+ , title : 'Rename Folder'
, textlabel : 'Name'
, focus : 0
, values : name
@@ -663,7 +666,7 @@ $( '.contextmenu a, .contextmenu .submenu' ).click( function() {
, checkchange : 1
, oklabel : 'Rename'
, ok : function() {
- bash( [ 'wrdirrename', path, name, infoVal() ] );
+ bash( [ 'wrdirrename', path, name, infoVal(), G.mode ] );
}
} );
return
diff --git a/srv/http/assets/js/function.js b/srv/http/assets/js/function.js
index e82617c58..8ca63e9da 100644
--- a/srv/http/assets/js/function.js
+++ b/srv/http/assets/js/function.js
@@ -190,7 +190,7 @@ function contextmenuLibrary( $li, $target ) {
$li.addClass( 'active' );
return
}
- var filemode = [ 'nas', 'sd', 'usb', 'webradio' ].includes( G.mode );
+ var filemode = [ 'nas', 'sd', 'usb', 'dabradio', 'webradio' ].includes( G.mode );
$menu.find( '.playnext, .replace' ).toggleClass( 'hide', !G.status.pllength );
$menu.find( '.replace' ).next().toggleClass( 'hide', !G.status.pllength );
$menu.find( '.refresh-library' ).toggleClass( 'hide', !( 'updating_db' in G.status ) );
@@ -630,15 +630,17 @@ function imageLoad( list ) {
$this.attr( 'src', src );
} );
} else {
- if ( G.mode.slice( -5 ) === 'radio' ) {
- var mode = G.mode;
- var menumode = 'webradio';
- } else {
- var mode = 'folder';
- var menumode = 'folder';
- }
+ var radio = G.mode.slice( -5 ) === 'radio';
$lazyload.off( 'error' ).on( 'error', function() {
- $( this ).replaceWith( '' );
+ var $this = $( this );
+ var dir = $this.parent().hasClass( 'dir' );
+ var mode = dir ? 'folder' : G.mode;
+ if ( radio ) {
+ var menu = dir ? 'wrdir' : 'webradio';
+ } else {
+ var menu = 'folder';
+ }
+ $this.replaceWith( '' );
} );
}
} else {
diff --git a/srv/http/assets/js/main.js b/srv/http/assets/js/main.js
index 4f818a5d5..4f1c57aee 100644
--- a/srv/http/assets/js/main.js
+++ b/srv/http/assets/js/main.js
@@ -1442,7 +1442,7 @@ $( '#lib-mode-list' ).on( 'click', '.mode-bookmark', function( e ) { // delegate
} ).on( 'click', '.bk-remove', function() {
var $this = $( this ).parent();
var path = $this.find( '.lipath' ).text();
- var name = $this.find( '.bklabel' ).text() || path.split( '/' ).pop();
+ var name = $this.find( '.label' ).text() || path.split( '/' ).pop();
var $img = $this.find( 'img' );
if ( $img.length ) {
var src = $img.attr( 'src' );
@@ -1461,36 +1461,26 @@ $( '#lib-mode-list' ).on( 'click', '.mode-bookmark', function( e ) { // delegate
, okcolor : red
, ok : function() {
G.bookmarkedit = 1;
- $.post( cmdphp, {
- cmd : 'bookmarkremove'
- , path : path
- , delete : name
- } );
- $this.parent().remove();
+ bash( [ 'bookmarkremove', name, path ] );
}
} );
} ).on( 'click', '.bk-rename', function() {
var $this = $( this ).parent();
var path = $this.find( '.lipath' ).text();
- var name = $this.find( '.bklabel' ).text() || path.split( '/' ).pop();
+ var name = $this.find( '.label' ).text() || path.split( '/' ).pop();
info( {
- icon : 'bookmark'
- , title : 'Rename Bookmark'
- , message : '
'
+ icon : 'bookmark'
+ , title : 'Rename Bookmark'
+ , message : '
'
+'
'+ name +'
'
- , textlabel : 'To:'
- , values : name
- , checkblank : 1
- , oklabel : '
Rename'
- , ok : function() {
+ , textlabel : 'To:'
+ , values : name
+ , checkblank : 1
+ , checkchanged : 1
+ , oklabel : '
Rename'
+ , ok : function() {
var newname = infoVal();
- $.post( cmdphp, {
- cmd : 'bookmarkrename'
- , path : path
- , name : name
- , rename : newname
- } );
- $this.find( '.bklabel' ).text( newname );
+ bash( [ 'bookmarkrename', name, newname, path ] );
}
} );
} ).on( 'click', '.bk-cover .iconcover', function() {
@@ -1522,7 +1512,7 @@ $( '#lib-mode-list' ).on( 'click', '.mode-bookmark', function( e ) { // delegate
, buttonlabel : !thumbnail ? '' : '
Default'
, buttoncolor : !thumbnail ? '' : orange
, button : !thumbnail ? '' : function() {
- bash( [ 'bookmarkreset', imagepath, name ] );
+ bash( [ 'bookmarkcoverreset', imagepath, name ] );
}
, ok : function() {
imageReplace( imagepath +'/coverart', 'bookmark', name ); // no ext
@@ -1532,7 +1522,7 @@ $( '#lib-mode-list' ).on( 'click', '.mode-bookmark', function( e ) { // delegate
if ( G.drag ) return
G.bookmarkedit = 1;
- G.bklabel = $( this ).find( '.bklabel' );
+ G.bklabel = $( this ).find( '.label' );
$( '.mode-bookmark' ).each( function() {
var $this = $( this );
var path = $this.find( '.lipath' ).text();
@@ -1543,7 +1533,7 @@ $( '#lib-mode-list' ).on( 'click', '.mode-bookmark', function( e ) { // delegate
} );
$( '.mode-bookmark' )
.css( 'background', 'hsl(0,0%,15%)' )
- .find( '.fa-bookmark, .bklabel, img' )
+ .find( '.fa-bookmark, .label, img' )
.css( 'opacity', 0.33 );
} );
new Sortable( document.getElementById( 'lib-mode-list' ), {
diff --git a/srv/http/assets/js/networks.js b/srv/http/assets/js/networks.js
index 1c7ef487e..46df5c6c2 100644
--- a/srv/http/assets/js/networks.js
+++ b/srv/http/assets/js/networks.js
@@ -504,7 +504,7 @@ function renderQR() {
}
}
function scanBluetooth() {
- bash( '/srv/http/bash/settings/networks-scanbt.sh', function( data ) {
+ bash( '/srv/http/bash/settings/networks-scan.sh', function( data ) {
if ( data ) {
G.listbtscan = data;
var htmlbt = '';
@@ -517,7 +517,7 @@ function scanBluetooth() {
}, 'json' );
}
function scanWlan() {
- bash( '/srv/http/bash/settings/networks-scanwlan.sh', function( data ) {
+ bash( '/srv/http/bash/settings/networks-scan.sh wlan', function( data ) {
if ( data ) {
var signals = '';
data.forEach( function( list, i, obj ) {
diff --git a/srv/http/assets/js/passive.js b/srv/http/assets/js/passive.js
index 19d7bfa37..c8a3c2e1b 100644
--- a/srv/http/assets/js/passive.js
+++ b/srv/http/assets/js/passive.js
@@ -56,8 +56,7 @@ function bookmarkCover( src, path ) {
htmlbk += '
';
} else {
htmlbk += '
'
- +'
'
- +''+ path.split( '/' ).pop() +'
'
+ +'
'+ path.split( '/' ).pop() +''
}
$this.find( '.mode' ).html( htmlbk );
return false
@@ -156,23 +155,34 @@ function psBtReceiver( connected ) {
$( '#'+ prefix +'-btsender' ).toggleClass( 'hide', !connected );
}
function psBookmark( data ) {
- if ( 'html' in data ) {
- $( '#lib-mode-list' ).append( data.html );
- } else {
- var $bookmark = $( '.lib-mode' ).filter( function() {
- return $( this ).find( '.lipath' ) === data.path;
- } );
- if ( data.type === 'delete' ) {
- $bookmark.remove();
+ if ( data.type === 'add' ) {
+ if ( data.src ) {
+ var icon = '
';
} else {
- $bookmark.find( '.bklabel' ).text( data.name );
+ var icon = '
'+ data.name +'';
}
+ var html = `
+
+`;
+ $( '#lib-mode-list' ).append( html );
+ } else {
+ $( '.lib-mode.bookmark' ).each( function() {
+ var $this = $( this );
+ if ( $this.find( '.lipath' ).text() === data.path ) {
+ data.type === 'delete' ? $this.remove() : $this.find( '.label' ).text( data.name );
+ return false
+ }
+ } );
}
- $( '.mode-bookmark, .bklabel' ).removeAttr( 'style' );
if ( 'order' in data ) {
G.display.order = data.order;
orderLibrary();
}
+ $( '#lib-mode-list' ).click();
}
function psCoverart( data ) {
clearTimeout( G.timeoutCover );
diff --git a/srv/http/assets/js/plugin/simple-keyboard-3.4.139.min.js b/srv/http/assets/js/plugin/simple-keyboard-3.4.139.min.js
new file mode 100644
index 000000000..f1e521762
--- /dev/null
+++ b/srv/http/assets/js/plugin/simple-keyboard-3.4.139.min.js
@@ -0,0 +1,16 @@
+/*!
+ *
+ * simple-keyboard v3.4.139 (index.modern.js - Modern Browsers bundle)
+ * https://github.com/hodgef/simple-keyboard
+ *
+ * NOTE: This modern browsers bundle (index.modern.js) removes all polyfills
+ * included in the standard version. Use this if you are supporting
+ * modern browsers only. Otherwise, use the standard version (index.js).
+ *
+ * Copyright (c) Francisco Hodge (https://github.com/hodgef) and project contributors.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ */
+!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.SimpleKeyboard=e():t.SimpleKeyboard=e()}(this,(function(){return function(){"use strict";var t={d:function(e,n){for(var o in n)t.o(n,o)&&!t.o(e,o)&&Object.defineProperty(e,o,{enumerable:!0,get:n[o]})},o:function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},r:function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})}},e={};t.r(e),t.d(e,{default:function(){return E}});function n(t){return function(t){if(Array.isArray(t))return i(t)}(t)||function(t){if("undefined"!=typeof Symbol&&null!=t[Symbol.iterator]||null!=t["@@iterator"])return Array.from(t)}(t)||o(t)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function o(t,e){if(t){if("string"==typeof t)return i(t,e);var n=Object.prototype.toString.call(t).slice(8,-1);return"Object"===n&&t.constructor&&(n=t.constructor.name),"Map"===n||"Set"===n?Array.from(t):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?i(t,e):void 0}}function i(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,o=new Array(e);n
3&&void 0!==arguments[3]?arguments[3]:n,i=arguments.length>4&&void 0!==arguments[4]&&arguments[4],a=this.getOptions(),s=[n,o,i],r=e;return("{bksp}"===t||"{backspace}"===t)&&r.length>0?r=this.removeAt.apply(this,[r].concat(s)):("{delete}"===t||"{forwarddelete}"===t)&&r.length>0?r=this.removeForwardsAt.apply(this,[r].concat(s)):"{space}"===t?r=this.addStringAt.apply(this,[r," "].concat(s)):"{tab}"!==t||"boolean"==typeof a.tabCharOnTab&&!1===a.tabCharOnTab?"{enter}"!==t&&"{numpadenter}"!==t||!a.newLineOnEnter?t.includes("numpad")&&Number.isInteger(Number(t[t.length-2]))?r=this.addStringAt.apply(this,[r,t[t.length-2]].concat(s)):"{numpaddivide}"===t?r=this.addStringAt.apply(this,[r,"/"].concat(s)):"{numpadmultiply}"===t?r=this.addStringAt.apply(this,[r,"*"].concat(s)):"{numpadsubtract}"===t?r=this.addStringAt.apply(this,[r,"-"].concat(s)):"{numpadadd}"===t?r=this.addStringAt.apply(this,[r,"+"].concat(s)):"{numpaddecimal}"===t?r=this.addStringAt.apply(this,[r,"."].concat(s)):"{"===t||"}"===t?r=this.addStringAt.apply(this,[r,t].concat(s)):t.includes("{")||t.includes("}")||(r=this.addStringAt.apply(this,[r,t].concat(s))):r=this.addStringAt.apply(this,[r,"\n"].concat(s)):r=this.addStringAt.apply(this,[r,"\t"].concat(s)),r}},{key:"updateCaretPos",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=this.updateCaretPosAction(t,e);this.dispatch((function(t){t.setCaretPosition(n)}))}},{key:"updateCaretPosAction",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=this.getOptions(),o=this.getCaretPosition();return null!=o&&(e?o>0&&(o-=t):o+=t),n.debug&&console.log("Caret at:",o),o}},{key:"addStringAt",value:function(t,e){var n,o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:t.length,i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:t.length,a=arguments.length>4&&void 0!==arguments[4]&&arguments[4];return o||0===o?(n=[t.slice(0,o),e,t.slice(i)].join(""),this.isMaxLengthReached()||a&&this.updateCaretPos(e.length)):n=t+e,n}},{key:"removeAt",value:function(t){var e,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:t.length,o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:t.length,i=arguments.length>3&&void 0!==arguments[3]&&arguments[3];if(0===n&&0===o)return t;if(n===o){var a=/([\uD800-\uDBFF][\uDC00-\uDFFF])/g;n&&n>=0?t.substring(n-2,n).match(a)?(e=t.substr(0,n-2)+t.substr(n),i&&this.updateCaretPos(2,!0)):(e=t.substr(0,n-1)+t.substr(n),i&&this.updateCaretPos(1,!0)):t.slice(-2).match(a)?(e=t.slice(0,-2),i&&this.updateCaretPos(2,!0)):(e=t.slice(0,-1),i&&this.updateCaretPos(1,!0))}else e=t.slice(0,n)+t.slice(o),i&&this.dispatch((function(t){t.setCaretPosition(n)}));return e}},{key:"removeForwardsAt",value:function(t){var e,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:t.length,o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:t.length,i=arguments.length>3&&void 0!==arguments[3]&&arguments[3];if(null==t||!t.length||null===n)return t;if(n===o){var a=/([\uD800-\uDBFF][\uDC00-\uDFFF])/g,s=t.substring(n,n+2),r=s.match(a);e=r?t.substr(0,n)+t.substr(n+2):t.substr(0,n)+t.substr(n+1)}else e=t.slice(0,n)+t.slice(o),i&&this.dispatch((function(t){t.setCaretPosition(n)}));return e}},{key:"handleMaxLength",value:function(t,e){var n=this.getOptions(),o=n.maxLength,i=t[n.inputName||"default"],s=e.length-1>=o;if(e.length<=i.length)return!1;if(Number.isInteger(o))return n.debug&&console.log("maxLength (num) reached:",s),s?(this.maxLengthReached=!0,!0):(this.maxLengthReached=!1,!1);if("object"===a(o)){var r=e.length-1>=o[n.inputName||"default"];return n.debug&&console.log("maxLength (obj) reached:",r),r?(this.maxLengthReached=!0,!0):(this.maxLengthReached=!1,!1)}}},{key:"isMaxLengthReached",value:function(){return Boolean(this.maxLengthReached)}},{key:"isTouchDevice",value:function(){return"ontouchstart"in window||navigator.maxTouchPoints}},{key:"pointerEventsSupported",value:function(){return!!window.PointerEvent}},{key:"camelCase",value:function(t){return t?t.toLowerCase().trim().split(/[.\-_\s]/g).reduce((function(t,e){return e.length?t+e[0].toUpperCase()+e.slice(1):t})):""}},{key:"chunkArray",value:function(t,e){return n(Array(Math.ceil(t.length/e))).map((function(n,o){return t.slice(e*o,e+e*o)}))}},{key:"escapeRegex",value:function(t){return t.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}}],u=[{key:"bindMethods",value:function(t,e){var n,i=function(t,e){var n="undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(!n){if(Array.isArray(t)||(n=o(t))||e&&t&&"number"==typeof t.length){n&&(t=n);var i=0,a=function(){};return{s:a,n:function(){return i>=t.length?{done:!0}:{done:!1,value:t[i++]}},e:function(t){throw t},f:a}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var s,r=!0,u=!1;return{s:function(){n=n.call(t)},n:function(){var t=n.next();return r=t.done,t},e:function(t){u=!0,s=t},f:function(){try{r||null==n.return||n.return()}finally{if(u)throw s}}}}(Object.getOwnPropertyNames(t.prototype));try{for(i.s();!(n=i.n()).done;){var a=n.value;"constructor"===a||"bindMethods"===a||(e[a]=e[a].bind(e))}}catch(t){i.e(t)}finally{i.f()}}}],i&&s(e.prototype,i),u&&s(e,u),Object.defineProperty(e,"prototype",{writable:!1}),t}();r(u,"noop",(function(){}));var l=u;function c(t,e){for(var n=0;n1?null===(e=n)||void 0===e?void 0:e.toLowerCase():n}},{key:"keyCodeToKey",value:function(t){return{8:"Backspace",9:"Tab",13:"Enter",16:"Shift",17:"Ctrl",18:"Alt",19:"Pause",20:"CapsLock",27:"Esc",32:"Space",33:"PageUp",34:"PageDown",35:"End",36:"Home",37:"ArrowLeft",38:"ArrowUp",39:"ArrowRight",40:"ArrowDown",45:"Insert",46:"Delete",48:"0",49:"1",50:"2",51:"3",52:"4",53:"5",54:"6",55:"7",56:"8",57:"9",65:"A",66:"B",67:"C",68:"D",69:"E",70:"F",71:"G",72:"H",73:"I",74:"J",75:"K",76:"L",77:"M",78:"N",79:"O",80:"P",81:"Q",82:"R",83:"S",84:"T",85:"U",86:"V",87:"W",88:"X",89:"Y",90:"Z",91:"Meta",96:"Numpad0",97:"Numpad1",98:"Numpad2",99:"Numpad3",100:"Numpad4",101:"Numpad5",102:"Numpad6",103:"Numpad7",104:"Numpad8",105:"Numpad9",106:"NumpadMultiply",107:"NumpadAdd",109:"NumpadSubtract",110:"NumpadDecimal",111:"NumpadDivide",112:"F1",113:"F2",114:"F3",115:"F4",116:"F5",117:"F6",118:"F7",119:"F8",120:"F9",121:"F10",122:"F11",123:"F12",144:"NumLock",145:"ScrollLock",186:";",187:"=",188:",",189:"-",190:".",191:"/",192:"`",219:"[",220:"\\",221:"]",222:"'"}[t]}}])&&c(e.prototype,n),o&&c(e,o),Object.defineProperty(e,"prototype",{writable:!1}),t}();function h(t,e){for(var n=0;n0&&void 0!==arguments[0]?arguments[0]:n();return r(t,e)},u.appendChild(e)}));var l=a>0,c=document.createElement("div");c.classList.add("hg-candidate-box-prev"),l&&c.classList.add("hg-candidate-box-btn-active"),c.onclick=function(){l&&n.renderPage({candidateListPages:o,targetElement:i,pageIndex:a-1,nbPages:s,onItemSelected:r})},this.candidateBoxElement.appendChild(c),this.candidateBoxElement.appendChild(u);var d=at.length)&&(e=t.length);for(var n=0,o=new Array(e);n1&&void 0!==arguments[1]?arguments[1]:t;this.caretPosition=t,this.caretPositionEnd=e}},{key:"getInputCandidates",value:function(t){var e=this,n=this.options,o=n.layoutCandidates,i=n.layoutCandidatesCaseSensitiveMatch;if(!o||"object"!==m(o))return{};var a=Object.keys(o).filter((function(n){var o=t.substring(0,e.getCaretPositionEnd()||0)||t,a=new RegExp("".concat(e.utilities.escapeRegex(n),"$"),i?"g":"gi");return!!y(o.matchAll(a)).length}));if(a.length>1){var s=a.sort((function(t,e){return e.length-t.length}))[0];return{candidateKey:s,candidateValue:o[s]}}if(a.length){var r=a[0];return{candidateKey:r,candidateValue:o[r]}}return{}}},{key:"showCandidatesBox",value:function(t,e,n){var o=this;this.candidateBox&&this.candidateBox.show({candidateValue:e,targetElement:n,onSelect:function(e,n){var i=o.options.layoutCandidatesCaseSensitiveMatch,a=e.normalize("NFD"),s=o.getInput(o.options.inputName,!0),r=o.getCaretPositionEnd()||0,u=s.substring(0,r||0)||s,l=new RegExp("".concat(o.utilities.escapeRegex(t),"$"),i?"g":"gi"),c=u.replace(l,a),d=s.replace(u,c),h=c.length-u.length,p=(r||s.length)+h;p<0&&(p=0),o.setInput(d,o.options.inputName,!0),o.setCaretPosition(p),"function"==typeof o.options.onChange&&o.options.onChange(o.getInput(o.options.inputName,!0),n),"function"==typeof o.options.onChangeAll&&o.options.onChangeAll(o.getAllInputs(),n)}})}},{key:"handleButtonClicked",value:function(t,e){var n=this.options,o=n.inputName,i=void 0===o?this.defaultName:o,a=n.debug;if("{//}"!==t){this.input[i]||(this.input[i]="");var s=this.utilities.getUpdatedInput(t,this.input[i],this.caretPosition,this.caretPositionEnd);if(this.utilities.isStandardButton(t)&&this.activeInputElement&&this.input[i]&&this.input[i]===s&&0===this.caretPosition&&this.caretPositionEnd===s.length)return this.setInput("",this.options.inputName,!0),this.setCaretPosition(0),this.activeInputElement.value="",this.activeInputElement.setSelectionRange(0,0),void this.handleButtonClicked(t,e);if("function"==typeof this.options.onKeyPress&&this.options.onKeyPress(t,e),this.input[i]!==s&&(!this.options.inputPattern||this.options.inputPattern&&this.inputPatternIsValid(s))){if(this.options.maxLength&&this.utilities.handleMaxLength(this.input,s))return;var r=this.utilities.getUpdatedInput(t,this.input[i],this.caretPosition,this.caretPositionEnd,!0);if(this.setInput(r,this.options.inputName,!0),a&&console.log("Input changed:",this.getAllInputs()),this.options.debug&&console.log("Caret at: ",this.getCaretPosition(),this.getCaretPositionEnd(),"(".concat(this.keyboardDOMClass,")")),this.options.syncInstanceInputs&&this.syncInstanceInputs(),"function"==typeof this.options.onChange&&this.options.onChange(this.getInput(this.options.inputName,!0),e),"function"==typeof this.options.onChangeAll&&this.options.onChangeAll(this.getAllInputs(),e),null!=e&&e.target&&this.options.enableLayoutCandidates){var u,l=this.getInputCandidates(s),c=l.candidateKey,d=l.candidateValue;c&&d?this.showCandidatesBox(c,d,this.keyboardDOM):null===(u=this.candidateBox)||void 0===u||u.destroy()}}a&&console.log("Key pressed:",t)}}},{key:"getMouseHold",value:function(){return this.isMouseHold}},{key:"setMouseHold",value:function(t){this.options.syncInstanceInputs?this.dispatch((function(e){e.isMouseHold=t})):this.isMouseHold=t}},{key:"handleButtonMouseDown",value:function(t,e){var n=this;e&&(this.options.preventMouseDownDefault&&e.preventDefault(),this.options.stopMouseDownPropagation&&e.stopPropagation(),e.target.classList.add(this.activeButtonClass)),this.holdInteractionTimeout&&clearTimeout(this.holdInteractionTimeout),this.holdTimeout&&clearTimeout(this.holdTimeout),this.setMouseHold(!0),this.options.disableButtonHold||(this.holdTimeout=window.setTimeout((function(){(n.getMouseHold()&&(!t.includes("{")&&!t.includes("}")||"{delete}"===t||"{backspace}"===t||"{bksp}"===t||"{space}"===t||"{tab}"===t)||"{arrowright}"===t||"{arrowleft}"===t||"{arrowup}"===t||"{arrowdown}"===t)&&(n.options.debug&&console.log("Button held:",t),n.handleButtonHold(t)),clearTimeout(n.holdTimeout)}),500))}},{key:"handleButtonMouseUp",value:function(t,e){var n=this;e&&(this.options.preventMouseUpDefault&&e.preventDefault&&e.preventDefault(),this.options.stopMouseUpPropagation&&e.stopPropagation&&e.stopPropagation(),!(e.target===this.keyboardDOM||e.target&&this.keyboardDOM.contains(e.target)||this.candidateBox&&this.candidateBox.candidateBoxElement&&(e.target===this.candidateBox.candidateBoxElement||e.target&&this.candidateBox.candidateBoxElement.contains(e.target)))&&this.candidateBox&&this.candidateBox.destroy()),this.recurseButtons((function(t){t.classList.remove(n.activeButtonClass)})),this.setMouseHold(!1),this.holdInteractionTimeout&&clearTimeout(this.holdInteractionTimeout),t&&"function"==typeof this.options.onKeyReleased&&this.options.onKeyReleased(t)}},{key:"handleKeyboardContainerMouseDown",value:function(t){this.options.preventMouseDownDefault&&t.preventDefault()}},{key:"handleButtonHold",value:function(t){var e=this;this.holdInteractionTimeout&&clearTimeout(this.holdInteractionTimeout),this.holdInteractionTimeout=window.setTimeout((function(){e.getMouseHold()?(e.handleButtonClicked(t),e.handleButtonHold(t)):clearTimeout(e.holdInteractionTimeout)}),100)}},{key:"syncInstanceInputs",value:function(){var t=this;this.dispatch((function(e){e.replaceInput(t.input),e.setCaretPosition(t.caretPosition,t.caretPositionEnd)}))}},{key:"clearInput",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.options.inputName||this.defaultName;this.input[t]="",this.setCaretPosition(0),this.options.syncInstanceInputs&&this.syncInstanceInputs()}},{key:"getInput",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.options.inputName||this.defaultName,e=arguments.length>1&&void 0!==arguments[1]&&arguments[1];if(this.options.syncInstanceInputs&&!e&&this.syncInstanceInputs(),this.options.rtl){var n=this.input[t].replace("","").replace("","");return""+n+""}return this.input[t]}},{key:"getAllInputs",value:function(){var t=this,e={};return Object.keys(this.input).forEach((function(n){e[n]=t.getInput(n,!0)})),e}},{key:"setInput",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.options.inputName||this.defaultName,n=arguments.length>2?arguments[2]:void 0;this.input[e]=t,!n&&this.options.syncInstanceInputs&&this.syncInstanceInputs()}},{key:"replaceInput",value:function(t){this.input=t}},{key:"setOptions",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},e=this.changedOptions(t);this.options=Object.assign(this.options,t),e.length&&(this.options.debug&&console.log("changedOptions",e),this.onSetOptions(e),this.render())}},{key:"changedOptions",value:function(t){var e=this;return Object.keys(t).filter((function(n){return JSON.stringify(t[n])!==JSON.stringify(e.options[n])}))}},{key:"onSetOptions",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[];t.includes("layoutName")&&this.candidateBox&&this.candidateBox.destroy(),(t.includes("layoutCandidatesPageSize")||t.includes("layoutCandidates"))&&this.candidateBox&&(this.candidateBox.destroy(),this.candidateBox=new f({utilities:this.utilities}))}},{key:"resetRows",value:function(){this.keyboardRowsDOM&&this.keyboardRowsDOM.remove(),this.keyboardDOM.className=this.keyboardDOMClass,this.keyboardDOM.setAttribute("data-skInstance",this.currentInstanceName),this.buttonElements={}}},{key:"dispatch",value:function(t){if(!window.SimpleKeyboardInstances)throw console.warn("SimpleKeyboardInstances is not defined. Dispatch cannot be called."),new Error("INSTANCES_VAR_ERROR");return Object.keys(window.SimpleKeyboardInstances).forEach((function(e){t(window.SimpleKeyboardInstances[e],e)}))}},{key:"addButtonTheme",value:function(t,e){var n=this;e&&t&&(t.split(" ").forEach((function(o){e.split(" ").forEach((function(e){n.options.buttonTheme||(n.options.buttonTheme=[]);var i=!1;n.options.buttonTheme.map((function(t){if(null!=t&&t.class.split(" ").includes(e)){i=!0;var n=t.buttons.split(" ");n.includes(o)||(i=!0,n.push(o),t.buttons=n.join(" "))}return t})),i||n.options.buttonTheme.push({class:e,buttons:t})}))})),this.render())}},{key:"removeButtonTheme",value:function(t,e){var n=this;if(!t&&!e)return this.options.buttonTheme=[],void this.render();t&&Array.isArray(this.options.buttonTheme)&&this.options.buttonTheme.length&&(t.split(" ").forEach((function(t){var o,i;null===(o=n.options)||void 0===o||null===(i=o.buttonTheme)||void 0===i||i.map((function(o,i){if(o&&e&&e.includes(o.class)||!e){var a,s,r=null===(a=o)||void 0===a?void 0:a.buttons.split(" ").filter((function(e){return e!==t}));o&&null!=r&&r.length?o.buttons=r.join(" "):(null===(s=n.options.buttonTheme)||void 0===s||s.splice(i,1),o=null)}return o}))})),this.render())}},{key:"getButtonElement",value:function(t){var e,n=this.buttonElements[t];return n&&(e=n.length>1?n:n[0]),e}},{key:"inputPatternIsValid",value:function(t){var e,n=this.options.inputPattern;if((e=n instanceof RegExp?n:n[this.options.inputName||this.defaultName])&&t){var o=e.test(t);return this.options.debug&&console.log('inputPattern ("'.concat(e,'"): ').concat(o?"passed":"did not pass!")),o}return!0}},{key:"setEventListeners",value:function(){!this.isFirstKeyboardInstance&&this.allKeyboardInstances||(this.options.debug&&console.log("Caret handling started (".concat(this.keyboardDOMClass,")")),document.addEventListener("keyup",this.handleKeyUp),document.addEventListener("keydown",this.handleKeyDown),document.addEventListener("mouseup",this.handleMouseUp),document.addEventListener("touchend",this.handleTouchEnd),document.addEventListener("select",this.handleSelect),document.addEventListener("selectionchange",this.handleSelectionChange))}},{key:"handleKeyUp",value:function(t){this.caretEventHandler(t),this.options.physicalKeyboardHighlight&&this.physicalKeyboard.handleHighlightKeyUp(t)}},{key:"handleKeyDown",value:function(t){this.options.physicalKeyboardHighlight&&this.physicalKeyboard.handleHighlightKeyDown(t)}},{key:"handleMouseUp",value:function(t){this.caretEventHandler(t)}},{key:"handleTouchEnd",value:function(t){this.caretEventHandler(t)}},{key:"handleSelect",value:function(t){this.caretEventHandler(t)}},{key:"handleSelectionChange",value:function(t){this.caretEventHandler(t)}},{key:"caretEventHandler",value:function(t){var e,n=this;t.target.tagName&&(e=t.target.tagName.toLowerCase()),this.dispatch((function(o){var i=t.target===o.keyboardDOM||t.target&&o.keyboardDOM.contains(t.target);n.options.syncInstanceInputs&&Array.isArray(t.path)&&(i=t.path.some((function(t){var e;return null==t||null===(e=t.hasAttribute)||void 0===e?void 0:e.call(t,"data-skInstance")}))),("textarea"===e||"input"===e&&["text","search","url","tel","password"].includes(t.target.type))&&!o.options.disableCaretPositioning?(o.setCaretPosition(t.target.selectionStart,t.target.selectionEnd),n.activeInputElement=t.target,o.options.debug&&console.log("Caret at: ",o.getCaretPosition(),o.getCaretPositionEnd(),t&&t.target.tagName.toLowerCase(),"(".concat(o.keyboardDOMClass,")"))):!o.options.disableCaretPositioning&&i||"selectionchange"===(null==t?void 0:t.type)||(o.setCaretPosition(null),n.activeInputElement=null,o.options.debug&&console.log('Caret position reset due to "'.concat(null==t?void 0:t.type,'" event'),t))}))}},{key:"recurseButtons",value:function(t){var e=this;t&&Object.keys(this.buttonElements).forEach((function(n){return e.buttonElements[n].forEach(t)}))}},{key:"destroy",value:function(){this.options.debug&&console.log("Destroying simple-keyboard instance: ".concat(this.currentInstanceName)),document.removeEventListener("keyup",this.handleKeyUp),document.removeEventListener("keydown",this.handleKeyDown),document.removeEventListener("mouseup",this.handleMouseUp),document.removeEventListener("touchend",this.handleTouchEnd),document.removeEventListener("select",this.handleSelect),document.removeEventListener("selectionchange",this.handleSelectionChange),document.onpointerup=null,document.ontouchend=null,document.ontouchcancel=null,document.onmouseup=null,this.recurseButtons((function(t){t&&(t.onpointerdown=null,t.onpointerup=null,t.onpointercancel=null,t.ontouchstart=null,t.ontouchend=null,t.ontouchcancel=null,t.onclick=null,t.onmousedown=null,t.onmouseup=null,t.remove(),t=null)})),this.keyboardDOM.onpointerdown=null,this.keyboardDOM.ontouchstart=null,this.keyboardDOM.onmousedown=null,this.resetRows(),this.candidateBox&&(this.candidateBox.destroy(),this.candidateBox=null),this.activeInputElement=null,this.keyboardDOM.removeAttribute("data-skInstance"),this.keyboardDOM.innerHTML="",window.SimpleKeyboardInstances[this.currentInstanceName]=null,delete window.SimpleKeyboardInstances[this.currentInstanceName],this.initialized=!1}},{key:"getButtonThemeClasses",value:function(t){var e=this.options.buttonTheme,n=[];return Array.isArray(e)&&e.forEach((function(e){if(e&&e.class&&"string"==typeof e.class&&e.buttons&&"string"==typeof e.buttons){var o=e.class.split(" ");e.buttons.split(" ").includes(t)&&(n=[].concat(y(n),y(o)))}else console.warn('Incorrect "buttonTheme". Please check the documentation.',e)})),n}},{key:"setDOMButtonAttributes",value:function(t,e){var n=this.options.buttonAttributes;Array.isArray(n)&&n.forEach((function(n){n.attribute&&"string"==typeof n.attribute&&n.value&&"string"==typeof n.value&&n.buttons&&"string"==typeof n.buttons?n.buttons.split(" ").includes(t)&&e(n.attribute,n.value):console.warn('Incorrect "buttonAttributes". Please check the documentation.',n)}))}},{key:"onTouchDeviceDetected",value:function(){this.processAutoTouchEvents(),this.disableContextualWindow()}},{key:"disableContextualWindow",value:function(){window.oncontextmenu=function(t){if(t.target.classList.contains("hg-button"))return t.preventDefault(),t.stopPropagation(),!1}}},{key:"processAutoTouchEvents",value:function(){this.options.autoUseTouchEvents&&(this.options.useTouchEvents=!0,this.options.debug&&console.log("autoUseTouchEvents: Touch device detected, useTouchEvents enabled."))}},{key:"onInit",value:function(){this.options.debug&&console.log("".concat(this.keyboardDOMClass," Initialized")),this.setEventListeners(),"function"==typeof this.options.onInit&&this.options.onInit(this)}},{key:"beforeFirstRender",value:function(){this.utilities.isTouchDevice()&&this.onTouchDeviceDetected(),"function"==typeof this.options.beforeFirstRender&&this.options.beforeFirstRender(this),this.isFirstKeyboardInstance&&this.utilities.pointerEventsSupported()&&!this.options.useTouchEvents&&!this.options.useMouseEvents&&this.options.debug&&console.log("Using PointerEvents as it is supported by this browser"),this.options.useTouchEvents&&this.options.debug&&console.log("useTouchEvents has been enabled. Only touch events will be used.")}},{key:"beforeRender",value:function(){"function"==typeof this.options.beforeRender&&this.options.beforeRender(this)}},{key:"onRender",value:function(){"function"==typeof this.options.onRender&&this.options.onRender(this)}},{key:"onModulesLoaded",value:function(){"function"==typeof this.options.onModulesLoaded&&this.options.onModulesLoaded(this)}},{key:"loadModules",value:function(){var t=this;Array.isArray(this.options.modules)&&(this.options.modules.forEach((function(e){var n=new e(t);n.init&&n.init(t)})),this.keyboardPluginClasses="modules-loaded",this.render(),this.onModulesLoaded())}},{key:"getModuleProp",value:function(t,e){return!!this.modules[t]&&this.modules[t][e]}},{key:"getModulesList",value:function(){return Object.keys(this.modules)}},{key:"parseRowDOMContainers",value:function(t,e,n,o){var i=this,a=Array.from(t.children),s=0;return a.length&&n.forEach((function(n,r){var u=o[r];if(!(u&&u>n))return!1;var l=n-s,c=u-s,d=document.createElement("div");d.className+="hg-button-container";var h="".concat(i.options.layoutName,"-r").concat(e,"c").concat(r);d.setAttribute("data-skUID",h);var p=a.splice(l,c-l+1);s=c-l,p.forEach((function(t){return d.appendChild(t)})),a.splice(l,0,d),t.innerHTML="",a.forEach((function(e){return t.appendChild(e)})),i.options.debug&&console.log("rowDOMContainer",p,l,c,s+1)})),t}},{key:"render",value:function(){var t=this;this.resetRows(),this.initialized||this.beforeFirstRender(),this.beforeRender();var e="hg-layout-".concat(this.options.layoutName),n=this.options.layout||{default:["` 1 2 3 4 5 6 7 8 9 0 - = {bksp}","{tab} q w e r t y u i o p [ ] \\","{lock} a s d f g h j k l ; ' {enter}","{shift} z x c v b n m , . / {shift}",".com @ {space}"],shift:["~ ! @ # $ % ^ & * ( ) _ + {bksp}","{tab} Q W E R T Y U I O P { } |",'{lock} A S D F G H J K L : " {enter}',"{shift} Z X C V B N M < > ? {shift}",".com @ {space}"]},o=this.options.useTouchEvents||!1,i=o?"hg-touch-events":"",a=this.options.useMouseEvents||!1,s=this.options.disableRowButtonContainers;this.keyboardDOM.className=this.getKeyboardClassString(this.options.theme,e,this.keyboardPluginClasses,i),this.keyboardDOM.setAttribute("data-skInstance",this.currentInstanceName),this.keyboardRowsDOM=document.createElement("div"),this.keyboardRowsDOM.className="hg-rows",n[this.options.layoutName||this.defaultName].forEach((function(e,n){var i=e.split(" ");t.options.excludeFromLayout&&t.options.excludeFromLayout[t.options.layoutName||t.defaultName]&&(i=i.filter((function(e){return t.options.excludeFromLayout&&!t.options.excludeFromLayout[t.options.layoutName||t.defaultName].includes(e)})));var r=document.createElement("div");r.className+="hg-row";var u=[],l=[];i.forEach((function(e,i){var c,d=!s&&"string"==typeof e&&e.length>1&&0===e.indexOf("["),h=!s&&"string"==typeof e&&e.length>1&&e.indexOf("]")===e.length-1;d&&(u.push(i),e=e.replace(/\[/g,"")),h&&(l.push(i),e=e.replace(/\]/g,""));var p=t.utilities.getButtonClass(e),f=t.utilities.getButtonDisplayName(e,t.options.display,t.options.mergeDisplay),g=t.options.useButtonTag?"button":"div",m=document.createElement(g);m.className+="hg-button ".concat(p),(c=m.classList).add.apply(c,y(t.getButtonThemeClasses(e))),t.setDOMButtonAttributes(e,(function(t,e){m.setAttribute(t,e)})),t.activeButtonClass="hg-activeButton",!t.utilities.pointerEventsSupported()||o||a?o?(m.ontouchstart=function(n){t.handleButtonClicked(e,n),t.handleButtonMouseDown(e,n)},m.ontouchend=function(n){t.handleButtonMouseUp(e,n)},m.ontouchcancel=function(n){t.handleButtonMouseUp(e,n)}):(m.onclick=function(n){t.setMouseHold(!1),"function"!=typeof t.options.onKeyReleased&&t.handleButtonClicked(e,n)},m.onmousedown=function(n){"function"!=typeof t.options.onKeyReleased||t.isMouseHold||t.handleButtonClicked(e,n),t.handleButtonMouseDown(e,n)},m.onmouseup=function(n){t.handleButtonMouseUp(e,n)}):(m.onpointerdown=function(n){t.handleButtonClicked(e,n),t.handleButtonMouseDown(e,n)},m.onpointerup=function(n){t.handleButtonMouseUp(e,n)},m.onpointercancel=function(n){t.handleButtonMouseUp(e,n)}),m.setAttribute("data-skBtn",e);var v="".concat(t.options.layoutName,"-r").concat(n,"b").concat(i);m.setAttribute("data-skBtnUID",v);var b=document.createElement("span");b.innerHTML=f,m.appendChild(b),t.buttonElements[e]||(t.buttonElements[e]=[]),t.buttonElements[e].push(m),r.appendChild(m)})),r=t.parseRowDOMContainers(r,n,u,l),t.keyboardRowsDOM.appendChild(r)})),this.keyboardDOM.appendChild(this.keyboardRowsDOM),this.onRender(),this.initialized||(this.initialized=!0,!this.utilities.pointerEventsSupported()||o||a?o?(document.ontouchend=function(e){return t.handleButtonMouseUp(void 0,e)},document.ontouchcancel=function(e){return t.handleButtonMouseUp(void 0,e)},this.keyboardDOM.ontouchstart=function(e){return t.handleKeyboardContainerMouseDown(e)}):o||(document.onmouseup=function(e){return t.handleButtonMouseUp(void 0,e)},this.keyboardDOM.onmousedown=function(e){return t.handleKeyboardContainerMouseDown(e)}):(document.onpointerup=function(e){return t.handleButtonMouseUp(void 0,e)},this.keyboardDOM.onpointerdown=function(e){return t.handleKeyboardContainerMouseDown(e)}),this.onInit())}}],n&&b(e.prototype,n),o&&b(e,o),Object.defineProperty(e,"prototype",{writable:!1}),t}(),E=w;return e}()}));
diff --git a/srv/http/assets/js/plugin/simple-keyboard-3.4.81.min.js b/srv/http/assets/js/plugin/simple-keyboard-3.4.81.min.js
deleted file mode 100644
index 2129a8451..000000000
--- a/srv/http/assets/js/plugin/simple-keyboard-3.4.81.min.js
+++ /dev/null
@@ -1,16 +0,0 @@
-/*!
- *
- * simple-keyboard v3.4.81 (index.modern.js - Modern Browsers bundle)
- * https://github.com/hodgef/simple-keyboard
- *
- * NOTE: This modern browsers bundle (index.modern.js) removes all polyfills
- * included in the standard version. Use this if you are supporting
- * modern browsers only. Otherwise, use the standard version (index.js).
- *
- * Copyright (c) Francisco Hodge (https://github.com/hodgef) and project contributors.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- *
- */
-!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.SimpleKeyboard=e():t.SimpleKeyboard=e()}(this,(function(){return function(){"use strict";var t={d:function(e,n){for(var o in n)t.o(n,o)&&!t.o(e,o)&&Object.defineProperty(e,o,{enumerable:!0,get:n[o]})},o:function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},r:function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})}},e={};t.r(e),t.d(e,{default:function(){return k}});function n(t){return function(t){if(Array.isArray(t))return i(t)}(t)||function(t){if("undefined"!=typeof Symbol&&null!=t[Symbol.iterator]||null!=t["@@iterator"])return Array.from(t)}(t)||o(t)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function o(t,e){if(t){if("string"==typeof t)return i(t,e);var n=Object.prototype.toString.call(t).slice(8,-1);return"Object"===n&&t.constructor&&(n=t.constructor.name),"Map"===n||"Set"===n?Array.from(t):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?i(t,e):void 0}}function i(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,o=new Array(e);n=t.length?{done:!0}:{done:!1,value:t[i++]}},e:function(t){throw t},f:a}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var s,r=!0,u=!1;return{s:function(){n=n.call(t)},n:function(){var t=n.next();return r=t.done,t},e:function(t){u=!0,s=t},f:function(){try{r||null==n.return||n.return()}finally{if(u)throw s}}}}(Object.getOwnPropertyNames(t.prototype));try{for(i.s();!(n=i.n()).done;){var a=n.value;"constructor"===a||"bindMethods"===a||(e[a]=e[a].bind(e))}}catch(t){i.e(t)}finally{i.f()}}}],(i=[{key:"getButtonType",value:function(t){return t.includes("{")&&t.includes("}")&&"{//}"!==t?"functionBtn":"standardBtn"}},{key:"getButtonClass",value:function(t){var e=this.getButtonType(t),n=t.replace("{","").replace("}",""),o="";return"standardBtn"!==e&&(o=" hg-button-".concat(n)),"hg-".concat(e).concat(o)}},{key:"getDefaultDiplay",value:function(){return{"{bksp}":"backspace","{backspace}":"backspace","{enter}":"< enter","{shift}":"shift","{shiftleft}":"shift","{shiftright}":"shift","{alt}":"alt","{s}":"shift","{tab}":"tab","{lock}":"caps","{capslock}":"caps","{accept}":"Submit","{space}":" ","{//}":" ","{esc}":"esc","{escape}":"esc","{f1}":"f1","{f2}":"f2","{f3}":"f3","{f4}":"f4","{f5}":"f5","{f6}":"f6","{f7}":"f7","{f8}":"f8","{f9}":"f9","{f10}":"f10","{f11}":"f11","{f12}":"f12","{numpaddivide}":"/","{numlock}":"lock","{arrowup}":"↑","{arrowleft}":"←","{arrowdown}":"↓","{arrowright}":"→","{prtscr}":"print","{scrolllock}":"scroll","{pause}":"pause","{insert}":"ins","{home}":"home","{pageup}":"up","{delete}":"del","{forwarddelete}":"del","{end}":"end","{pagedown}":"down","{numpadmultiply}":"*","{numpadsubtract}":"-","{numpadadd}":"+","{numpadenter}":"enter","{period}":".","{numpaddecimal}":".","{numpad0}":"0","{numpad1}":"1","{numpad2}":"2","{numpad3}":"3","{numpad4}":"4","{numpad5}":"5","{numpad6}":"6","{numpad7}":"7","{numpad8}":"8","{numpad9}":"9"}}},{key:"getButtonDisplayName",value:function(t,e,n){return(e=n?Object.assign({},this.getDefaultDiplay(),e):e||this.getDefaultDiplay())[t]||t}},{key:"getUpdatedInput",value:function(t,e,n){var o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:n,i=arguments.length>4&&void 0!==arguments[4]&&arguments[4],a=this.getOptions(),s=[n,o,i],r=e;return("{bksp}"===t||"{backspace}"===t)&&r.length>0?r=this.removeAt.apply(this,[r].concat(s)):("{delete}"===t||"{forwarddelete}"===t)&&r.length>0?r=this.removeForwardsAt.apply(this,[r].concat(s)):"{space}"===t?r=this.addStringAt.apply(this,[r," "].concat(s)):"{tab}"!==t||"boolean"==typeof a.tabCharOnTab&&!1===a.tabCharOnTab?"{enter}"!==t&&"{numpadenter}"!==t||!a.newLineOnEnter?t.includes("numpad")&&Number.isInteger(Number(t[t.length-2]))?r=this.addStringAt.apply(this,[r,t[t.length-2]].concat(s)):"{numpaddivide}"===t?r=this.addStringAt.apply(this,[r,"/"].concat(s)):"{numpadmultiply}"===t?r=this.addStringAt.apply(this,[r,"*"].concat(s)):"{numpadsubtract}"===t?r=this.addStringAt.apply(this,[r,"-"].concat(s)):"{numpadadd}"===t?r=this.addStringAt.apply(this,[r,"+"].concat(s)):"{numpaddecimal}"===t?r=this.addStringAt.apply(this,[r,"."].concat(s)):"{"===t||"}"===t?r=this.addStringAt.apply(this,[r,t].concat(s)):t.includes("{")||t.includes("}")||(r=this.addStringAt.apply(this,[r,t].concat(s))):r=this.addStringAt.apply(this,[r,"\n"].concat(s)):r=this.addStringAt.apply(this,[r,"\t"].concat(s)),r}},{key:"updateCaretPos",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=this.updateCaretPosAction(t,e);this.dispatch((function(t){t.setCaretPosition(n)}))}},{key:"updateCaretPosAction",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=this.getOptions(),o=this.getCaretPosition();return null!=o&&(e?o>0&&(o-=t):o+=t),n.debug&&console.log("Caret at:",o),o}},{key:"addStringAt",value:function(t,e){var n,o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:t.length,i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:t.length,a=arguments.length>4&&void 0!==arguments[4]&&arguments[4];return o||0===o?(n=[t.slice(0,o),e,t.slice(i)].join(""),this.isMaxLengthReached()||a&&this.updateCaretPos(e.length)):n=t+e,n}},{key:"removeAt",value:function(t){var e,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:t.length,o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:t.length,i=arguments.length>3&&void 0!==arguments[3]&&arguments[3];if(0===n&&0===o)return t;if(n===o){var a=/([\uD800-\uDBFF][\uDC00-\uDFFF])/g;n&&n>=0?t.substring(n-2,n).match(a)?(e=t.substr(0,n-2)+t.substr(n),i&&this.updateCaretPos(2,!0)):(e=t.substr(0,n-1)+t.substr(n),i&&this.updateCaretPos(1,!0)):t.slice(-2).match(a)?(e=t.slice(0,-2),i&&this.updateCaretPos(2,!0)):(e=t.slice(0,-1),i&&this.updateCaretPos(1,!0))}else e=t.slice(0,n)+t.slice(o),i&&this.dispatch((function(t){t.setCaretPosition(n)}));return e}},{key:"removeForwardsAt",value:function(t){var e,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:t.length,o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:t.length,i=arguments.length>3&&void 0!==arguments[3]&&arguments[3];if(null==t||!t.length||null===n)return t;if(n===o){var a=/([\uD800-\uDBFF][\uDC00-\uDFFF])/g,s=t.substring(n,n+2),r=s.match(a);e=r?t.substr(0,n)+t.substr(n+2):t.substr(0,n)+t.substr(n+1)}else e=t.slice(0,n)+t.slice(o),i&&this.dispatch((function(t){t.setCaretPosition(n)}));return e}},{key:"handleMaxLength",value:function(t,e){var n=this.getOptions(),o=n.maxLength,i=t[n.inputName||"default"],s=e.length-1>=o;if(e.length<=i.length)return!1;if(Number.isInteger(o))return n.debug&&console.log("maxLength (num) reached:",s),s?(this.maxLengthReached=!0,!0):(this.maxLengthReached=!1,!1);if("object"===a(o)){var r=e.length-1>=o[n.inputName||"default"];return n.debug&&console.log("maxLength (obj) reached:",r),r?(this.maxLengthReached=!0,!0):(this.maxLengthReached=!1,!1)}}},{key:"isMaxLengthReached",value:function(){return Boolean(this.maxLengthReached)}},{key:"isTouchDevice",value:function(){return"ontouchstart"in window||navigator.maxTouchPoints}},{key:"pointerEventsSupported",value:function(){return!!window.PointerEvent}},{key:"camelCase",value:function(t){return t?t.toLowerCase().trim().split(/[.\-_\s]/g).reduce((function(t,e){return e.length?t+e[0].toUpperCase()+e.slice(1):t})):""}},{key:"chunkArray",value:function(t,e){return n(Array(Math.ceil(t.length/e))).map((function(n,o){return t.slice(e*o,e+e*o)}))}}])&&s(e.prototype,i),u&&s(e,u),Object.defineProperty(e,"prototype",{writable:!1}),t}();r(u,"noop",(function(){}));var l=u;function c(t,e){for(var n=0;n1?null===(e=n)||void 0===e?void 0:e.toLowerCase():n}},{key:"keyCodeToKey",value:function(t){return{8:"Backspace",9:"Tab",13:"Enter",16:"Shift",17:"Ctrl",18:"Alt",19:"Pause",20:"CapsLock",27:"Esc",32:"Space",33:"PageUp",34:"PageDown",35:"End",36:"Home",37:"ArrowLeft",38:"ArrowUp",39:"ArrowRight",40:"ArrowDown",45:"Insert",46:"Delete",48:"0",49:"1",50:"2",51:"3",52:"4",53:"5",54:"6",55:"7",56:"8",57:"9",65:"A",66:"B",67:"C",68:"D",69:"E",70:"F",71:"G",72:"H",73:"I",74:"J",75:"K",76:"L",77:"M",78:"N",79:"O",80:"P",81:"Q",82:"R",83:"S",84:"T",85:"U",86:"V",87:"W",88:"X",89:"Y",90:"Z",91:"Meta",96:"Numpad0",97:"Numpad1",98:"Numpad2",99:"Numpad3",100:"Numpad4",101:"Numpad5",102:"Numpad6",103:"Numpad7",104:"Numpad8",105:"Numpad9",106:"NumpadMultiply",107:"NumpadAdd",109:"NumpadSubtract",110:"NumpadDecimal",111:"NumpadDivide",112:"F1",113:"F2",114:"F3",115:"F4",116:"F5",117:"F6",118:"F7",119:"F8",120:"F9",121:"F10",122:"F11",123:"F12",144:"NumLock",145:"ScrollLock",186:";",187:"=",188:",",189:"-",190:".",191:"/",192:"`",219:"[",220:"\\",221:"]",222:"'"}[t]}}])&&c(e.prototype,n),o&&c(e,o),Object.defineProperty(e,"prototype",{writable:!1}),t}();function h(t,e){for(var n=0;n0&&void 0!==arguments[0]?arguments[0]:n();return r(t,e)},u.appendChild(e)}));var l=a>0,c=document.createElement("div");c.classList.add("hg-candidate-box-prev"),l&&c.classList.add("hg-candidate-box-btn-active"),c.onclick=function(){l&&n.renderPage({candidateListPages:o,targetElement:i,pageIndex:a-1,nbPages:s,onItemSelected:r})},this.candidateBoxElement.appendChild(c),this.candidateBoxElement.appendChild(u);var d=at.length)&&(e=t.length);for(var n=0,o=new Array(e);n1&&void 0!==arguments[1]?arguments[1]:t;this.caretPosition=t,this.caretPositionEnd=e}},{key:"getInputCandidates",value:function(t){var e=this,n=this.options,o=n.layoutCandidates,i=n.layoutCandidatesCaseSensitiveMatch;if(!o||"object"!==g(o))return{};var a=Object.keys(o).filter((function(n){var o=t.substring(0,e.getCaretPositionEnd()||0)||t,a=new RegExp("".concat(n,"$"),i?"g":"gi");return!!f(o.matchAll(a)).length}));if(a.length>1){var s=a.sort((function(t,e){return e.length-t.length}))[0];return{candidateKey:s,candidateValue:o[s]}}if(a.length){var r=a[0];return{candidateKey:r,candidateValue:o[r]}}return{}}},{key:"showCandidatesBox",value:function(t,e,n){var o=this;this.candidateBox&&this.candidateBox.show({candidateValue:e,targetElement:n,onSelect:function(e,n){var i=o.options.layoutCandidatesCaseSensitiveMatch,a=e.normalize("NFD"),s=o.getInput(o.options.inputName,!0),r=o.getCaretPositionEnd()||0,u=s.substring(0,r||0)||s,l=new RegExp("".concat(t,"$"),i?"g":"gi"),c=u.replace(l,a),d=s.replace(u,c),h=c.length-u.length,p=(r||s.length)+h;p<0&&(p=0),o.setInput(d,o.options.inputName,!0),o.setCaretPosition(p),"function"==typeof o.options.onChange&&o.options.onChange(o.getInput(o.options.inputName,!0),n),"function"==typeof o.options.onChangeAll&&o.options.onChangeAll(o.getAllInputs(),n)}})}},{key:"handleButtonClicked",value:function(t,e){var n=this.options,o=n.inputName,i=void 0===o?this.defaultName:o,a=n.debug;if("{//}"!==t){this.input[i]||(this.input[i]="");var s=this.utilities.getUpdatedInput(t,this.input[i],this.caretPosition,this.caretPositionEnd);if(this.utilities.isStandardButton(t)&&this.activeInputElement&&this.input[i]&&this.input[i]===s&&0===this.caretPosition&&this.caretPositionEnd===s.length)return this.setInput("",this.options.inputName,!0),this.setCaretPosition(0),this.activeInputElement.value="",this.activeInputElement.setSelectionRange(0,0),void this.handleButtonClicked(t,e);if("function"==typeof this.options.onKeyPress&&this.options.onKeyPress(t,e),this.input[i]!==s&&(!this.options.inputPattern||this.options.inputPattern&&this.inputPatternIsValid(s))){if(this.options.maxLength&&this.utilities.handleMaxLength(this.input,s))return;var r=this.utilities.getUpdatedInput(t,this.input[i],this.caretPosition,this.caretPositionEnd,!0);if(this.setInput(r,this.options.inputName,!0),a&&console.log("Input changed:",this.getAllInputs()),this.options.debug&&console.log("Caret at: ",this.getCaretPosition(),this.getCaretPositionEnd(),"(".concat(this.keyboardDOMClass,")")),this.options.syncInstanceInputs&&this.syncInstanceInputs(),"function"==typeof this.options.onChange&&this.options.onChange(this.getInput(this.options.inputName,!0),e),"function"==typeof this.options.onChangeAll&&this.options.onChangeAll(this.getAllInputs(),e),null!=e&&e.target&&this.options.enableLayoutCandidates){var u,l=this.getInputCandidates(s),c=l.candidateKey,d=l.candidateValue;c&&d?this.showCandidatesBox(c,d,this.keyboardDOM):null===(u=this.candidateBox)||void 0===u||u.destroy()}}a&&console.log("Key pressed:",t)}}},{key:"getMouseHold",value:function(){return this.isMouseHold}},{key:"setMouseHold",value:function(t){this.options.syncInstanceInputs?this.dispatch((function(e){e.isMouseHold=t})):this.isMouseHold=t}},{key:"handleButtonMouseDown",value:function(t,e){var n=this;e&&(this.options.preventMouseDownDefault&&e.preventDefault(),this.options.stopMouseDownPropagation&&e.stopPropagation(),e.target.classList.add(this.activeButtonClass)),this.holdInteractionTimeout&&clearTimeout(this.holdInteractionTimeout),this.holdTimeout&&clearTimeout(this.holdTimeout),this.setMouseHold(!0),this.options.disableButtonHold||(this.holdTimeout=window.setTimeout((function(){(n.getMouseHold()&&(!t.includes("{")&&!t.includes("}")||"{delete}"===t||"{backspace}"===t||"{bksp}"===t||"{space}"===t||"{tab}"===t)||"{arrowright}"===t||"{arrowleft}"===t||"{arrowup}"===t||"{arrowdown}"===t)&&(n.options.debug&&console.log("Button held:",t),n.handleButtonHold(t)),clearTimeout(n.holdTimeout)}),500))}},{key:"handleButtonMouseUp",value:function(t,e){var n=this;e&&(this.options.preventMouseUpDefault&&e.preventDefault&&e.preventDefault(),this.options.stopMouseUpPropagation&&e.stopPropagation&&e.stopPropagation(),!(e.target===this.keyboardDOM||e.target&&this.keyboardDOM.contains(e.target)||this.candidateBox&&this.candidateBox.candidateBoxElement&&(e.target===this.candidateBox.candidateBoxElement||e.target&&this.candidateBox.candidateBoxElement.contains(e.target)))&&this.candidateBox&&this.candidateBox.destroy()),this.recurseButtons((function(t){t.classList.remove(n.activeButtonClass)})),this.setMouseHold(!1),this.holdInteractionTimeout&&clearTimeout(this.holdInteractionTimeout),t&&"function"==typeof this.options.onKeyReleased&&this.options.onKeyReleased(t)}},{key:"handleKeyboardContainerMouseDown",value:function(t){this.options.preventMouseDownDefault&&t.preventDefault()}},{key:"handleButtonHold",value:function(t){var e=this;this.holdInteractionTimeout&&clearTimeout(this.holdInteractionTimeout),this.holdInteractionTimeout=window.setTimeout((function(){e.getMouseHold()?(e.handleButtonClicked(t),e.handleButtonHold(t)):clearTimeout(e.holdInteractionTimeout)}),100)}},{key:"syncInstanceInputs",value:function(){var t=this;this.dispatch((function(e){e.replaceInput(t.input),e.setCaretPosition(t.caretPosition,t.caretPositionEnd)}))}},{key:"clearInput",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.options.inputName||this.defaultName;this.input[t]="",this.setCaretPosition(0),this.options.syncInstanceInputs&&this.syncInstanceInputs()}},{key:"getInput",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.options.inputName||this.defaultName,e=arguments.length>1&&void 0!==arguments[1]&&arguments[1];if(this.options.syncInstanceInputs&&!e&&this.syncInstanceInputs(),this.options.rtl){var n=this.input[t].replace("","").replace("","");return""+n+""}return this.input[t]}},{key:"getAllInputs",value:function(){var t=this,e={};return Object.keys(this.input).forEach((function(n){e[n]=t.getInput(n,!0)})),e}},{key:"setInput",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.options.inputName||this.defaultName,n=arguments.length>2?arguments[2]:void 0;this.input[e]=t,!n&&this.options.syncInstanceInputs&&this.syncInstanceInputs()}},{key:"replaceInput",value:function(t){this.input=t}},{key:"setOptions",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},e=this.changedOptions(t);this.options=Object.assign(this.options,t),e.length&&(this.options.debug&&console.log("changedOptions",e),this.onSetOptions(e),this.render())}},{key:"changedOptions",value:function(t){var e=this;return Object.keys(t).filter((function(n){return JSON.stringify(t[n])!==JSON.stringify(e.options[n])}))}},{key:"onSetOptions",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[];t.includes("layoutName")&&this.candidateBox&&this.candidateBox.destroy(),(t.includes("layoutCandidatesPageSize")||t.includes("layoutCandidates"))&&this.candidateBox&&(this.candidateBox.destroy(),this.candidateBox=new p({utilities:this.utilities}))}},{key:"resetRows",value:function(){this.keyboardRowsDOM&&this.keyboardRowsDOM.remove(),this.keyboardDOM.className=this.keyboardDOMClass,this.buttonElements={}}},{key:"dispatch",value:function(t){if(!window.SimpleKeyboardInstances)throw console.warn("SimpleKeyboardInstances is not defined. Dispatch cannot be called."),new Error("INSTANCES_VAR_ERROR");return Object.keys(window.SimpleKeyboardInstances).forEach((function(e){t(window.SimpleKeyboardInstances[e],e)}))}},{key:"addButtonTheme",value:function(t,e){var n=this;e&&t&&(t.split(" ").forEach((function(o){e.split(" ").forEach((function(e){n.options.buttonTheme||(n.options.buttonTheme=[]);var i=!1;n.options.buttonTheme.map((function(t){if(null!=t&&t.class.split(" ").includes(e)){i=!0;var n=t.buttons.split(" ");n.includes(o)||(i=!0,n.push(o),t.buttons=n.join(" "))}return t})),i||n.options.buttonTheme.push({class:e,buttons:t})}))})),this.render())}},{key:"removeButtonTheme",value:function(t,e){var n=this;if(!t&&!e)return this.options.buttonTheme=[],void this.render();t&&Array.isArray(this.options.buttonTheme)&&this.options.buttonTheme.length&&(t.split(" ").forEach((function(t){var o,i;null===(o=n.options)||void 0===o||null===(i=o.buttonTheme)||void 0===i||i.map((function(o,i){if(o&&e&&e.includes(o.class)||!e){var a,s,r=null===(a=o)||void 0===a?void 0:a.buttons.split(" ").filter((function(e){return e!==t}));o&&null!=r&&r.length?o.buttons=r.join(" "):(null===(s=n.options.buttonTheme)||void 0===s||s.splice(i,1),o=null)}return o}))})),this.render())}},{key:"getButtonElement",value:function(t){var e,n=this.buttonElements[t];return n&&(e=n.length>1?n:n[0]),e}},{key:"inputPatternIsValid",value:function(t){var e,n=this.options.inputPattern;if((e=n instanceof RegExp?n:n[this.options.inputName||this.defaultName])&&t){var o=e.test(t);return this.options.debug&&console.log('inputPattern ("'.concat(e,'"): ').concat(o?"passed":"did not pass!")),o}return!0}},{key:"setEventListeners",value:function(){!this.isFirstKeyboardInstance&&this.allKeyboardInstances||(this.options.debug&&console.log("Caret handling started (".concat(this.keyboardDOMClass,")")),document.addEventListener("keyup",this.handleKeyUp),document.addEventListener("keydown",this.handleKeyDown),document.addEventListener("mouseup",this.handleMouseUp),document.addEventListener("touchend",this.handleTouchEnd),document.addEventListener("select",this.handleSelect),document.addEventListener("selectionchange",this.handleSelectionChange))}},{key:"handleKeyUp",value:function(t){this.caretEventHandler(t),this.options.physicalKeyboardHighlight&&this.physicalKeyboard.handleHighlightKeyUp(t)}},{key:"handleKeyDown",value:function(t){this.options.physicalKeyboardHighlight&&this.physicalKeyboard.handleHighlightKeyDown(t)}},{key:"handleMouseUp",value:function(t){this.caretEventHandler(t)}},{key:"handleTouchEnd",value:function(t){this.caretEventHandler(t)}},{key:"handleSelect",value:function(t){this.caretEventHandler(t)}},{key:"handleSelectionChange",value:function(t){this.caretEventHandler(t)}},{key:"caretEventHandler",value:function(t){var e,n=this;t.target.tagName&&(e=t.target.tagName.toLowerCase()),this.dispatch((function(o){var i=t.target===o.keyboardDOM||t.target&&o.keyboardDOM.contains(t.target);("textarea"===e||"input"===e&&["text","search","url","tel","password"].includes(t.target.type))&&!o.options.disableCaretPositioning?(o.setCaretPosition(t.target.selectionStart,t.target.selectionEnd),n.activeInputElement=t.target,o.options.debug&&console.log("Caret at: ",o.getCaretPosition(),o.getCaretPositionEnd(),t&&t.target.tagName.toLowerCase(),"(".concat(o.keyboardDOMClass,")"))):!o.options.disableCaretPositioning&&i||"selectionchange"===(null==t?void 0:t.type)||(o.setCaretPosition(null),n.activeInputElement=null,o.options.debug&&console.log('Caret position reset due to "'.concat(null==t?void 0:t.type,'" event'),t))}))}},{key:"recurseButtons",value:function(t){var e=this;t&&Object.keys(this.buttonElements).forEach((function(n){return e.buttonElements[n].forEach(t)}))}},{key:"destroy",value:function(){this.options.debug&&console.log("Destroying simple-keyboard instance: ".concat(this.currentInstanceName)),document.removeEventListener("keyup",this.handleKeyUp),document.removeEventListener("keydown",this.handleKeyDown),document.removeEventListener("mouseup",this.handleMouseUp),document.removeEventListener("touchend",this.handleTouchEnd),document.removeEventListener("select",this.handleSelect),document.removeEventListener("selectionchange",this.handleSelectionChange),document.onpointerup=null,document.ontouchend=null,document.ontouchcancel=null,document.onmouseup=null,this.recurseButtons((function(t){t&&(t.onpointerdown=null,t.onpointerup=null,t.onpointercancel=null,t.ontouchstart=null,t.ontouchend=null,t.ontouchcancel=null,t.onclick=null,t.onmousedown=null,t.onmouseup=null,t.remove(),t=null)})),this.keyboardDOM.onpointerdown=null,this.keyboardDOM.ontouchstart=null,this.keyboardDOM.onmousedown=null,this.resetRows(),this.candidateBox&&(this.candidateBox.destroy(),this.candidateBox=null),this.activeInputElement=null,this.keyboardDOM.innerHTML="",window.SimpleKeyboardInstances[this.currentInstanceName]=null,delete window.SimpleKeyboardInstances[this.currentInstanceName],this.initialized=!1}},{key:"getButtonThemeClasses",value:function(t){var e=this.options.buttonTheme,n=[];return Array.isArray(e)&&e.forEach((function(e){if(e&&e.class&&"string"==typeof e.class&&e.buttons&&"string"==typeof e.buttons){var o=e.class.split(" ");e.buttons.split(" ").includes(t)&&(n=[].concat(f(n),f(o)))}else console.warn('Incorrect "buttonTheme". Please check the documentation.',e)})),n}},{key:"setDOMButtonAttributes",value:function(t,e){var n=this.options.buttonAttributes;Array.isArray(n)&&n.forEach((function(n){n.attribute&&"string"==typeof n.attribute&&n.value&&"string"==typeof n.value&&n.buttons&&"string"==typeof n.buttons?n.buttons.split(" ").includes(t)&&e(n.attribute,n.value):console.warn('Incorrect "buttonAttributes". Please check the documentation.',n)}))}},{key:"onTouchDeviceDetected",value:function(){this.processAutoTouchEvents(),this.disableContextualWindow()}},{key:"disableContextualWindow",value:function(){window.oncontextmenu=function(t){if(t.target.classList.contains("hg-button"))return t.preventDefault(),t.stopPropagation(),!1}}},{key:"processAutoTouchEvents",value:function(){this.options.autoUseTouchEvents&&(this.options.useTouchEvents=!0,this.options.debug&&console.log("autoUseTouchEvents: Touch device detected, useTouchEvents enabled."))}},{key:"onInit",value:function(){this.options.debug&&console.log("".concat(this.keyboardDOMClass," Initialized")),this.setEventListeners(),"function"==typeof this.options.onInit&&this.options.onInit(this)}},{key:"beforeFirstRender",value:function(){this.utilities.isTouchDevice()&&this.onTouchDeviceDetected(),"function"==typeof this.options.beforeFirstRender&&this.options.beforeFirstRender(this),this.isFirstKeyboardInstance&&this.utilities.pointerEventsSupported()&&!this.options.useTouchEvents&&!this.options.useMouseEvents&&this.options.debug&&console.log("Using PointerEvents as it is supported by this browser"),this.options.useTouchEvents&&this.options.debug&&console.log("useTouchEvents has been enabled. Only touch events will be used.")}},{key:"beforeRender",value:function(){"function"==typeof this.options.beforeRender&&this.options.beforeRender(this)}},{key:"onRender",value:function(){"function"==typeof this.options.onRender&&this.options.onRender(this)}},{key:"onModulesLoaded",value:function(){"function"==typeof this.options.onModulesLoaded&&this.options.onModulesLoaded(this)}},{key:"loadModules",value:function(){var t=this;Array.isArray(this.options.modules)&&(this.options.modules.forEach((function(e){var n=new e(t);n.init&&n.init(t)})),this.keyboardPluginClasses="modules-loaded",this.render(),this.onModulesLoaded())}},{key:"getModuleProp",value:function(t,e){return!!this.modules[t]&&this.modules[t][e]}},{key:"getModulesList",value:function(){return Object.keys(this.modules)}},{key:"parseRowDOMContainers",value:function(t,e,n,o){var i=this,a=Array.from(t.children),s=0;return a.length&&n.forEach((function(n,r){var u=o[r];if(!(u&&u>n))return!1;var l=n-s,c=u-s,d=document.createElement("div");d.className+="hg-button-container";var h="".concat(i.options.layoutName,"-r").concat(e,"c").concat(r);d.setAttribute("data-skUID",h);var p=a.splice(l,c-l+1);s=c-l,p.forEach((function(t){return d.appendChild(t)})),a.splice(l,0,d),t.innerHTML="",a.forEach((function(e){return t.appendChild(e)})),i.options.debug&&console.log("rowDOMContainer",p,l,c,s+1)})),t}},{key:"render",value:function(){var t=this;this.resetRows(),this.initialized||this.beforeFirstRender(),this.beforeRender();var e="hg-layout-".concat(this.options.layoutName),n=this.options.layout||{default:["` 1 2 3 4 5 6 7 8 9 0 - = {bksp}","{tab} q w e r t y u i o p [ ] \\","{lock} a s d f g h j k l ; ' {enter}","{shift} z x c v b n m , . / {shift}",".com @ {space}"],shift:["~ ! @ # $ % ^ & * ( ) _ + {bksp}","{tab} Q W E R T Y U I O P { } |",'{lock} A S D F G H J K L : " {enter}',"{shift} Z X C V B N M < > ? {shift}",".com @ {space}"]},o=this.options.useTouchEvents||!1,i=o?"hg-touch-events":"",a=this.options.useMouseEvents||!1,s=this.options.disableRowButtonContainers;this.keyboardDOM.className=this.getKeyboardClassString(this.options.theme,e,this.keyboardPluginClasses,i),this.keyboardRowsDOM=document.createElement("div"),this.keyboardRowsDOM.className="hg-rows",n[this.options.layoutName||this.defaultName].forEach((function(e,n){var i=e.split(" ");t.options.excludeFromLayout&&t.options.excludeFromLayout[t.options.layoutName||t.defaultName]&&(i=i.filter((function(e){return t.options.excludeFromLayout&&!t.options.excludeFromLayout[t.options.layoutName||t.defaultName].includes(e)})));var r=document.createElement("div");r.className+="hg-row";var u=[],l=[];i.forEach((function(e,i){var c,d=!s&&"string"==typeof e&&e.length>1&&0===e.indexOf("["),h=!s&&"string"==typeof e&&e.length>1&&e.indexOf("]")===e.length-1;d&&(u.push(i),e=e.replace(/\[/g,"")),h&&(l.push(i),e=e.replace(/\]/g,""));var p=t.utilities.getButtonClass(e),y=t.utilities.getButtonDisplayName(e,t.options.display,t.options.mergeDisplay),g=t.options.useButtonTag?"button":"div",m=document.createElement(g);m.className+="hg-button ".concat(p),(c=m.classList).add.apply(c,f(t.getButtonThemeClasses(e))),t.setDOMButtonAttributes(e,(function(t,e){m.setAttribute(t,e)})),t.activeButtonClass="hg-activeButton",!t.utilities.pointerEventsSupported()||o||a?o?(m.ontouchstart=function(n){t.handleButtonClicked(e,n),t.handleButtonMouseDown(e,n)},m.ontouchend=function(n){t.handleButtonMouseUp(e,n)},m.ontouchcancel=function(n){t.handleButtonMouseUp(e,n)}):(m.onclick=function(n){t.setMouseHold(!1),t.handleButtonClicked(e,n)},m.onmousedown=function(n){t.handleButtonMouseDown(e,n)},m.onmouseup=function(n){t.handleButtonMouseUp(e,n)}):(m.onpointerdown=function(n){t.handleButtonClicked(e,n),t.handleButtonMouseDown(e,n)},m.onpointerup=function(n){t.handleButtonMouseUp(e,n)},m.onpointercancel=function(n){t.handleButtonMouseUp(e,n)}),m.setAttribute("data-skBtn",e);var v="".concat(t.options.layoutName,"-r").concat(n,"b").concat(i);m.setAttribute("data-skBtnUID",v);var b=document.createElement("span");b.innerHTML=y,m.appendChild(b),t.buttonElements[e]||(t.buttonElements[e]=[]),t.buttonElements[e].push(m),r.appendChild(m)})),r=t.parseRowDOMContainers(r,n,u,l),t.keyboardRowsDOM.appendChild(r)})),this.keyboardDOM.appendChild(this.keyboardRowsDOM),this.onRender(),this.initialized||(this.initialized=!0,!this.utilities.pointerEventsSupported()||o||a?o?(document.ontouchend=function(e){return t.handleButtonMouseUp(void 0,e)},document.ontouchcancel=function(e){return t.handleButtonMouseUp(void 0,e)},this.keyboardDOM.ontouchstart=function(e){return t.handleKeyboardContainerMouseDown(e)}):o||(document.onmouseup=function(e){return t.handleButtonMouseUp(void 0,e)},this.keyboardDOM.onmousedown=function(e){return t.handleKeyboardContainerMouseDown(e)}):(document.onpointerup=function(e){return t.handleButtonMouseUp(void 0,e)},this.keyboardDOM.onpointerdown=function(e){return t.handleKeyboardContainerMouseDown(e)}),this.onInit())}}])&&v(e.prototype,n),o&&v(e,o),Object.defineProperty(e,"prototype",{writable:!1}),t}();return e}()}));
diff --git a/srv/http/assets/js/settings.js b/srv/http/assets/js/settings.js
index d25726a97..018a5520b 100644
--- a/srv/http/assets/js/settings.js
+++ b/srv/http/assets/js/settings.js
@@ -184,7 +184,7 @@ disconnect = () => {
hiddenSet = () => {
if ( page === 'networks' ) {
if ( !$( '#divbluetooth' ).hasClass( 'hide' ) || !$( '#divwifi' ).hasClass( 'hide' ) ) {
- bash( 'killall -q networks-scanbt.sh; killall -q networks-scanwlan.sh' );
+ bash( 'killall -q networks-scan.sh &> /dev/null' );
clearTimeout( G.timeoutScan );
$( '#scanning-bt, #scanning-wifi' ).removeClass( 'blink' );
$( '.back' ).click();
@@ -414,7 +414,7 @@ $( '.container' ).click( function( e ) {
$( '#close' ).click( function() {
if ( page === 'networks' ) {
clearTimeout( G.timeoutScan );
- bash( 'killall networks-scanbt.sh networks-scanwlan.sh &> /dev/null' );
+ bash( 'killall networks-scan.sh &> /dev/null' );
}
bash( [ 'cmd', 'rebootlist' ], function( list ) {
if ( !list ) {
diff --git a/srv/http/bash/bluetoothcommand.sh b/srv/http/bash/bluetoothcommand.sh
index 6dd8fd8e3..f758b48be 100644
--- a/srv/http/bash/bluetoothcommand.sh
+++ b/srv/http/bash/bluetoothcommand.sh
@@ -63,8 +63,9 @@ if [[ $udev == connect ]]; then # >>>> bluetooth.rules: 1. pair from sender; 2.
grep -q $mac $dirshm/btconnected &> /dev/null && mac= || break
fi
done
- # unpaired sender only - fix: rAudio triggered to connect by unpaired receivers when power on
- if bluetoothctl paired-devices | grep -q $mac; then
+ # unpaired sender only - fix: rAudio triggered to connect by unpaired receivers when power on
+ controller=$( bluetoothctl show | head -1 | cut -d' ' -f2 )
+ if [[ -e /var/lib/bluetooth/$controller/$mac ]]; then
if [[ -e $dirsystem/camilladsp ]] && bluetoothctl info $mac | grep -q 'UUID: Audio Sink'; then
name=$( bluetoothctl info $mac | grep '^\s*Alias:' | sed 's/^\s*Alias: //' )
bluetoothctl disconnect $mac
@@ -157,7 +158,8 @@ elif [[ $action == disconnect || $action == remove ]]; then # from rAudio only
else
bluetoothctl remove $mac &> /dev/null
for i in {1..5}; do
- bluetoothctl paired-devices 2> /dev/null | grep -q $mac && sleep 1 || break
+ controller=$( bluetoothctl show | head -1 | cut -d' ' -f2 )
+ [[ -e /var/lib/bluetooth/$controller/$mac ]] && sleep 1 || break
done
disconnectRemove Removed
fi
diff --git a/srv/http/bash/cmd.sh b/srv/http/bash/cmd.sh
index eb74becd3..5af634d6b 100644
--- a/srv/http/bash/cmd.sh
+++ b/srv/http/bash/cmd.sh
@@ -56,6 +56,7 @@ gifThumbnail() {
rm -f "${target:0:-4}".*
[[ $animated ]] && (( ${imgwh[1]/x*} > 200 || ${imgwh[1]/*x} > 200 )) && gifNotify
gifsicle -O3 --resize-fit 200x200 "$source" > "$target"
+ gifsicle -O3 --resize-fit 80x80 "$source" > "$( dirname "$target" )/thumb.gif"
;;
coverart )
dir=$( dirname "$target" )
@@ -78,6 +79,7 @@ gifThumbnail() {
gifsicle -O3 --resize-fit 80x80 $source > $filenoext-thumb.gif
;;
esac
+ pushstreamImage "$target" $type "$covername"
}
jpgThumbnail() {
type=$1
@@ -88,13 +90,14 @@ jpgThumbnail() {
bookmark )
rm -f "${target:0:-4}".*
cp -f "$source" "$target"
+ convert "$target" -thumbnail 80x80\> -unsharp 0x.5 "$( dirname "$target" )/thumb.jpg"
;;
coverart )
dir=$( dirname "$target" )
rm -f "$dir/cover".*.backup "$dir/coverart".* "$dir/thumb".*
coverfile=$( ls -1 "$dir/cover".* 2> /dev/null | head -1 )
[[ -e $coverfile ]] && mv -f "$coverfile" "$coverfile.backup"
- cp -f "$source" "$dir/cover.jpg" # already resized from client
+ cp -f "$source" "$target" # already resized from client
[[ ! -e "$target" ]] && pushstreamNotify ${type^} 'No write permission.' warning && exit
convert "$source" -thumbnail 200x200\> -unsharp 0x.5 "$dir/coverart.jpg"
@@ -108,6 +111,7 @@ jpgThumbnail() {
convert $source -thumbnail 80x80\> -unsharp 0x.5 $filenoext-thumb.jpg
;;
esac
+ pushstreamImage "$target" $type "$covername"
}
mpdoledLogo() {
systemctl stop mpd_oled
@@ -130,6 +134,22 @@ pladdPosition() {
pos=$(( $( mpc playlist | wc -l ) + 1 ))
fi
}
+pushstreamImage() {
+ target=$1
+ [[ ! -e $target ]] && exit
+
+ type=$2
+ covername=$3
+ if [[ $type == bookmark ]]; then
+ bkfile="$dirdata/bookmarks/$covername"
+ echo "$( head -1 "$bkfile" )
+${target/\/srv\/http}" > "$bkfile"
+ fi
+ coverart=${target:0:-4}.$( date +%s ).${target: -3};
+ [[ ${coverart:0:4} == /mnt ]] && coverart=$( php -r "echo rawurlencode( '${coverart//\'/\\\'}' );" )
+ data='{"url":"'$coverart'","type":"'$type'"}'
+ pushstream coverart "$data"
+}
pushstreamPlaylist() {
pushstream playlist "$( php /srv/http/mpdplaylist.php current )"
}
@@ -353,18 +373,66 @@ audiocdtag )
sed -i "$track s|.*|$tag|" $dirdata/audiocd/$discid
pushstreamPlaylist
;;
-bookmarkreset )
+bookmarkadd )
+ name=${args[1]//\//|}
+ path=${args[2]}
+ coverart=${args[3]}
+ bkfile="$dirdata/bookmarks/$name"
+ [[ -e $bkfile ]] && echo -1 && exit
+
+ echo "$path
+$coverart" > "$bkfile"
+ if [[ -e $dirsystem/order ]]; then
+ order=$( jq < $dirsystem/order | jq '. + ["'"$path"'"]' )
+ echo "$order" > $dirsystem/order
+ fi
+ [[ $coverart ]] && src=$( php -r "echo rawurlencode( '${coverart//\'/\\\'}' );" )
+ data='{
+ "type" : "add"
+, "path" : "'$path'"
+, "src" : "'$src'"
+, "name" : "'$name'"
+, "order" : '$order'
+}'
+ pushstream bookmark "$data"
+ ;;
+bookmarkcoverreset )
imagepath=${args[1]}
name=${args[2]}
sed -i '2d' "$dirdata/bookmarks/$name"
- rm -f "$imagepath/coverart".*
- data='{"url":"'$imagepath/reset'","type":"bookmark"}'
+ rm -f "$imagepath/coverart".* "$imagepath/thumb".*
+ data='{
+ "url" : "'$imagepath/reset'"
+, "type" :"bookmark"
+}'
pushstream coverart "$data"
;;
-bookmarkthumb )
- mpdpath=${args[1]}
- coverartfile=$( ls "/mnt/MPD/$mpdpath/coverart".* )
- echo ${coverartfile: -3} # ext
+bookmarkremove )
+ name=${args[1]//\//|}
+ path=${args[2]}
+ rm "$dirdata/bookmarks/$name"
+ if [[ -e $dirsystem/order ]]; then
+ order=$( jq < $dirsystem/order | jq '. - ["'"$path"'"]' )
+ echo "$order" > $dirsystem/order
+ fi
+ data='{
+ "type" : "delete"
+, "path" : "'$path'"
+, "order" :'$( cat $dirsystem/order 2> /dev/null )'
+}'
+ pushstream bookmark "$data"
+ ;;
+bookmarkrename )
+ name=${args[1]//\//|}
+ newname=${args[2]//\//|}
+ path=${args[3]}
+ mv $dirdata/bookmarks/{"$name","$newname"}
+ data='{
+ "type" : "rename"
+, "path" : "'$path'"
+, "name" : "'$newname'"
+}'
+ pushstream bookmark "$data"
;;
camillagui )
systemctl start camillagui
@@ -1269,6 +1337,31 @@ webradiodelete )
[[ -z $( find $dir -name $urlname ) ]] && rm -f "$path/img/$urlname"{,-thumb}.*
webradioCount $type
;;
+wrdirdelete )
+ path=${args[1]}
+ mode=${args[2]}
+ noconfirm=${args[3]}
+ if [[ ! $noconfirm && $( ls -A "$dirdata/$mode/$path" ) ]]; then
+ echo -1
+ else
+ rm -rf "$dirdata/$mode/$path"
+ pushstream radiolist '{"type":"webradio"}'
+ fi
+ ;;
+wrdirnew )
+ dir=${args[1]}
+ sub=${args[2]}
+ [[ $dir ]] && mkdir -p "$dirwebradio/$dir/$path" || mkdir -p "$dirwebradio/$sub"
+ pushstream radiolist '{"type":"webradio"}'
+ ;;
+wrdirrename )
+ path=${args[1]}
+ name=${args[2]}
+ newname=${args[3]}
+ mode=${args[4]}
+ mv -f "$dirdata/$mode/$path/$name" "$dirdata/$mode/$path/$newname"
+ pushstream radiolist '{"type":"webradio"}'
+ ;;
webradioedit )
dir=${args[1]}
name=${args[2]}
@@ -1299,27 +1392,5 @@ $charset" > "$file"
fi
pushstream radiolist '{"type":"webradio"}'
;;
-wrdirdelete )
- path=${args[1]}
- if [[ $( ls -A "$dirwebradio/$path" ) ]]; then
- echo -1
- else
- rm -rf "$dirwebradio/$path"
- pushstream radiolist '{"type":"webradio"}'
- fi
- ;;
-wrdirnew )
- dir=${args[1]}
- sub=${args[2]}
- [[ $dir ]] && mkdir -p "$dirwebradio/$dir/$path" || mkdir -p "$dirwebradio/$sub"
- pushstream radiolist '{"type":"webradio"}'
- ;;
-wrdirrename )
- path=${args[1]}
- name=${args[2]}
- newname=${args[3]}
- mv -f "$dirwebradio/$path/$name" "$dirwebradio/$path/$newname"
- pushstream radiolist '{"type":"webradio"}'
- ;;
esac
diff --git a/srv/http/bash/settings/networks-data.sh b/srv/http/bash/settings/networks-data.sh
index 0338b3cd5..230643e34 100644
--- a/srv/http/bash/settings/networks-data.sh
+++ b/srv/http/bash/settings/networks-data.sh
@@ -4,25 +4,21 @@
# bluetooth
if systemctl -q is-active bluetooth; then
- readarray -t lines <<< $( bluetoothctl paired-devices \
- | cut -d' ' -f2,3- \
- | awk NF \
- | sort -k2 -fh )
- if [[ $lines ]]; then
- for line in "${lines[@]}"; do
- mac=${line/ *}
- [[ $mac == Device ]] && continue
-
- info=$( bluetoothctl info $mac )
- name=$( echo "$info" | grep '^\s*Alias:' | sed 's/^\s*Alias: //' )
- connected=$( echo "$info" | grep -q 'Connected: yes' && echo true || echo false )
- type=$( echo "$info" | grep 'UUID: Audio' | sed -E 's/\s*UUID: Audio (.*) .*/\1/' | xargs )
- [[ ! $type ]] && type=Device
+ controller=$( bluetoothctl show | head -1 | cut -d' ' -f2 )
+ readarray -t macs <<< $( ls -1 /var/lib/bluetooth/$controller | egrep -v 'cache|settings' )
+ if [[ $macs ]]; then
+ for mac in "${macs[@]}"; do
+ readarray -t info <<< $( bluetoothctl info $mac \
+ | egrep 'Name: |Connected: |UUID: Audio' \
+ | sed -E 's/^\s*Name: //
+ s/^\s*Connected: yes/true/
+ s/^\s*Connected: no/false/
+ s/\s*UUID: Audio (.*) .*/\1/' )
listbt+=',{
- "name" : "'$name'"
-, "mac" : "'$mac'"
-, "connected" : '$connected'
-, "type" : "'$type'"
+ "mac" : "'$mac'"
+, "name" : "'${info[0]}'"
+, "connected" : '${info[1]}'
+, "type" : "'${info[2]}'"
}'
done
listbt="[ ${listbt:1} ]"
diff --git a/srv/http/bash/settings/networks-scan.sh b/srv/http/bash/settings/networks-scan.sh
new file mode 100644
index 000000000..47425dbff
--- /dev/null
+++ b/srv/http/bash/settings/networks-scan.sh
@@ -0,0 +1,71 @@
+#!/bin/bash
+
+. /srv/http/bash/common.sh
+
+if [[ $1 == wlan ]]; then
+ wlandev=$( cat $dirshm/wlan )
+ ip link set $wlandev up
+
+ # pre-scan hidden ssid to force responding to scan
+ readarray -t hiddenprofiles <<< $( grep -rl --exclude-dir=examples ^Hidden=yes /etc/netctl )
+ if [[ $hiddenprofiles ]]; then
+ for file in "${hiddenprofiles[@]}"; do
+ iwlist $wlandev scan essid "$( basename "$file" )" &> /dev/null
+ done
+ fi
+
+ # ESSID:"NAME"
+ # Encryption key:on
+ # Quality=37/70 Signal level=-73 dBm --- Quality=0/100 Signal level=25/100
+ # IE: IEEE 802.11i/WPA2 Version 1
+ # IE: WPA Version 1
+ scan=$( iwlist $wlandev scan \
+ | sed -E 's/^\s*|\s*$//g' \
+ | egrep '^Cell|^ESSID|^Encryption|^IE.*WPA|^Quality' \
+ | sed -E 's/^Cell.*/},{/
+ s/^ESSID:/,"ssid":/
+ s/\\x00//g
+ s/^Encryption key:(.*)/,"encrypt":"\1"/
+ s/^IE.*WPA.*/,"wpa":true/
+ s/^Quality.*level.(.*)/,"signal":"\1"/' \
+ | sed '/},{/ {n;s/^,/ /}' )
+ # save profile
+ readarray -t ssids <<< $( grep '"ssid":' <<< "$scan" \
+ | sed -E 's/^.*:"(.*)"/\1/' \
+ | awk NF )
+ for ssid in "${ssids[@]}"; do
+ [[ -e "/etc/netctl/$ssid" ]] && scan=$( sed '/"ssid":"'$ssid'"/ a\,"profile":true' <<< "$scan" )
+ done
+ # connected ssid
+ connectedssid=$( iwgetid $wlandev -r )
+ scan=$( sed '/"ssid":"'$connectedssid'"/ a\,"connected":true' <<< "$scan" )
+
+ # },{... > [ {...} ]
+ echo "[ ${scan:2} } ]" | jq
+ exit
+fi
+
+bluetoothctl --timeout=10 scan on &> /dev/null
+devices=$( bluetoothctl devices \
+ | grep -v ' ..-..-..-..-..-..$' \
+ | sed -E 's/Device (..:..:..:..:..:..) (.*)/\2^\1/' \
+ | sort -f )
+[[ ! $devices ]] && exit
+
+controller=$( bluetoothctl show | head -1 | cut -d' ' -f2 )
+readarray -t macs <<< $( ls -1 /var/lib/bluetooth/$controller | egrep -v 'cache|settings' )
+if [[ $macs ]]; then
+ for mac in "${macs[@]}"; do
+ devices=$( grep -v $mac <<< "$devices" )
+ done
+fi
+readarray -t devices <<< "$devices"
+for dev in "${devices[@]}"; do
+ name=${dev/^*}
+ mac=${dev/*^}
+ data+=',{
+"name" : "'$name'"
+, "mac" : "'$mac'"
+}'
+done
+data2json "$data"
diff --git a/srv/http/bash/settings/networks-scanbt.sh b/srv/http/bash/settings/networks-scanbt.sh
deleted file mode 100644
index 4b38df1c6..000000000
--- a/srv/http/bash/settings/networks-scanbt.sh
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/bin/bash
-
-. /srv/http/bash/common.sh
-
-listBt() {
- bluetoothctl $1 \
- | grep -v ' ..-..-..-..-..-..$' \
- | sed -E 's/Device (..:..:..:..:..:..) (.*)/\2^\1/' \
- | sort -f
-}
-
-bluetoothctl --timeout=10 scan on &> /dev/null
-
-devices=$( listBt devices )
-[[ ! $devices ]] && exit
-
-paired=$( listBt paired-devices )
-[[ $paired ]] && devices=$( diff <( echo "$paired" ) <( echo "$devices" ) | grep '^>' | cut -c 3- )
-readarray -t devices <<< "$devices"
-for dev in "${devices[@]}"; do
- name=${dev/^*}
- mac=${dev/*^}
- data+=',{
- "name" : "'$name'"
-, "mac" : "'$mac'"
-}'
-done
-
-data2json "$data"
diff --git a/srv/http/bash/settings/networks-scanwlan.sh b/srv/http/bash/settings/networks-scanwlan.sh
deleted file mode 100644
index ed8b2cbfb..000000000
--- a/srv/http/bash/settings/networks-scanwlan.sh
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/bin/bash
-
-. /srv/http/bash/common.sh
-
-wlandev=$( cat $dirshm/wlan )
-ip link set $wlandev up
-
-# pre-scan hidden ssid to force responding to scan
-readarray -t hiddenprofiles <<< $( grep -rl --exclude-dir=examples ^Hidden=yes /etc/netctl )
-if [[ $hiddenprofiles ]]; then
- for file in "${hiddenprofiles[@]}"; do
- iwlist $wlandev scan essid "$( basename "$file" )" &> /dev/null
- done
-fi
-
-# ESSID:"NAME"
-# Encryption key:on
-# Quality=37/70 Signal level=-73 dBm --- Quality=0/100 Signal level=25/100
-# IE: IEEE 802.11i/WPA2 Version 1
-# IE: WPA Version 1
-scan=$( iwlist $wlandev scan \
- | sed -E 's/^\s*|\s*$//g' \
- | egrep '^Cell|^ESSID|^Encryption|^IE.*WPA|^Quality' \
- | sed -E 's/^Cell.*/},{/
- s/^ESSID:/,"ssid":/
- s/\\x00//g
- s/^Encryption key:(.*)/,"encrypt":"\1"/
- s/^IE.*WPA.*/,"wpa":true/
- s/^Quality.*level.(.*)/,"signal":"\1"/' \
- | sed '/},{/ {n;s/^,/ /}' )
-# save profile
-readarray -t ssids <<< $( grep '"ssid":' <<< "$scan" \
- | sed -E 's/^.*:"(.*)"/\1/' \
- | awk NF )
-for ssid in "${ssids[@]}"; do
- [[ -e "/etc/netctl/$ssid" ]] && scan=$( sed '/"ssid":"'$ssid'"/ a\,"profile":true' <<< "$scan" )
-done
-# connected ssid
-connectedssid=$( iwgetid $wlandev -r )
-scan=$( sed '/"ssid":"'$connectedssid'"/ a\,"connected":true' <<< "$scan" )
-
-# },{... > [ {...} ]
-echo "[ ${scan:2} } ]" | jq
diff --git a/srv/http/bash/status-push.sh b/srv/http/bash/status-push.sh
index 39dd6d755..81a067ce8 100644
--- a/srv/http/bash/status-push.sh
+++ b/srv/http/bash/status-push.sh
@@ -14,14 +14,14 @@ else
if [[ -e $dirshm/status ]]; then
statusprev=$( cat $dirshm/status )
compare='^Artist|^Title|^Album'
- [[ "$( grep "$compare" <<< "$statusnew" | sort )" != "$( grep "$compare" <<< "$statusprev" | sort )" ]] && trackchanged=1
+ [[ "$( egrep "$compare" <<< "$statusnew" | sort )" != "$( egrep "$compare" <<< "$statusprev" | sort )" ]] && trackchanged=1
. <( echo "$statusnew" )
if [[ $webradio == true ]]; then
[[ ! $trackchanged && $state == play ]] && exit
else
compare='^state|^elapsed'
- [[ "$( egrep "$compare" <<< "$statusnew" | sort )" != "$( grep "$compare" <<< "$statusprev" | sort )" ]] && statuschanged=1
+ [[ "$( egrep "$compare" <<< "$statusnew" | sort )" != "$( egrep "$compare" <<< "$statusprev" | sort )" ]] && statuschanged=1
[[ ! $trackchanged && ! $statuschanged ]] && exit
fi
diff --git a/srv/http/cmd.php b/srv/http/cmd.php
index 45c069102..bcb2bdab4 100644
--- a/srv/http/cmd.php
+++ b/srv/http/cmd.php
@@ -4,9 +4,6 @@
$dirdata = '/srv/http/data/';
$dirbookmarks = $dirdata.'bookmarks/';
$dirsystem = $dirdata.'system/';
-$coverartsize = '200x200';
-$thumbsize = '80x80';
-$unsharp = '0x.5';
switch( $_POST[ 'cmd' ] ) {
@@ -40,53 +37,6 @@
echo json_encode( $output );
break;
-case 'bookmark':
- $name = $_POST[ 'name' ];
- if ( file_exists( $dirbookmarks.$name ) ) exit( '-1' );
-
- $path = $_POST[ 'path' ];
- $coverart = $_POST[ 'coverart' ] ?? '';
- $fileorder = $dirsystem.'order';
- $order = json_decode( file_get_contents( $fileorder ) );
- $order[] = $path;
- file_put_contents( $fileorder, json_encode( $order, JSON_PRETTY_PRINT ) );
- if ( $coverart ) {
- $content = $path."\n".$coverart;
- $icon = '';
- } else {
- $content = $path;
- $icon =''.$name.'
';
- }
- file_put_contents( $dirbookmarks.str_replace( '/', '|', $name ), $content );
- $data = [
- 'path' => $path
- , 'html' => '
- '
- , 'order' => $order
- ];
- pushstream( 'bookmark', $data );
- break;
-case 'bookmarkremove':
- $path = $_POST[ 'path' ];
- $fileorder = $dirsystem.'order';
- $order = json_decode( file_get_contents( $fileorder ) );
- $name = str_replace( '/', '|', $_POST[ 'delete' ] );
- exec( 'rm "'.$dirbookmarks.escape( $name ).'"' );
- $index = array_search( $path, $order );
- array_splice( $order, $index, 1 ); // remove + reindex for json_encode
- file_put_contents( $fileorder, json_encode( $order, JSON_PRETTY_PRINT ) );
- pushstream( 'bookmark', [ 'type' => 'delete', 'path' => $path, 'order' => $order ] );
- break;
-case 'bookmarkrename':
- $name = $_POST[ 'name' ];
- $rename = $_POST[ 'rename' ];
- rename( $dirbookmarks.str_replace( '/', '|', $name ), $dirbookmarks.str_replace( '/', '|', $rename ) );
- pushstream( 'bookmark', [ 'type' => 'rename', 'path' => $_POST[ 'path' ], 'name' => $rename ] );
- break;
case 'datarestore':
if ( $_FILES[ 'file' ][ 'error' ] != UPLOAD_ERR_OK ) exit( '-1' );
@@ -106,16 +56,9 @@
} else { // gif passed as file
$tmpfile = $_FILES[ 'file' ][ 'tmp_name' ];
}
- cmdsh( [ $base64 ? 'thumbjpg' : 'thumbgif', $type, $tmpfile, $imagefile, $covername ] );
- if ( $type === 'bookmark' ) {
- $coverfile = preg_replace( '#^/srv/http#', '', $imagefile ); // radio - /srv/http/data/...
- $path = exec( 'head -1 "'.$dirbookmarks.$covername.'"' );
- if ( file_exists( $imagefile ) ) $path.= "\n".$coverfile;
- file_put_contents( $dirbookmarks.$covername, $path );
- }
- $coverfile = $filenoext.time().$ext;
- if ( substr( $coverfile, 0, 4 ) === '/mnt' ) $coverfile = rawurlencode( $coverfile );
- pushstream( 'coverart', json_decode( '{"url":"'.$coverfile.'","type":"'.$type.'"}' ) );
+ $sh = [ $base64 ? 'thumbjpg' : 'thumbgif', $type, $tmpfile, $imagefile, $covername ];
+ $script = '/usr/bin/sudo /srv/http/bash/cmd.sh "'.escape( implode( "\n", $sh ) ).'"';
+ shell_exec( $script );
break;
case 'login':
$passwordfile = $dirsystem.'loginset';
@@ -146,18 +89,6 @@
break;
}
-function cmdsh( $sh ) {
- $script = '/usr/bin/sudo /srv/http/bash/cmd.sh "';
- $script.= escape( implode( "\n", $sh ) ).'"';
- return shell_exec( $script );
-}
function escape( $string ) {
return preg_replace( '/(["`])/', '\\\\\1', $string );
}
-function pushstream( $channel, $data ) {
- $ch = curl_init( 'http://localhost/pub?id='.$channel );
- curl_setopt( $ch, CURLOPT_HTTPHEADER, array( 'Content-Type:application/json' ) );
- curl_setopt( $ch, CURLOPT_POSTFIELDS, json_encode( $data, JSON_NUMERIC_CHECK ) );
- curl_exec( $ch );
- curl_close( $ch );
-}
diff --git a/srv/http/index-body.php b/srv/http/index-body.php
index de91b9d03..5a95de718 100644
--- a/srv/http/index-body.php
+++ b/srv/http/index-body.php
@@ -69,7 +69,7 @@
$files = array_slice( scandir( $dir ), 2 ); // remove ., ..
if ( count( $files ) ) {
foreach( $files as $name ) {
- $data = file( $dir.'/'.$name, FILE_IGNORE_NEW_LINES );
+ $data = file( $dir.'/'.str_replace( '|', '/', $name ), FILE_IGNORE_NEW_LINES );
$bkpath = $data[ 0 ];
$coverart = $data[ 1 ] ?? '';
if ( $coverart ) {
diff --git a/srv/http/index.php b/srv/http/index.php
index ba6bc8c6f..aa1cd7cb4 100644
--- a/srv/http/index.php
+++ b/srv/http/index.php
@@ -50,10 +50,10 @@
-
+
-
+
diff --git a/srv/http/mpdlibrary.php b/srv/http/mpdlibrary.php
index f25ed6263..aa86d10ba 100644
--- a/srv/http/mpdlibrary.php
+++ b/srv/http/mpdlibrary.php
@@ -137,8 +137,7 @@
case 'radio':
$dir = '/srv/http/data/'.$gmode.'/';
$dirimg = '/data/'.$gmode.'/img/';
- $path = $string !== '' ? $string.'/' : '';
- $dir.= $path;
+ $dir.= $string;
$subdirs = [];
$files = [];
$indexes = [];
@@ -151,14 +150,14 @@
exec( 'ls -1 "'.$dir.'" | egrep -v "^img|\.jpg$|\.gif$"'
, $lists );
foreach( $lists as $list ) {
- if ( is_dir( $dir.$list ) ) {
+ if ( is_dir( $dir.'/'.$list ) ) {
$subdirs[] = $list;
} else {
$files[] = $list;
}
}
}
- htmlRadio( $subdirs, $files, $dir, $dirimg, $path );
+ htmlRadio( $subdirs, $files, $dir, $dirimg );
break;
case 'search':
exec( 'mpc search -f "'.$format.'" any "'.$string.'" | awk NF'
@@ -361,7 +360,7 @@ function htmlList( $lists ) { // non-file 'list' command
'.$indexbar[ 1 ].'
';
echo $html;
}
-function htmlRadio( $subdirs, $files, $dir, $dirimg, $path ) {
+function htmlRadio( $subdirs, $files, $dir, $dirimg ) {
global $mode;
global $gmode;
global $html;
@@ -375,6 +374,7 @@ function htmlRadio( $subdirs, $files, $dir, $dirimg, $path ) {
usort( $array, function( $a, $b ) {
return strnatcasecmp( $a->sort, $b->sort );
} );
+ $path = substr( $dir, 9 );
foreach( $array as $each ) {
if ( count( $files ) ) {
$html.= '';
@@ -383,9 +383,11 @@ function htmlRadio( $subdirs, $files, $dir, $dirimg, $path ) {
$indexes[] = $index;
$html.= '';
}
- $html.= '
- '.$path.$each->subdir.'
- '.$each->subdir.'
+ $subdir = $each->subdir;
+ $thumbsrc = rawurlencode( $path.$subdir.'/thumb.'.time().'.jpg' );
+ $html.= '
+ '.$subdir.'
+ '.$subdir.'
';
}
}
@@ -416,7 +418,7 @@ function htmlRadio( $subdirs, $files, $dir, $dirimg, $path ) {
$name = $searchmode ? preg_replace( "/($string)/i", '$1', $liname ) : $liname;
$html.= '
- '.$path.$url.'
+ '.$url.'
'.$liname.'
'.$name.'
'.$url.'