pifi 0.4.6 → 0.4.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b6e7b2bd5b4e59bc9c8a6112919750ad53d8d200ed948aa64fd5030912f992bc
4
- data.tar.gz: ffc1c53416c9cdce5cb30404064ca20873924dcf775e539d5cbadc6d00ebb227
3
+ metadata.gz: 781b3226270fe494e3d7cdd3be0510c7e2b6b056ed34b9b02d3ba3c5630691d9
4
+ data.tar.gz: 0aafef0c435099adf107b51003360151f61d5799af058ac5a3d65e7fd1ee9f4a
5
5
  SHA512:
6
- metadata.gz: 2cbce35b963cbcdd9f2688ba4a1548a15ef658c1960f0c4b6b3525996358cf44be7a4df5e331f229feedfec88f076b1a088c9d34300e6cea83944aa88c493e41
7
- data.tar.gz: 886806be70c2a95df6fa521477e5c9cb0ae64cfdb15a53699a0c071ea004629835f215cb5611a471d8162ca4fd15bd188d6c2ffb1653c967ad3223be38b42df2
6
+ metadata.gz: 72c2704a3713c028e7d4275b5f3d8f0fd5ab869a00301f4ab9e14d452bf89507d7f6cae846bdfa2c5d0deb6a1afbe8b07c1f0171f1010a215cc54da5364630a5
7
+ data.tar.gz: 013b3fa365b6f6be41184c6dd2455ddc02bfd00e30c503053cf8cbcff4de3d48671af3de04e698a91279dadd3593e53e7b03f85962dea02c95050096f287f54a
data/README.md CHANGED
@@ -99,14 +99,14 @@ It's now completely optional to have a configuration file for PiFi. You only nee
99
99
 
100
100
  The path is `/etc/pifi/config.json` and these are the options:
101
101
 
102
- | Key | Default | Description |
103
- | ------------------- | ------------------------ | ----------------------------------------------------------------------------------------------------------------- |
102
+ | Key | Default | Description |
103
+ | ------------------- | -------------------------- | ----------------------------------------------------------------------------------------------------------------- |
104
104
  | `mpd_host` | `"127.0.0.1"` | MPD host. |
105
105
  | `mpd_port` | `6600` | MPD port. |
106
106
  | `mpd_password` | `""` (none) | MPD password. |
107
107
  | `streams_path` | `"/etc/pifi/streams.json"` | Path to the JSON file containing the streams. |
108
108
  | `streams_path_priv` | `""` (none) | Path to JSON file containing additional streams. These will be shown only to the devices listed on `special_ips`. |
109
- | `special_ips` | `[]` (none) | The IPs of the devices to show additional streams. Example: `["10.0.0.1", "10.0.0.2"]` |
109
+ | `special_ips` | `[]` (none) | The IPs of the devices to show additional streams. Example: `["10.0.0.1", "10.0.0.2"]` |
110
110
  | `serve_static` | `true` | If we should serve static resources. Set it to `false` if your web server is already doing it. |
111
111
 
112
112
  If you want to change any of these options, download the sample file and edit it to your needs:
@@ -147,6 +147,7 @@ The default language for PiFi is English, so you should use it as a reference.
147
147
 
148
148
  ## Credits
149
149
 
150
+ - de-de: [cedege](https://github.com/cedege)
150
151
  - fr-fr: [Francis Chavanon](https://github.com/rimeno)
151
152
  - pl-pl: [Struart88](https://github.com/Struart88)
152
153
  - nl-nl: [Heimen Stoffels](https://github.com/Vistaus)
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "files": {
3
3
  "main.css": "/static/css/main.221e80d3.chunk.css",
4
- "main.js": "/static/js/main.8e5c89f3.chunk.js",
5
- "main.js.map": "/static/js/main.8e5c89f3.chunk.js.map",
4
+ "main.js": "/static/js/main.4bed24b2.chunk.js",
5
+ "main.js.map": "/static/js/main.4bed24b2.chunk.js.map",
6
6
  "runtime-main.js": "/static/js/runtime-main.5aae5a31.js",
7
7
  "runtime-main.js.map": "/static/js/runtime-main.5aae5a31.js.map",
8
8
  "static/css/2.d34346ea.chunk.css": "/static/css/2.d34346ea.chunk.css",
9
9
  "static/js/2.6c0ded8a.chunk.js": "/static/js/2.6c0ded8a.chunk.js",
10
10
  "static/js/2.6c0ded8a.chunk.js.map": "/static/js/2.6c0ded8a.chunk.js.map",
11
11
  "index.html": "/index.html",
12
- "precache-manifest.2c90c6fbdaaa7d18bbe102974b424a55.js": "/precache-manifest.2c90c6fbdaaa7d18bbe102974b424a55.js",
12
+ "precache-manifest.9dcd6ace3f74e77109acd0095f020876.js": "/precache-manifest.9dcd6ace3f74e77109acd0095f020876.js",
13
13
  "service-worker.js": "/service-worker.js",
14
14
  "static/css/2.d34346ea.chunk.css.map": "/static/css/2.d34346ea.chunk.css.map",
15
15
  "static/css/main.221e80d3.chunk.css.map": "/static/css/main.221e80d3.chunk.css.map",
@@ -22,6 +22,6 @@
22
22
  "static/css/2.d34346ea.chunk.css",
23
23
  "static/js/2.6c0ded8a.chunk.js",
24
24
  "static/css/main.221e80d3.chunk.css",
25
- "static/js/main.8e5c89f3.chunk.js"
25
+ "static/js/main.4bed24b2.chunk.js"
26
26
  ]
27
27
  }
@@ -1 +1 @@
1
- <!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"><meta name="description" content="MPD web client to listen to radio"/><link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png"><link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png"><link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png"><link rel="manifest" href="/manifest.json"><link rel="mask-icon" href="/safari-pinned-tab.svg" color="#5bbad5"><meta name="apple-mobile-web-app-title" content="PiFi Radio"><meta name="application-name" content="PiFi Radio"><meta name="msapplication-TileColor" content="#2b5797"><meta name="theme-color" content="#375a7f"><title>PiFi Radio</title><link rel="preload" href="https://stackpath.bootstrapcdn.com/bootswatch/4.4.1/darkly/bootstrap.min.css" as="style"><link href="https://stackpath.bootstrapcdn.com/bootswatch/4.4.1/darkly/bootstrap.min.css" rel="stylesheet" title="theme"><link href="/static/css/2.d34346ea.chunk.css" rel="stylesheet"><link href="/static/css/main.221e80d3.chunk.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script>var isIE=window.document.documentMode,unsupportedMsg='<img src="/assets/logo80.png" class="mx-auto d-block my-5">';if(unsupportedMsg+='<h5 class="text-center my-5">This browser is not supported</h5>',isIE){var root=document.getElementById("root");root.innerHTML=unsupportedMsg,root.setAttribute("id","")}</script><script>!function(e){function r(r){for(var n,f,i=r[0],l=r[1],p=r[2],c=0,s=[];c<i.length;c++)f=i[c],Object.prototype.hasOwnProperty.call(o,f)&&o[f]&&s.push(o[f][0]),o[f]=0;for(n in l)Object.prototype.hasOwnProperty.call(l,n)&&(e[n]=l[n]);for(a&&a(r);s.length;)s.shift()();return u.push.apply(u,p||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,i=1;i<t.length;i++){var l=t[i];0!==o[l]&&(n=!1)}n&&(u.splice(r--,1),e=f(f.s=t[0]))}return e}var n={},o={1:0},u=[];function f(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,f),t.l=!0,t.exports}f.m=e,f.c=n,f.d=function(e,r,t){f.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},f.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},f.t=function(e,r){if(1&r&&(e=f(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(f.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)f.d(t,n,function(r){return e[r]}.bind(null,n));return t},f.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return f.d(r,"a",r),r},f.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},f.p="/";var i=this.webpackJsonppifi_frontend=this.webpackJsonppifi_frontend||[],l=i.push.bind(i);i.push=r,i=i.slice();for(var p=0;p<i.length;p++)r(i[p]);var a=l;t()}([])</script><script src="/static/js/2.6c0ded8a.chunk.js"></script><script src="/static/js/main.8e5c89f3.chunk.js"></script></body></html>
1
+ <!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"><meta name="description" content="MPD web client to listen to radio"/><link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png"><link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png"><link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png"><link rel="manifest" href="/manifest.json"><link rel="mask-icon" href="/safari-pinned-tab.svg" color="#5bbad5"><meta name="apple-mobile-web-app-title" content="PiFi Radio"><meta name="application-name" content="PiFi Radio"><meta name="msapplication-TileColor" content="#2b5797"><meta name="theme-color" content="#375a7f"><title>PiFi Radio</title><link rel="preload" href="https://stackpath.bootstrapcdn.com/bootswatch/4.4.1/darkly/bootstrap.min.css" as="style"><link href="https://stackpath.bootstrapcdn.com/bootswatch/4.4.1/darkly/bootstrap.min.css" rel="stylesheet" title="theme"><link href="/static/css/2.d34346ea.chunk.css" rel="stylesheet"><link href="/static/css/main.221e80d3.chunk.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script>var isIE=window.document.documentMode,unsupportedMsg='<img src="/assets/logo80.png" class="mx-auto d-block my-5">';if(unsupportedMsg+='<h5 class="text-center my-5">This browser is not supported</h5>',isIE){var root=document.getElementById("root");root.innerHTML=unsupportedMsg,root.setAttribute("id","")}</script><script>!function(e){function r(r){for(var n,f,i=r[0],l=r[1],p=r[2],c=0,s=[];c<i.length;c++)f=i[c],Object.prototype.hasOwnProperty.call(o,f)&&o[f]&&s.push(o[f][0]),o[f]=0;for(n in l)Object.prototype.hasOwnProperty.call(l,n)&&(e[n]=l[n]);for(a&&a(r);s.length;)s.shift()();return u.push.apply(u,p||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,i=1;i<t.length;i++){var l=t[i];0!==o[l]&&(n=!1)}n&&(u.splice(r--,1),e=f(f.s=t[0]))}return e}var n={},o={1:0},u=[];function f(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,f),t.l=!0,t.exports}f.m=e,f.c=n,f.d=function(e,r,t){f.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},f.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},f.t=function(e,r){if(1&r&&(e=f(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(f.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)f.d(t,n,function(r){return e[r]}.bind(null,n));return t},f.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return f.d(r,"a",r),r},f.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},f.p="/";var i=this.webpackJsonppifi_frontend=this.webpackJsonppifi_frontend||[],l=i.push.bind(i);i.push=r,i=i.slice();for(var p=0;p<i.length;p++)r(i[p]);var a=l;t()}([])</script><script src="/static/js/2.6c0ded8a.chunk.js"></script><script src="/static/js/main.4bed24b2.chunk.js"></script></body></html>
@@ -0,0 +1,28 @@
1
+ {
2
+ "about": "Über",
3
+ "cancel": "Abbruch",
4
+ "close": "Schließen",
5
+ "coffee": "Wenn Dir PiFi Radio gefällt, unterstütze das Projekt und gib dem Entwickler einen Kaffee aus.",
6
+ "disconnectedMPD": "Keine Verbindung zu MPD",
7
+ "environment": "Environment",
8
+ "errorForbidden": "Zugriff verweigert. Prüfe MPD Passwort und Berechtigungen.",
9
+ "errorNetwork": "Keine Verbindung zum PiFi Server",
10
+ "errorNotFound": "Der Stream wurde nicht gefunden.",
11
+ "errorUnexpected": "Ein unerwarteter Fehler ist aufgetreten.",
12
+ "goToDocs": "Gehe zur Dokumentation",
13
+ "language": "Sprache",
14
+ "mpdHost": "MPD Host",
15
+ "mpdPort": "MPD Port",
16
+ "noStreams": "Kein Sender verfügbar.",
17
+ "ok": "Ok",
18
+ "playing": "Es läuft",
19
+ "playURL": "Öffne URL",
20
+ "search": "Suche...",
21
+ "settings": "Einstellungen",
22
+ "stopped": "Beendet",
23
+ "theme": "Theme",
24
+ "tryingURL": "Versuche Sender zu verbinden...",
25
+ "tunning": "Senderwechsel...",
26
+ "version": "Version",
27
+ "volume": "Lautstärke"
28
+ }
@@ -1,6 +1,6 @@
1
1
  self.__precacheManifest = (self.__precacheManifest || []).concat([
2
2
  {
3
- "revision": "1b00b4f5ebb2adb60a0dacf8f59d8ae0",
3
+ "revision": "012da186bda9c64ff6c71013f3cf0ec1",
4
4
  "url": "/index.html"
5
5
  },
6
6
  {
@@ -8,7 +8,7 @@ self.__precacheManifest = (self.__precacheManifest || []).concat([
8
8
  "url": "/static/css/2.d34346ea.chunk.css"
9
9
  },
10
10
  {
11
- "revision": "03fa90d8aef5be8a204d",
11
+ "revision": "294499573a38483fb7c8",
12
12
  "url": "/static/css/main.221e80d3.chunk.css"
13
13
  },
14
14
  {
@@ -20,8 +20,8 @@ self.__precacheManifest = (self.__precacheManifest || []).concat([
20
20
  "url": "/static/js/2.6c0ded8a.chunk.js.LICENSE.txt"
21
21
  },
22
22
  {
23
- "revision": "03fa90d8aef5be8a204d",
24
- "url": "/static/js/main.8e5c89f3.chunk.js"
23
+ "revision": "294499573a38483fb7c8",
24
+ "url": "/static/js/main.4bed24b2.chunk.js"
25
25
  },
26
26
  {
27
27
  "revision": "af7ed8886109d8666769",
@@ -14,7 +14,7 @@
14
14
  importScripts("https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js");
15
15
 
16
16
  importScripts(
17
- "/precache-manifest.2c90c6fbdaaa7d18bbe102974b424a55.js"
17
+ "/precache-manifest.9dcd6ace3f74e77109acd0095f020876.js"
18
18
  );
19
19
 
20
20
  self.addEventListener('message', (event) => {
@@ -0,0 +1,2 @@
1
+ (this.webpackJsonppifi_frontend=this.webpackJsonppifi_frontend||[]).push([[0],{13:function(e){e.exports=JSON.parse('{"b":["en","de-DE","fr-FR","nl-NL","pl-PL","pt-BR"],"c":1000,"a":2500,"d":3000}')},30:function(e,t,a){e.exports=a.p+"static/media/logo.91554ce9.svg"},50:function(e,t,a){e.exports=a(94)},56:function(e,t,a){},79:function(e,t,a){},80:function(e,t,a){},83:function(e,t,a){},84:function(e,t,a){},85:function(e,t,a){},86:function(e,t,a){},87:function(e,t,a){},89:function(e,t,a){},94:function(e,t,a){"use strict";a.r(t);var n=a(0),r=a.n(n),l=a(12),o=a.n(l),c=a(2),s=a.n(c),i=a(8),u=a(9),m=a(10),d=a(19),p=a(20),b=a(3),f=a(98),v=a(26),h=(a(56),a(30)),g=a.n(h),y=function(){var e=Object(v.a)().t;return r.a.createElement("nav",{className:"navbar navbar-expand-sm navbar-dark bg-primary"},r.a.createElement("div",{className:"container"},r.a.createElement("a",{className:"navbar-brand",href:"/"},r.a.createElement("img",{src:g.a,width:"30",height:"30",className:"d-inline-block align-text-bottom mr-2",alt:""}),"PiFi Radio"),r.a.createElement("button",{className:"navbar-toggler",type:"button","data-toggle":"collapse","data-target":"#navbarNavAltMarkup","aria-controls":"navbarNavAltMarkup","aria-expanded":"false","aria-label":"Toggle navigation"},r.a.createElement("span",{className:"navbar-toggler-icon"})),r.a.createElement("div",{className:"collapse navbar-collapse",id:"navbarNavAltMarkup"},r.a.createElement("div",{className:"navbar-nav pt-1 ml-2"},r.a.createElement("button",{className:"btn btn-link nav-link","data-toggle":"modal","data-target":"#url-dialog"},e("playURL")),r.a.createElement("button",{className:"btn btn-link nav-link","data-toggle":"modal","data-target":"#settings"},e("settings")),r.a.createElement("button",{className:"btn btn-link nav-link","data-toggle":"modal","data-target":"#about"},e("about"))))))},E=a(15),k=a(48),N=a(44),S=a.n(N),w=function(e){var t=e.id,a=e.title,n=e.footer,l=e.children,o=Object(v.a)().t,c=r.a.createElement("button",{className:"btn btn-secondary","data-dismiss":"modal"},o("close"));return r.a.createElement("div",{className:"modal fade",id:t,tabIndex:"-1",role:"dialog","aria-labelledby":"staticBackdropLabel","aria-hidden":"true"},r.a.createElement("div",{className:"modal-dialog",role:"document"},r.a.createElement("div",{className:"modal-content"},r.a.createElement("div",{className:"modal-header"},r.a.createElement("h5",{className:"modal-title",id:"staticBackdropLabel"},a),r.a.createElement("button",{type:"button",className:"close","data-dismiss":"modal","aria-label":"Close"},r.a.createElement("span",{"aria-hidden":"true"},"\xd7"))),r.a.createElement("div",{className:"modal-body"},l),r.a.createElement("div",{className:"modal-footer"},n||c))))},O=a(49),j=function(e){var t=e.id,a=e.label,n=e.row,l=e.data,o=Object(O.a)(e,["id","label","row","data"]);return r.a.createElement("div",{className:n?"form-group row":"form-group"},r.a.createElement("label",{htmlFor:t,className:"col-sm-2 col-form-label"},a),r.a.createElement("div",{className:"col-sm-10"},r.a.createElement("select",Object.assign({id:t,className:"form-control"},o),l.map((function(e){return r.a.createElement("option",{key:e.id||e,value:e.id||e},e.name||e)})))))},C=[{id:"darkly",name:"Darkly",themeColor:"#375a7f"},{id:"lux",name:"Lux",themeColor:"#1a1a1a"}];function _(){var e=x(),t=function(e){return"https://stackpath.bootstrapcdn.com/bootswatch/4.4.1/".concat(e,"/bootstrap.min.css")}(e),a=C.find((function(t){return t.id===e})).themeColor;document.querySelector('link[title="theme"]').setAttribute("href",t),document.querySelector('meta[name="theme-color"]').setAttribute("content",a)}function x(){var e=localStorage.getItem("theme");return""===e?"darkly":0===C.filter((function(t){return t.id===e})).length?(localStorage.removeItem("theme"),"darkly"):e}var T={availableThemes:C,getCurrentId:x,change:function(e){localStorage.setItem("theme",e),_()},apply:_},L=a(13),P=function(){var e=Object(v.a)(),t=e.t,a=e.i18n,l=Object(n.useState)(""),o=Object(E.a)(l,2),c=o[0],s=o[1],i=L.b.sort().map((function(e){var t=e.slice(0,2);return{id:e,name:"".concat(S()(e)," ").concat(k.a.getNativeName(t))}}));return Object(n.useEffect)((function(){s(T.getCurrentId())}),[]),r.a.createElement(w,{id:"settings",title:t("settings")},r.a.createElement(j,{id:"theme-select",label:t("theme"),data:T.availableThemes,row:!0,value:c,onChange:function(e){return function(e){var t=e.target.value;T.change(t),s(t)}(e)}}),r.a.createElement(j,{id:"language-select",label:t("language"),data:i,row:!0,value:a.language,onChange:function(e){return a.changeLanguage(e.target.value)}}))},R=a(24),A=a.n(R),B=a(97);A.a.defaults.baseURL="/api",A.a.interceptors.response.use(null,(function(e){var t=e.response&&e.response.status>=400&&e.response.status<500;return document.querySelector(".Toastify")&&(t||b.b.error(r.a.createElement(B.a,null,(function(e){return e("errorUnexpected")}))),e.response&&403===e.response.status&&b.b.error(r.a.createElement(B.a,null,(function(e){return e("errorForbidden")})))),Promise.reject(e)}));var D={get:A.a.get,post:A.a.post};function I(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null,a=new FormData;return a.set("method",e),t&&a.set("params",t),a}function F(){return D.post("/player",I("play"))}function U(){return D.post("/player",I("stop"))}function M(e){return D.post("/player",I("change_vol",e))}function q(e){return D.post("/player",I("play_radios",e))}function W(e){return D.post("/player",I("play_urls",e))}var Y=function(){var e=Object(n.useState)(""),t=Object(E.a)(e,2),a=t[0],l=t[1],o=Object(v.a)().t,c=function(){""!==a&&(u(a),l(""))},u=function(){var e=Object(i.a)(s.a.mark((function e(t){var a,n;return s.a.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return a={type:b.b.TYPE.ERROR,render:o("errorNotFound")},n=Object(b.b)(o("tryingURL")),e.prev=2,e.next=5,W(t);case 5:e.next=10;break;case 7:e.prev=7,e.t0=e.catch(2),e.t0.response&&400===e.t0.response.status&&b.b.update(n,a);case 10:case"end":return e.stop()}}),e,null,[[2,7]])})));return function(t){return e.apply(this,arguments)}}();return r.a.createElement(w,{id:"url-dialog",title:o("playURL"),footer:r.a.createElement(r.a.Fragment,null,r.a.createElement("button",{className:"btn btn-primary","data-dismiss":"modal",onClick:c},o("ok")),r.a.createElement("button",{className:"btn btn-secondary",onClick:function(){return l("")},"data-dismiss":"modal"},o("cancel")))},r.a.createElement("input",{className:"form-control mb-4",type:"text",placeholder:"URL",value:a,onChange:function(e){var t=e.target;l(t.value)},onKeyDown:function(e){"Enter"===e.key&&c()}}))};function K(){return D.get("/config")}a(79);var V=function(){return r.a.createElement("div",{className:"loader"},r.a.createElement("div",{className:"spinner-border",role:"status"},r.a.createElement("span",{className:"sr-only"},"Loading...")))},H=function(){var e=Object(v.a)().t,t=Object(n.useState)({}),a=Object(E.a)(t,2),l=a[0],o=a[1],c=Object(n.useState)(!0),u=Object(E.a)(c,2),m=u[0],d=u[1];Object(n.useEffect)((function(){function e(){return(e=Object(i.a)(s.a.mark((function e(){var t,a;return s.a.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,K();case 2:t=e.sent,a=t.data,o(a),d(!1);case 6:case"end":return e.stop()}}),e)})))).apply(this,arguments)}!function(){e.apply(this,arguments)}()}),[]);var p=[{label:e("mpdHost"),value:l.mpd_host},{label:e("mpdPort"),value:l.mpd_port},{label:e("environment"),value:l.environment},{label:e("version"),value:l.version}],b=r.a.createElement("div",{className:"copyright small mt-5"},r.a.createElement("p",null,r.a.createElement("a",{href:"https://rafaelc.org/pifi",target:"_blank",rel:"noopener noreferrer",style:{color:"inherit"}},e("goToDocs"))),r.a.createElement("p",null,"Copyright \xa9 2017-2020\xa0",r.a.createElement("a",{href:"https://rafaelc.org/",target:"_blank",rel:"noopener noreferrer",style:{color:"inherit"}},"Rafael Cavalcanti"))),f=r.a.createElement("div",{className:"coffee mt-5"},r.a.createElement("p",null,e("coffee")),r.a.createElement("a",{href:"https://www.buymeacoffee.com/rafaelc",target:"_blank",rel:"noopener noreferrer"},r.a.createElement("img",{src:"https://cdn.buymeacoffee.com/buttons/default-blue.png",alt:"Buy Me A Coffee",style:{height:51,width:217}})));return r.a.createElement(w,{id:"about",title:e("about")},m?r.a.createElement(V,null):r.a.createElement("table",{className:"table"},r.a.createElement("tbody",null,p.map((function(e){return r.a.createElement("tr",{key:e.label},r.a.createElement("th",{scope:"row"},e.label),r.a.createElement("td",null,e.value))})))),f,b)},J=(a(80),function(){return window.innerWidth-document.documentElement.clientWidth}),G=function(e){var t=e.title,a=e.body,n=t,l=document.body.classList.contains("body--backdrop");n&&!l?(document.body.style.paddingRight=J()+"px",document.body.classList.add("body--backdrop")):!n&&l&&(document.body.style.paddingRight=0,document.body.classList.remove("body--backdrop"));var o="backdrop p-2 text-white"+(n?" backdrop--visible":"");return r.a.createElement("div",{className:o},r.a.createElement("h3",{className:"text-white"},t),r.a.createElement("h5",{className:"text-white"},a))},$=function(e){var t=e.playerStatus,a=t.playing,n=t.title,l=Object(v.a)().t;return r.a.createElement("div",{className:"text-center w-100"},r.a.createElement("h5",{className:"small text-uppercase"},l(a?"playing":"stopped")),r.a.createElement("h3",{className:"ellipsis"},n))},z=a(14),Q=a(11),X=function(e){return e.playing?r.a.createElement("button",{className:"btn btn-danger",onClick:U,"aria-label":"Stop"},r.a.createElement(z.a,{icon:Q.d})):r.a.createElement("button",{className:"btn btn-dark",onClick:F,"aria-label":"Play"},r.a.createElement(z.a,{icon:Q.c}))},Z=function(e){var t=e.playerStatus,a=Object(v.a)().t,n=null==t.vol,l=function(){var e=Object(i.a)(s.a.mark((function e(t){var n,r,l,o;return s.a.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,M(t);case 2:n=e.sent,r=n.data,"vol",l="".concat(a("volume"),": ").concat(r,"%"),o={toastId:"vol",autoClose:L.d},b.b.isActive("vol")?b.b.update("vol",{render:l}):b.b.info(l,o);case 8:case"end":return e.stop()}}),e)})));return function(t){return e.apply(this,arguments)}}(),o=function(e,t,a){return r.a.createElement("button",{className:"btn btn-dark p-3",disabled:n,onClick:function(){return l(e)},"aria-label":a},r.a.createElement(z.a,{icon:t}))};return r.a.createElement("div",{className:"player-controls btn-group w-100 m-2",onClick:function(e){return e.stopPropagation()}},o("-5",Q.e,"Volume down"),o("+5",Q.f,"Volume up"),r.a.createElement(X,{playing:t.playing}))},ee=(a(83),function(e){var t=e.playerStatus;return r.a.createElement("div",{className:"player"},r.a.createElement($,{playerStatus:t}),r.a.createElement("img",{src:a(30),alt:"Logo",className:"player-logo m-4"}),r.a.createElement(Z,{playerStatus:t}))}),te=function(e){var t=e.value,a=e.onChange,n=Object(v.a)().t;return r.a.createElement("input",{className:"form-control mb-4",type:"text",id:"query",placeholder:n("search"),"aria-label":n("search"),autoComplete:"off",value:t,onChange:function(e){return a(e.target.value)},onFocus:function(){return a("")}})};a(84);var ae=function(e){Object(p.a)(a,e);var t=Object(d.a)(a);function a(){var e;Object(u.a)(this,a);for(var n=arguments.length,r=new Array(n),l=0;l<n;l++)r[l]=arguments[l];return(e=t.call.apply(t,[this].concat(r))).state={streams:{},loading:!0,query:""},e.isPlaying=function(t){return t===e.props.playerStatus.title&&e.props.playerStatus.playing},e.handleItemClick=function(){var t=Object(i.a)(s.a.mark((function t(a){var n,r,l;return s.a.wrap((function(t){for(;;)switch(t.prev=t.next){case 0:if(n=e.props,r=n.t,l=n.onBackdrop,!e.isPlaying(a)){t.next=3;break}return t.abrupt("return");case 3:return l(r("tunning"),a),t.prev=4,t.next=7,q(a);case 7:t.next=12;break;case 9:t.prev=9,t.t0=t.catch(4),t.t0.response&&400===t.t0.response.status&&b.b.error(r("errorNotFound"));case 12:case"end":return t.stop()}}),t,null,[[4,9]])})));return function(e){return t.apply(this,arguments)}}(),e.getItemClasses=function(t){var a="streams__item ellipsis list-group-item ";return e.isPlaying(t)?a+"active":a+"list-group-item-action"},e.handleSearch=function(t){e.setState({query:t})},e}return Object(m.a)(a,[{key:"componentDidMount",value:function(){var e=Object(i.a)(s.a.mark((function e(){var t,a;return s.a.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,D.get("/streams");case 2:t=e.sent,a=t.data,this.setState({streams:a,loading:!1});case 5:case"end":return e.stop()}}),e,this)})));return function(){return e.apply(this,arguments)}}()},{key:"filteredStreams",value:function(){var e=this.state,t=e.streams,a=e.query;if(""===a)return t;var n={};for(var r in t)r.toLowerCase().includes(a.toLowerCase())&&!t[r]&&(n[r]=t[r]);return n}},{key:"renderList",value:function(){var e=this,t=this.filteredStreams();return 0===Object.keys(t).length?r.a.createElement("h4",{className:"p-4"},this.props.t("noStreams")):r.a.createElement("ul",{className:"list-group list-group-flush"},Object.keys(t).map((function(a){return t[a]?r.a.createElement("li",{className:"streams__header ellipsis",key:a},a):r.a.createElement("li",{className:e.getItemClasses(a),key:a,onClick:function(){return e.handleItemClick(a)}},a)})))}},{key:"render",value:function(){return this.state.loading?r.a.createElement(V,null):r.a.createElement("div",{className:"streams"},r.a.createElement(te,{value:this.state.query,onChange:this.handleSearch}),this.renderList())}}]),a}(n.Component),ne=Object(f.a)()(ae),re=(a(85),function(e){var t=e.playerStatus,a=t.title,n=t.playing;return r.a.createElement("div",{className:"mini-player"},r.a.createElement("div",{className:"mini-player__left ellipsis"},a),r.a.createElement("div",{className:"mini-player__right",onClick:function(e){return e.stopPropagation()}},r.a.createElement(X,{playing:n})))}),le=(a(86),function(e){Object(p.a)(a,e);var t=Object(d.a)(a);function a(){var e;Object(u.a)(this,a);for(var n=arguments.length,l=new Array(n),o=0;o<n;o++)l[o]=arguments[o];return(e=t.call.apply(t,[this].concat(l))).state={open:!1},e.toggle=function(){e.setState({open:!e.state.open})},e.handleClick=function(){e.toggle()},e.handleTouchStart=function(t){if(t.touches.length>1)return e.setState({touchStartY:null});e.setState({touchStartY:t.touches[0].clientY})},e.handleTouchMove=function(t){var a=e.state,n=a.open,r=a.touchStartY;if(!(null===r||t.touches.length>1)){var l=t.changedTouches[0].clientY;(l>r&&n||l<r&&!n)&&e.toggle()}},e.renderToggleButton=function(){return r.a.createElement("button",{className:"drawer__toggler btn btn-primary-outline","aria-label":"Toggle player"},r.a.createElement(z.a,{icon:e.state.open?Q.a:Q.b,className:"fa-lg"}))},e}return Object(m.a)(a,[{key:"render",value:function(){var e=this.props.playerStatus,t=this.state.open,a="drawer fixed-bottom bg-secondary shadow-lg p-2";return t?(a+=" drawer--open",document.body.classList.add("body--drawer")):document.body.classList.remove("body--drawer"),r.a.createElement("div",{className:a,onClick:this.handleClick,onTouchStart:this.handleTouchStart,onTouchMove:this.handleTouchMove},this.renderToggleButton(),t?r.a.createElement(ee,{playerStatus:e}):r.a.createElement(re,{playerStatus:e}))}}]),a}(n.Component)),oe=(a(87),function(e){var t=e.playerStatus,a=e.onBackdrop;return r.a.createElement("main",{className:"main"},r.a.createElement(le,{playerStatus:t}),r.a.createElement("div",{className:"main__primary container"},r.a.createElement(ne,{onBackdrop:a,playerStatus:t}),r.a.createElement(ee,{playerStatus:t})))}),ce=(a(88),function(e){Object(p.a)(a,e);var t=Object(d.a)(a);function a(){var e;Object(u.a)(this,a);for(var n=arguments.length,r=new Array(n),l=0;l<n;l++)r[l]=arguments[l];return(e=t.call.apply(t,[this].concat(r))).state={playerStatus:{},loading:!0,networkError:!1,backdrop:{}},e.handleBackdrop=function(t){var a=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";e.setState({backdrop:{title:t,body:a}}),setTimeout((function(){return e.setState({backdrop:{}})}),L.a)},e.setDocumentTitle=function(){var t=e.state,a=t.playerStatus;!t.networkError&&a.playing?document.title="PiFi \ud83d\udd0a "+a.title:document.title="PiFi Radio"},e}return Object(m.a)(a,[{key:"componentDidMount",value:function(){this.updatePlayerStatus()}},{key:"componentDidUpdate",value:function(){this.setDocumentTitle()}},{key:"updatePlayerStatus",value:function(){var e=Object(i.a)(s.a.mark((function e(){var t,a,n=this;return s.a.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.prev=0,e.next=3,D.get("/player");case 3:t=e.sent,a=t.data,this.setState({playerStatus:a,loading:!1,networkError:!1}),e.next=11;break;case 8:e.prev=8,e.t0=e.catch(0),this.setState({loading:!1,networkError:!0});case 11:setTimeout((function(){return n.updatePlayerStatus()}),L.c);case 12:case"end":return e.stop()}}),e,this,[[0,8]])})));return function(){return e.apply(this,arguments)}}()},{key:"render",value:function(){var e=this.state,t=e.loading,a=e.networkError,n=e.backdrop,l=e.playerStatus,o=this.props.t;return a?r.a.createElement(G,{title:o("errorNetwork")}):t?r.a.createElement(V,null):l.con_mpd?r.a.createElement("div",{className:"app"},r.a.createElement(b.a,{pauseOnFocusLoss:!1}),r.a.createElement(G,{title:n.title,body:n.body}),r.a.createElement(y,null),r.a.createElement(oe,{onBackdrop:this.handleBackdrop,playerStatus:l}),r.a.createElement(Y,null),r.a.createElement(P,null),r.a.createElement(H,null)):r.a.createElement(G,{title:o("disconnectedMPD")})}}]),a}(n.Component)),se=Object(f.a)()(ce);Boolean("localhost"===window.location.hostname||"[::1]"===window.location.hostname||window.location.hostname.match(/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/));var ie=a(29),ue=a(21),me=a(47),de=a(46);ie.a.use(me.a).use(de.a).use(ue.f).init({fallbackLng:"en",debug:Object({NODE_ENV:"production",PUBLIC_URL:"",WDS_SOCKET_HOST:void 0,WDS_SOCKET_PATH:void 0,WDS_SOCKET_PORT:void 0,REACT_APP_API_URL:"/api"}).REACT_APP_I18N_DEBUG,load:"currentOnly",returnEmptyString:!1,interpolation:{escapeValue:!1}}),ie.a.on("languageChanged",(function(e){document.documentElement.setAttribute("lang",e)}));ie.a,a(89),a(90),a(91);T.apply(),o.a.render(r.a.createElement(n.Suspense,{fallback:r.a.createElement(V,null)},r.a.createElement(se,null)),document.getElementById("root")),"serviceWorker"in navigator&&navigator.serviceWorker.ready.then((function(e){e.unregister()}))}},[[50,1,2]]]);
2
+ //# sourceMappingURL=main.4bed24b2.chunk.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["assets/logo.svg","components/navBar.jsx","components/common/modal.jsx","components/common/select.jsx","theme.js","components/modals/settings.jsx","services/httpService.js","services/playerService.js","components/modals/urlDialog.jsx","services/configService.js","components/common/loader.jsx","components/modals/about.jsx","components/common/backdrop.jsx","components/player/playerStatus.jsx","components/player/playStopControl.jsx","components/player/playerControls.jsx","components/player/player.jsx","components/common/searchBox.jsx","components/streams.jsx","services/streamsService.js","components/player/miniPlayer.jsx","components/drawer.jsx","components/main.jsx","App.js","serviceWorker.js","i18n.js","index.js"],"names":["module","exports","NavBar","t","useTranslation","className","href","src","logo","width","height","alt","type","data-toggle","data-target","aria-controls","aria-expanded","aria-label","id","Modal","title","footer","children","defaultFooter","data-dismiss","tabIndex","role","aria-labelledby","aria-hidden","Select","label","row","data","rest","htmlFor","map","d","key","value","name","availableThemes","themeColor","apply","themeId","getCurrentId","themePath","getThemePath","find","document","querySelector","setAttribute","localId","localStorage","getItem","filter","length","removeItem","change","setItem","Settings","i18n","useState","setThemeId","languagesData","languages","sort","lang","isoCode","slice","localeEmoji","ISO6391","getNativeName","useEffect","theme","onChange","e","newThemeId","target","handleThemeChange","language","changeLanguage","axios","defaults","baseURL","process","interceptors","response","use","error","expectedError","status","toast","Translation","Promise","reject","get","post","body","method","params","FormData","set","play","http","stop","changeVol","delta","playRadio","playURL","url","URLDialog","setURL","handleOK","doPlayURL","a","errorToastOpts","TYPE","ERROR","render","toastId","update","Fragment","onClick","placeholder","input","onKeyDown","getConfig","Loader","About","config","setConfig","loading","setLoading","fetchData","tableData","mpd_host","mpd_port","environment","version","copyright","rel","style","color","coffee","item","scope","getScrollbarWidth","window","innerWidth","documentElement","clientWidth","Backdrop","visible","bodyStyled","classList","contains","paddingRight","add","remove","classes","PlayerStatus","playerStatus","playing","PlayStopControl","icon","faStop","faPlay","PlayerControls","volDisabled","vol","handleVolChange","toastMsg","toastOpts","autoClose","volTimeout","isActive","info","renderVolButton","disabled","stopPropagation","faVolumeDown","faVolumeUp","Player","require","SearchBox","autoComplete","onFocus","Streams","state","streams","query","isPlaying","props","handleItemClick","onBackdrop","getItemClasses","handleSearch","setState","this","filtered","k","toLowerCase","includes","filteredStreams","Object","keys","renderList","Component","withTranslation","MiniPlayer","Drawer","open","toggle","handleClick","handleTouchStart","touches","touchStartY","clientY","handleTouchMove","touchEndY","changedTouches","renderToggleButton","faChevronDown","faChevronUp","onTouchStart","onTouchMove","Main","App","networkError","backdrop","handleBackdrop","setTimeout","backdropTimeout","setDocumentTitle","updatePlayerStatus","updateInterval","con_mpd","pauseOnFocusLoss","Boolean","location","hostname","match","Backend","LanguageDetector","initReactI18next","init","fallbackLng","debug","REACT_APP_I18N_DEBUG","load","returnEmptyString","interpolation","escapeValue","on","ReactDOM","fallback","getElementById","navigator","serviceWorker","ready","then","registration","unregister"],"mappings":"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","file":"static/js/main.8e5c89f3.chunk.js","sourcesContent":["module.exports = __webpack_public_path__ + \"static/media/logo.91554ce9.svg\";","import React from 'react';\nimport { useTranslation } from 'react-i18next';\nimport './navBar.scss';\nimport logo from '../assets/logo.svg';\n\nconst NavBar = () => {\n const { t } = useTranslation();\n\n return (\n \n );\n};\nexport default NavBar;\n","import React from 'react';\nimport { useTranslation } from 'react-i18next';\n\nconst Modal = ({ id, title, footer, children }) => {\n const { t } = useTranslation();\n\n const defaultFooter = (\n \n );\n\n return (\n \n
\n
\n
\n
\n {title}\n
\n \n ×\n \n
\n
{children}
\n
{footer ? footer : defaultFooter}
\n
\n
\n
\n );\n};\n\nexport default Modal;\n","import React from 'react';\n\nconst Select = ({ id, label, row, data, ...rest }) => (\n
\n \n
\n \n
\n
\n);\n\nexport default Select;\n","const DEFAULT_THEME_ID = 'darkly';\n\nconst STORAGE_KEY = 'theme';\n\nconst getThemePath = themeId =>\n `https://stackpath.bootstrapcdn.com/bootswatch/4.4.1/${themeId}/bootstrap.min.css`;\n\nconst availableThemes = [\n { id: 'darkly', name: 'Darkly', themeColor: '#375a7f' },\n { id: 'lux', name: 'Lux', themeColor: '#1a1a1a' }\n];\n\nfunction change(themeId) {\n localStorage.setItem(STORAGE_KEY, themeId);\n apply();\n}\n\nfunction apply() {\n const themeId = getCurrentId();\n const themePath = getThemePath(themeId);\n const themeColor = availableThemes.find(t => t.id === themeId).themeColor;\n\n const linkEl = document.querySelector('link[title=\"theme\"]');\n linkEl.setAttribute('href', themePath);\n\n const metaEl = document.querySelector('meta[name=\"theme-color\"]');\n metaEl.setAttribute('content', themeColor);\n}\n\nfunction getCurrentId() {\n const localId = localStorage.getItem(STORAGE_KEY);\n\n if (localId === '') return DEFAULT_THEME_ID;\n if (availableThemes.filter(t => t.id === localId).length === 0) {\n localStorage.removeItem(STORAGE_KEY);\n return DEFAULT_THEME_ID;\n }\n\n return localId;\n}\n\nexport default {\n availableThemes,\n getCurrentId,\n change,\n apply\n};\n","import React, { useState, useEffect } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport ISO6391 from 'iso-639-1';\nimport localeEmoji from 'locale-emoji';\nimport Modal from '../common/modal';\nimport Select from '../common/select';\nimport theme from '../../theme';\nimport { languages } from '../../config.json';\n\nconst Settings = () => {\n const { t, i18n } = useTranslation();\n\n const [themeId, setThemeId] = useState('');\n\n const languagesData = languages.sort().map(lang => {\n const isoCode = lang.slice(0, 2);\n return {\n id: lang,\n name: `${localeEmoji(lang)} ${ISO6391.getNativeName(isoCode)}`\n };\n });\n\n const handleThemeChange = ({ target }) => {\n const newThemeId = target.value;\n theme.change(newThemeId);\n setThemeId(newThemeId);\n };\n\n useEffect(() => {\n setThemeId(theme.getCurrentId());\n }, []);\n\n return (\n \n handleThemeChange(e)}\n />\n i18n.changeLanguage(e.target.value)}\n />\n \n );\n};\n\nexport default Settings;\n","import React from 'react';\nimport axios from 'axios';\nimport { toast } from 'react-toastify';\nimport { Translation } from 'react-i18next';\n\naxios.defaults.baseURL = process.env.REACT_APP_API_URL;\n\naxios.interceptors.response.use(null, error => {\n const expectedError =\n error.response &&\n error.response.status >= 400 &&\n error.response.status < 500;\n\n // Some errors cause our app to only render a backdrop warning.\n // Queuing toasts would be redundant.\n const hasToastify = document.querySelector('.Toastify');\n\n if (hasToastify) {\n if (!expectedError)\n toast.error({t => t('errorUnexpected')});\n\n // Universal expected error\n if (error.response && error.response.status === 403)\n toast.error({t => t('errorForbidden')});\n }\n\n return Promise.reject(error);\n});\n\nexport default {\n get: axios.get,\n post: axios.post\n};\n","import http from './httpService.js';\n\nconst apiEndpoint = '/player';\n\nfunction body(method, params = null) {\n const body = new FormData();\n body.set('method', method);\n if (params) body.set('params', params);\n return body;\n}\n\nexport function getStatus() {\n return http.get(apiEndpoint);\n}\n\nexport function play() {\n return http.post(apiEndpoint, body('play'));\n}\n\nexport function stop() {\n return http.post(apiEndpoint, body('stop'));\n}\n\nexport function changeVol(delta) {\n return http.post(apiEndpoint, body('change_vol', delta));\n}\n\nexport function playRadio(name) {\n return http.post(apiEndpoint, body('play_radios', name));\n}\n\nexport function playURL(url) {\n return http.post(apiEndpoint, body('play_urls', url));\n}\n","import React, { useState } from 'react';\nimport { toast } from 'react-toastify';\nimport { useTranslation } from 'react-i18next';\nimport Modal from '../common/modal';\nimport { playURL } from '../../services/playerService';\n\nconst URLDialog = () => {\n const [url, setURL] = useState('');\n\n const { t } = useTranslation();\n\n const handleOK = () => {\n if (url === '') return;\n doPlayURL(url);\n setURL('');\n };\n\n const doPlayURL = async url => {\n const errorToastOpts = {\n type: toast.TYPE.ERROR,\n render: t('errorNotFound')\n };\n\n const toastId = toast(t('tryingURL'));\n\n try {\n await playURL(url);\n } catch (ex) {\n if (ex.response && ex.response.status === 400)\n toast.update(toastId, errorToastOpts);\n }\n };\n\n const handleChange = ({ target: input }) => {\n setURL(input.value);\n };\n\n const handleKeyDown = e => {\n if (e.key === 'Enter') handleOK();\n };\n\n const renderFooter = () => (\n \n \n {t('ok')}\n \n setURL('')}\n data-dismiss=\"modal\"\n >\n {t('cancel')}\n \n \n );\n\n return (\n \n \n \n );\n};\n\nexport default URLDialog;\n","import http from './httpService';\n\nconst apiEndpoint = '/config';\n\nexport function getConfig() {\n return http.get(apiEndpoint);\n}\n","import React from 'react';\nimport './loader.scss';\n\nconst Loader = () => (\n
\n
\n Loading...\n
\n
\n);\n\nexport default Loader;\n","import React from 'react';\nimport { useEffect, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport Modal from '../common/modal';\nimport { getConfig } from '../../services/configService';\nimport Loader from '../common/loader';\n\nconst About = () => {\n const { t } = useTranslation();\n\n const [config, setConfig] = useState({});\n const [loading, setLoading] = useState(true);\n\n useEffect(() => {\n async function fetchData() {\n const { data: config } = await getConfig();\n setConfig(config);\n setLoading(false);\n }\n fetchData();\n }, []);\n\n const tableData = [\n { label: t('mpdHost'), value: config.mpd_host },\n { label: t('mpdPort'), value: config.mpd_port },\n { label: t('environment'), value: config.environment },\n { label: t('version'), value: config.version },\n ];\n\n const renderTable = () => {\n if (loading) return ;\n\n return (\n \n \n {tableData.map((item) => (\n \n \n \n \n ))}\n \n
{item.label}{item.value}
\n );\n };\n\n const copyright = (\n
\n

\n \n {t('goToDocs')}\n \n

\n

\n Copyright © 2017-2020 \n {/* Use the default color, as some themes give a different color for links. */}\n \n Rafael Cavalcanti\n \n

\n
\n );\n\n const coffee = (\n
\n

{t('coffee')}

\n \n \n \n
\n );\n\n return (\n \n {renderTable()}\n {coffee}\n {copyright}\n \n );\n};\n\nexport default About;\n","import React from 'react';\nimport './backdrop.scss';\n\nconst Backdrop = ({ title, body }) => {\n const visible = title;\n const bodyStyled = document.body.classList.contains('body--backdrop');\n\n if (visible && !bodyStyled) {\n // Calculate this BEFORE adding the class.\n document.body.style.paddingRight = getScrollbarWidth() + 'px';\n document.body.classList.add('body--backdrop');\n // We need this check because Bootstrap modals also style paddingRight\n } else if (!visible && bodyStyled) {\n document.body.style.paddingRight = 0;\n document.body.classList.remove('body--backdrop');\n }\n\n const classes =\n 'backdrop p-2 text-white' + (visible ? ' backdrop--visible' : '');\n\n // We need text-white on h* tags because some themes override it\n return (\n
\n

{title}

\n
{body}
\n
\n );\n};\n\nconst getScrollbarWidth = () =>\n window.innerWidth - document.documentElement.clientWidth;\n\nexport default Backdrop;\n","import React from 'react';\nimport { useTranslation } from 'react-i18next';\n\nconst PlayerStatus = ({ playerStatus }) => {\n const { playing, title } = playerStatus;\n\n const { t } = useTranslation();\n\n return (\n
\n
\n {playing ? t('playing') : t('stopped')}\n
\n

{title}

\n
\n );\n};\n\nexport default PlayerStatus;\n","import React from 'react';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { faStop, faPlay } from '@fortawesome/free-solid-svg-icons';\nimport { play, stop } from '../../services/playerService';\n\nconst PlayStopControl = ({ playing }) =>\n playing ? (\n \n ) : (\n \n );\n\nexport default PlayStopControl;\n","import React from 'react';\nimport PlayStopControl from './playStopControl';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { faVolumeDown, faVolumeUp } from '@fortawesome/free-solid-svg-icons';\nimport { toast } from 'react-toastify';\nimport { useTranslation } from 'react-i18next';\nimport { changeVol } from '../../services/playerService';\nimport { volTimeout } from '../../config.json';\n\nconst PlayerControls = ({ playerStatus }) => {\n const { t } = useTranslation();\n\n const volDisabled = playerStatus.vol == null;\n\n const handleVolChange = async delta => {\n const { data: vol } = await changeVol(delta);\n\n const toastId = 'vol';\n const toastMsg = `${t('volume')}: ${vol}%`;\n const toastOpts = { toastId, autoClose: volTimeout };\n if (toast.isActive(toastId)) toast.update(toastId, { render: toastMsg });\n else toast.info(toastMsg, toastOpts);\n };\n\n const renderVolButton = (delta, icon, label) => (\n handleVolChange(delta)}\n aria-label={label}\n >\n \n \n );\n\n return (\n e.stopPropagation()}\n >\n {renderVolButton('-5', faVolumeDown, 'Volume down')}\n {renderVolButton('+5', faVolumeUp, 'Volume up')}\n \n \n );\n};\n\nexport default PlayerControls;\n","import React from 'react';\nimport PlayerStatus from './playerStatus';\nimport PlayerControls from './playerControls';\nimport './player.scss';\n\nconst Player = ({ playerStatus }) => {\n const renderLogo = () => (\n \n );\n\n return (\n
\n \n {renderLogo()}\n \n
\n );\n};\n\nexport default Player;\n","import React from 'react';\nimport { useTranslation } from 'react-i18next';\n\nconst SearchBox = ({ value, onChange }) => {\n const { t } = useTranslation();\n\n return (\n onChange(e.target.value)}\n onFocus={() => onChange('')}\n >\n );\n};\n\nexport default SearchBox;\n","import React, { Component } from 'react';\nimport { withTranslation } from 'react-i18next';\nimport { toast } from 'react-toastify';\nimport Loader from './common/loader';\nimport SearchBox from './common/searchBox';\nimport { playRadio } from '../services/playerService';\nimport { getStreams } from '../services/streamsService';\nimport './streams.scss';\n\nclass Streams extends Component {\n state = { streams: {}, loading: true, query: '' };\n\n async componentDidMount() {\n const { data: streams } = await getStreams();\n this.setState({ streams, loading: false });\n }\n\n isPlaying = name => {\n return (\n name === this.props.playerStatus.title && this.props.playerStatus.playing\n );\n };\n\n handleItemClick = async name => {\n const { t, onBackdrop } = this.props;\n\n if (this.isPlaying(name)) return;\n\n onBackdrop(t('tunning'), name);\n try {\n await playRadio(name);\n } catch (ex) {\n if (ex.response && ex.response.status === 400)\n toast.error(t('errorNotFound'));\n }\n };\n\n getItemClasses = name => {\n const classes = 'streams__item ellipsis list-group-item ';\n return this.isPlaying(name)\n ? classes + 'active'\n : classes + 'list-group-item-action';\n };\n\n handleSearch = query => {\n this.setState({ query });\n };\n\n filteredStreams() {\n const { streams, query } = this.state;\n\n if (query === '') return streams;\n\n let filtered = {};\n for (let k in streams) {\n if (k.toLowerCase().includes(query.toLowerCase()) && !streams[k]) {\n filtered[k] = streams[k];\n }\n }\n return filtered;\n }\n\n renderList() {\n const streams = this.filteredStreams();\n\n if (Object.keys(streams).length === 0)\n return

{this.props.t('noStreams')}

;\n\n return (\n
    \n {Object.keys(streams).map(name =>\n streams[name] ? (\n
  • \n {name}\n
  • \n ) : (\n this.handleItemClick(name)}\n >\n {name}\n \n )\n )}\n
\n );\n }\n\n render() {\n if (this.state.loading) return ;\n\n return (\n
\n \n {this.renderList()}\n
\n );\n }\n}\n\nexport default withTranslation()(Streams);\n","import http from './httpService';\n\nconst apiEndpoint = '/streams';\n\nexport function getStreams() {\n return http.get(apiEndpoint);\n}\n","import React from 'react';\nimport PlayStopControl from './playStopControl';\nimport './miniPlayer.scss';\n\nconst MiniPlayer = ({ playerStatus }) => {\n const { title, playing } = playerStatus;\n\n return (\n
\n
\n {title}\n
\n e.stopPropagation()}\n >\n \n
\n \n );\n};\n\nexport default MiniPlayer;\n","import React, { Component } from 'react';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { faChevronDown, faChevronUp } from '@fortawesome/free-solid-svg-icons';\nimport MiniPlayer from './player/miniPlayer';\nimport Player from './player/player';\nimport './drawer.scss';\n\nclass Drawer extends Component {\n state = { open: false };\n\n toggle = () => {\n this.setState({ open: !this.state.open });\n };\n\n handleClick = () => {\n this.toggle();\n };\n\n handleTouchStart = (e) => {\n // Ignore multitouch\n if (e.touches.length > 1) return this.setState({ touchStartY: null });\n\n this.setState({ touchStartY: e.touches[0].clientY });\n };\n\n handleTouchMove = (e) => {\n const { open, touchStartY } = this.state;\n\n // Ignore multitouch\n if (touchStartY === null || e.touches.length > 1) return;\n\n const touchEndY = e.changedTouches[0].clientY;\n const touchUp = touchEndY < touchStartY;\n const touchDown = touchEndY > touchStartY;\n\n if (touchDown && open) this.toggle();\n else if (touchUp && !open) this.toggle();\n };\n\n renderToggleButton = () => (\n \n \n \n );\n\n render() {\n const { playerStatus } = this.props;\n const { open } = this.state;\n\n let classes = 'drawer fixed-bottom bg-secondary shadow-lg p-2';\n\n if (open) {\n classes += ' drawer--open';\n document.body.classList.add('body--drawer');\n } else document.body.classList.remove('body--drawer');\n\n return (\n \n {this.renderToggleButton()}\n {open ? (\n \n ) : (\n \n )}\n \n );\n }\n}\n\nexport default Drawer;\n","import React from 'react';\nimport Player from './player/player';\nimport Streams from './streams';\nimport Drawer from './drawer';\nimport './main.scss';\n\nconst Main = ({ playerStatus, onBackdrop }) => {\n return (\n
\n \n
\n \n \n
\n
\n );\n};\n\nexport default Main;\n","import React, { Component } from 'react';\nimport { ToastContainer } from 'react-toastify';\nimport { withTranslation } from 'react-i18next';\nimport NavBar from './components/navBar';\nimport Settings from './components/modals/settings';\nimport URLDialog from './components/modals/urlDialog';\nimport About from './components/modals/about';\nimport Loader from './components/common/loader';\nimport Backdrop from './components/common/backdrop';\nimport Main from './components/main';\nimport { getStatus } from './services/playerService';\nimport { updateInterval, backdropTimeout } from './config.json';\nimport 'react-toastify/dist/ReactToastify.css';\n\nclass App extends Component {\n state = {\n playerStatus: {},\n loading: true,\n networkError: false,\n backdrop: {},\n };\n\n componentDidMount() {\n this.updatePlayerStatus();\n }\n\n componentDidUpdate() {\n this.setDocumentTitle();\n }\n\n async updatePlayerStatus() {\n try {\n const { data: playerStatus } = await getStatus();\n this.setState({ playerStatus, loading: false, networkError: false });\n } catch (ex) {\n this.setState({ loading: false, networkError: true });\n }\n\n setTimeout(() => this.updatePlayerStatus(), updateInterval);\n }\n\n handleBackdrop = (title, body = '') => {\n this.setState({ backdrop: { title, body } });\n setTimeout(() => this.setState({ backdrop: {} }), backdropTimeout);\n };\n\n setDocumentTitle = () => {\n const { playerStatus: status, networkError } = this.state;\n\n if (!networkError && status.playing)\n document.title = 'PiFi 🔊 ' + status.title;\n else document.title = 'PiFi Radio';\n };\n\n render() {\n const { loading, networkError, backdrop, playerStatus } = this.state;\n const { t } = this.props;\n\n if (networkError) return ;\n if (loading) return ;\n if (!playerStatus.con_mpd) return ;\n\n return (\n
\n \n \n \n
\n \n \n \n
\n );\n }\n}\n\nexport default withTranslation()(App);\n","// This optional code is used to register a service worker.\n// register() is not called by default.\n\n// This lets the app load faster on subsequent visits in production, and gives\n// it offline capabilities. However, it also means that developers (and users)\n// will only see deployed updates on subsequent visits to a page, after all the\n// existing tabs open on the page have been closed, since previously cached\n// resources are updated in the background.\n\n// To learn more about the benefits of this model and instructions on how to\n// opt-in, read https://bit.ly/CRA-PWA\n\nconst isLocalhost = Boolean(\n window.location.hostname === 'localhost' ||\n // [::1] is the IPv6 localhost address.\n window.location.hostname === '[::1]' ||\n // 127.0.0.0/8 are considered localhost for IPv4.\n window.location.hostname.match(\n /^127(?:\\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/\n )\n);\n\nexport function register(config) {\n if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {\n // The URL constructor is available in all browsers that support SW.\n const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);\n if (publicUrl.origin !== window.location.origin) {\n // Our service worker won't work if PUBLIC_URL is on a different origin\n // from what our page is served on. This might happen if a CDN is used to\n // serve assets; see https://github.com/facebook/create-react-app/issues/2374\n return;\n }\n\n window.addEventListener('load', () => {\n const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;\n\n if (isLocalhost) {\n // This is running on localhost. Let's check if a service worker still exists or not.\n checkValidServiceWorker(swUrl, config);\n\n // Add some additional logging to localhost, pointing developers to the\n // service worker/PWA documentation.\n navigator.serviceWorker.ready.then(() => {\n console.log(\n 'This web app is being served cache-first by a service ' +\n 'worker. To learn more, visit https://bit.ly/CRA-PWA'\n );\n });\n } else {\n // Is not localhost. Just register service worker\n registerValidSW(swUrl, config);\n }\n });\n }\n}\n\nfunction registerValidSW(swUrl, config) {\n navigator.serviceWorker\n .register(swUrl)\n .then(registration => {\n registration.onupdatefound = () => {\n const installingWorker = registration.installing;\n if (installingWorker == null) {\n return;\n }\n installingWorker.onstatechange = () => {\n if (installingWorker.state === 'installed') {\n if (navigator.serviceWorker.controller) {\n // At this point, the updated precached content has been fetched,\n // but the previous service worker will still serve the older\n // content until all client tabs are closed.\n console.log(\n 'New content is available and will be used when all ' +\n 'tabs for this page are closed. See https://bit.ly/CRA-PWA.'\n );\n\n // Execute callback\n if (config && config.onUpdate) {\n config.onUpdate(registration);\n }\n } else {\n // At this point, everything has been precached.\n // It's the perfect time to display a\n // \"Content is cached for offline use.\" message.\n console.log('Content is cached for offline use.');\n\n // Execute callback\n if (config && config.onSuccess) {\n config.onSuccess(registration);\n }\n }\n }\n };\n };\n })\n .catch(error => {\n console.error('Error during service worker registration:', error);\n });\n}\n\nfunction checkValidServiceWorker(swUrl, config) {\n // Check if the service worker can be found. If it can't reload the page.\n fetch(swUrl, {\n headers: { 'Service-Worker': 'script' }\n })\n .then(response => {\n // Ensure service worker exists, and that we really are getting a JS file.\n const contentType = response.headers.get('content-type');\n if (\n response.status === 404 ||\n (contentType != null && contentType.indexOf('javascript') === -1)\n ) {\n // No service worker found. Probably a different app. Reload the page.\n navigator.serviceWorker.ready.then(registration => {\n registration.unregister().then(() => {\n window.location.reload();\n });\n });\n } else {\n // Service worker found. Proceed as normal.\n registerValidSW(swUrl, config);\n }\n })\n .catch(() => {\n console.log(\n 'No internet connection found. App is running in offline mode.'\n );\n });\n}\n\nexport function unregister() {\n if ('serviceWorker' in navigator) {\n navigator.serviceWorker.ready.then(registration => {\n registration.unregister();\n });\n }\n}\n","import i18n from 'i18next';\nimport { initReactI18next } from 'react-i18next';\n\nimport Backend from 'i18next-http-backend';\nimport LanguageDetector from 'i18next-browser-languagedetector';\n// not like to use this?\n// have a look at the Quick start guide\n// for passing in lng and translations on init\n\ni18n\n // load translation using xhr -> see /public/locales\n // learn more: https://github.com/i18next/i18next-xhr-backend\n .use(Backend)\n // detect user language\n // learn more: https://github.com/i18next/i18next-browser-languageDetector\n .use(LanguageDetector)\n // pass the i18n instance to react-i18next.\n .use(initReactI18next)\n // init i18next\n // for all options read: https://www.i18next.com/overview/configuration-options\n .init({\n fallbackLng: 'en',\n debug: process.env.REACT_APP_I18N_DEBUG,\n load: 'currentOnly',\n returnEmptyString: false,\n\n interpolation: {\n escapeValue: false // not needed for react as it escapes by default\n }\n });\n\n// Set language on html tag\ni18n.on('languageChanged', lang => {\n document.documentElement.setAttribute('lang', lang);\n});\n\nexport default i18n;\n","import React, { Suspense } from 'react';\nimport ReactDOM from 'react-dom';\nimport App from './App';\nimport Loader from './components/common/loader';\nimport * as serviceWorker from './serviceWorker';\nimport './i18n';\nimport theme from './theme';\nimport './index.scss';\n// Bootstrap dependencies\nimport 'jquery/dist/jquery.min.js';\nimport 'bootstrap/dist/js/bootstrap.js';\n\ntheme.apply();\n\nReactDOM.render(\n // Suspense needed for i18n\n }>\n \n ,\n document.getElementById('root')\n);\n\n// If you want your app to work offline and load faster, you can change\n// unregister() to register() below. Note this comes with some pitfalls.\n// Learn more about service workers: https://bit.ly/CRA-PWA\nserviceWorker.unregister();\n"],"sourceRoot":""}
1
+ {"version":3,"sources":["assets/logo.svg","components/navBar.jsx","components/common/modal.jsx","components/common/select.jsx","theme.js","components/modals/settings.jsx","services/httpService.js","services/playerService.js","components/modals/urlDialog.jsx","services/configService.js","components/common/loader.jsx","components/modals/about.jsx","components/common/backdrop.jsx","components/player/playerStatus.jsx","components/player/playStopControl.jsx","components/player/playerControls.jsx","components/player/player.jsx","components/common/searchBox.jsx","components/streams.jsx","services/streamsService.js","components/player/miniPlayer.jsx","components/drawer.jsx","components/main.jsx","App.js","serviceWorker.js","i18n.js","index.js"],"names":["module","exports","NavBar","t","useTranslation","className","href","src","logo","width","height","alt","type","data-toggle","data-target","aria-controls","aria-expanded","aria-label","id","Modal","title","footer","children","defaultFooter","data-dismiss","tabIndex","role","aria-labelledby","aria-hidden","Select","label","row","data","rest","htmlFor","map","d","key","value","name","availableThemes","themeColor","apply","themeId","getCurrentId","themePath","getThemePath","find","document","querySelector","setAttribute","localId","localStorage","getItem","filter","length","removeItem","change","setItem","Settings","i18n","useState","setThemeId","languagesData","languages","sort","lang","isoCode","slice","localeEmoji","ISO6391","getNativeName","useEffect","theme","onChange","e","newThemeId","target","handleThemeChange","language","changeLanguage","axios","defaults","baseURL","process","interceptors","response","use","error","expectedError","status","toast","Translation","Promise","reject","get","post","body","method","params","FormData","set","play","http","stop","changeVol","delta","playRadio","playURL","url","URLDialog","setURL","handleOK","doPlayURL","a","errorToastOpts","TYPE","ERROR","render","toastId","update","Fragment","onClick","placeholder","input","onKeyDown","getConfig","Loader","About","config","setConfig","loading","setLoading","fetchData","tableData","mpd_host","mpd_port","environment","version","copyright","rel","style","color","coffee","item","scope","getScrollbarWidth","window","innerWidth","documentElement","clientWidth","Backdrop","visible","bodyStyled","classList","contains","paddingRight","add","remove","classes","PlayerStatus","playerStatus","playing","PlayStopControl","icon","faStop","faPlay","PlayerControls","volDisabled","vol","handleVolChange","toastMsg","toastOpts","autoClose","volTimeout","isActive","info","renderVolButton","disabled","stopPropagation","faVolumeDown","faVolumeUp","Player","require","SearchBox","autoComplete","onFocus","Streams","state","streams","query","isPlaying","props","handleItemClick","onBackdrop","getItemClasses","handleSearch","setState","this","filtered","k","toLowerCase","includes","filteredStreams","Object","keys","renderList","Component","withTranslation","MiniPlayer","Drawer","open","toggle","handleClick","handleTouchStart","touches","touchStartY","clientY","handleTouchMove","touchEndY","changedTouches","renderToggleButton","faChevronDown","faChevronUp","onTouchStart","onTouchMove","Main","App","networkError","backdrop","handleBackdrop","setTimeout","backdropTimeout","setDocumentTitle","updatePlayerStatus","updateInterval","con_mpd","pauseOnFocusLoss","Boolean","location","hostname","match","Backend","LanguageDetector","initReactI18next","init","fallbackLng","debug","REACT_APP_I18N_DEBUG","load","returnEmptyString","interpolation","escapeValue","on","ReactDOM","fallback","getElementById","navigator","serviceWorker","ready","then","registration","unregister"],"mappings":"0NAAAA,EAAOC,QAAU,IAA0B,kC,mZCiE5BC,EA5DA,WAAO,IACZC,EAAMC,cAAND,EAER,OACE,yBAAKE,UAAU,kDACb,yBAAKA,UAAU,aACb,uBAAGA,UAAU,eAAeC,KAAK,KAC/B,yBACEC,IAAKC,IACLC,MAAM,KACNC,OAAO,KACPL,UAAU,wCACVM,IAAI,KANR,cAUA,4BACEN,UAAU,iBACVO,KAAK,SACLC,cAAY,WACZC,cAAY,sBACZC,gBAAc,qBACdC,gBAAc,QACdC,aAAW,qBAEX,0BAAMZ,UAAU,yBAElB,yBAAKA,UAAU,2BAA2Ba,GAAG,sBAC3C,yBAAKb,UAAU,wBAGb,4BACEA,UAAU,wBACVQ,cAAY,QACZC,cAAY,eAEXX,EAAE,YAGL,4BACEE,UAAU,wBACVQ,cAAY,QACZC,cAAY,aAEXX,EAAE,aAGL,4BACEE,UAAU,wBACVQ,cAAY,QACZC,cAAY,UAEXX,EAAE,e,iCCbFgB,EAzCD,SAAC,GAAqC,IAAnCD,EAAkC,EAAlCA,GAAIE,EAA8B,EAA9BA,MAAOC,EAAuB,EAAvBA,OAAQC,EAAe,EAAfA,SAC1BnB,EAAMC,cAAND,EAEFoB,EACJ,4BAAQlB,UAAU,oBAAoBmB,eAAa,SAChDrB,EAAE,UAIP,OACE,yBACEE,UAAU,aACVa,GAAIA,EACJO,SAAS,KACTC,KAAK,SACLC,kBAAgB,sBAChBC,cAAY,QAEZ,yBAAKvB,UAAU,eAAeqB,KAAK,YACjC,yBAAKrB,UAAU,iBACb,yBAAKA,UAAU,gBACb,wBAAIA,UAAU,cAAca,GAAG,uBAC5BE,GAEH,4BACER,KAAK,SACLP,UAAU,QACVmB,eAAa,QACbP,aAAW,SAEX,0BAAMW,cAAY,QAAlB,UAGJ,yBAAKvB,UAAU,cAAciB,GAC7B,yBAAKjB,UAAU,gBAAgBgB,GAAkBE,O,QClB5CM,EAjBA,SAAC,GAAD,IAAGX,EAAH,EAAGA,GAAIY,EAAP,EAAOA,MAAOC,EAAd,EAAcA,IAAKC,EAAnB,EAAmBA,KAASC,EAA5B,kDACb,yBAAK5B,UAAW0B,EAAM,iBAAmB,cACvC,2BAAOG,QAAShB,EAAIb,UAAU,2BAC3ByB,GAEH,yBAAKzB,UAAU,aACb,0CAAQa,GAAIA,EAAIb,UAAU,gBAAmB4B,GAC1CD,EAAKG,KAAI,SAAAC,GAAC,OACT,4BAAQC,IAAKD,EAAElB,IAAMkB,EAAGE,MAAOF,EAAElB,IAAMkB,GACpCA,EAAEG,MAAQH,UCJjBI,EAAkB,CACtB,CAAEtB,GAAI,SAAUqB,KAAM,SAAUE,WAAY,WAC5C,CAAEvB,GAAI,MAAOqB,KAAM,MAAOE,WAAY,YAQxC,SAASC,IACP,IAAMC,EAAUC,IACVC,EAfa,SAAAF,GAAO,oEAC6BA,EAD7B,sBAeRG,CAAaH,GACzBF,EAAaD,EAAgBO,MAAK,SAAA5C,GAAC,OAAIA,EAAEe,KAAOyB,KAASF,WAEhDO,SAASC,cAAc,uBAC/BC,aAAa,OAAQL,GAEbG,SAASC,cAAc,4BAC/BC,aAAa,UAAWT,GAGjC,SAASG,IACP,IAAMO,EAAUC,aAAaC,QA5BX,SA8BlB,MAAgB,KAAZF,EAhCmB,SAiCsC,IAAzDX,EAAgBc,QAAO,SAAAnD,GAAC,OAAIA,EAAEe,KAAOiC,KAASI,QAChDH,aAAaI,WAhCG,SAFK,UAsChBL,EAGM,OACbX,kBACAI,eACAa,OAhCF,SAAgBd,GACdS,aAAaM,QAXK,QAWgBf,GAClCD,KA+BAA,S,QCSaiB,EA7CE,WAAO,IAAD,EACDvD,cAAZD,EADa,EACbA,EAAGyD,EADU,EACVA,KADU,EAGSC,mBAAS,IAHlB,mBAGdlB,EAHc,KAGLmB,EAHK,KAKfC,EAAgBC,IAAUC,OAAO9B,KAAI,SAAA+B,GACzC,IAAMC,EAAUD,EAAKE,MAAM,EAAG,GAC9B,MAAO,CACLlD,GAAIgD,EACJ3B,KAAK,GAAD,OAAK8B,IAAYH,GAAjB,YAA0BI,IAAQC,cAAcJ,QAcxD,OAJAK,qBAAU,WACRV,EAAWW,EAAM7B,kBAChB,IAGD,kBAAC,EAAD,CAAO1B,GAAG,WAAWE,MAAOjB,EAAE,aAC5B,kBAAC,EAAD,CACEe,GAAG,eACHY,MAAO3B,EAAE,SACT6B,KAAMyC,EAAMjC,gBACZT,KAAG,EACHO,MAAOK,EACP+B,SAAU,SAAAC,GAAC,OAlBS,SAAC,GAAgB,IACnCC,EADkC,EAAbC,OACDvC,MAC1BmC,EAAMhB,OAAOmB,GACbd,EAAWc,GAeQE,CAAkBH,MAEnC,kBAAC,EAAD,CACEzD,GAAG,kBACHY,MAAO3B,EAAE,YACT6B,KAAM+B,EACNhC,KAAG,EACHO,MAAOsB,EAAKmB,SACZL,SAAU,SAAAC,GAAC,OAAIf,EAAKoB,eAAeL,EAAEE,OAAOvC,Y,yBC3CpD2C,IAAMC,SAASC,QAAUC,OAEzBH,IAAMI,aAAaC,SAASC,IAAI,MAAM,SAAAC,GACpC,IAAMC,EACJD,EAAMF,UACNE,EAAMF,SAASI,QAAU,KACzBF,EAAMF,SAASI,OAAS,IAe1B,OAXoB1C,SAASC,cAAc,eAGpCwC,GACHE,IAAMH,MAAM,kBAACI,EAAA,EAAD,MAAc,SAAAzF,GAAC,OAAIA,EAAE,uBAG/BqF,EAAMF,UAAsC,MAA1BE,EAAMF,SAASI,QACnCC,IAAMH,MAAM,kBAACI,EAAA,EAAD,MAAc,SAAAzF,GAAC,OAAIA,EAAE,uBAG9B0F,QAAQC,OAAON,MAGT,OACbO,IAAKd,IAAMc,IACXC,KAAMf,IAAMe,MC3Bd,SAASC,EAAKC,GAAwB,IAAhBC,EAAe,uDAAN,KACvBF,EAAO,IAAIG,SAGjB,OAFAH,EAAKI,IAAI,SAAUH,GACfC,GAAQF,EAAKI,IAAI,SAAUF,GACxBF,EAOF,SAASK,IACd,OAAOC,EAAKP,KAdM,UAcYC,EAAK,SAG9B,SAASO,IACd,OAAOD,EAAKP,KAlBM,UAkBYC,EAAK,SAG9B,SAASQ,EAAUC,GACxB,OAAOH,EAAKP,KAtBM,UAsBYC,EAAK,aAAcS,IAG5C,SAASC,EAAUpE,GACxB,OAAOgE,EAAKP,KA1BM,UA0BYC,EAAK,cAAe1D,IAG7C,SAASqE,EAAQC,GACtB,OAAON,EAAKP,KA9BM,UA8BYC,EAAK,YAAaY,IC1BlD,IAoEeC,EApEG,WAAO,IAAD,EACAjD,mBAAS,IADT,mBACfgD,EADe,KACVE,EADU,KAGd5G,EAAMC,cAAND,EAEF6G,EAAW,WACH,KAARH,IACJI,EAAUJ,GACVE,EAAO,MAGHE,EAAS,uCAAG,WAAMJ,GAAN,iBAAAK,EAAA,6DACVC,EAAiB,CACrBvG,KAAM+E,IAAMyB,KAAKC,MACjBC,OAAQnH,EAAE,kBAGNoH,EAAU5B,YAAMxF,EAAE,cANR,kBASRyG,EAAQC,GATA,uDAWV,KAAGvB,UAAmC,MAAvB,KAAGA,SAASI,QAC7BC,IAAM6B,OAAOD,EAASJ,GAZV,yDAAH,sDA2Cf,OACE,kBAAC,EAAD,CAAOjG,GAAG,aAAaE,MAAOjB,EAAE,WAAYkB,OAnB5C,kBAAC,IAAMoG,SAAP,KACE,4BACEpH,UAAU,kBACVmB,eAAa,QACbkG,QAASV,GAER7G,EAAE,OAEL,4BACEE,UAAU,oBACVqH,QAAS,kBAAMX,EAAO,KACtBvF,eAAa,SAEZrB,EAAE,aAOL,2BACEE,UAAU,oBACVO,KAAK,OACL+G,YAAY,MACZrF,MAAOuE,EACPnC,SAlCe,SAAC,GAAuB,IAAbkD,EAAY,EAApB/C,OACtBkC,EAAOa,EAAMtF,QAkCTuF,UA/BgB,SAAAlD,GACN,UAAVA,EAAEtC,KAAiB2E,SClCpB,SAASc,IACd,OAAOvB,EAAKR,IAHM,W,UCSLgC,EARA,kBACb,yBAAK1H,UAAU,UACb,yBAAKA,UAAU,iBAAiBqB,KAAK,UACnC,0BAAMrB,UAAU,WAAhB,iBC6FS2H,EA5FD,WAAO,IACX7H,EAAMC,cAAND,EADU,EAGU0D,mBAAS,IAHnB,mBAGXoE,EAHW,KAGHC,EAHG,OAIYrE,oBAAS,GAJrB,mBAIXsE,EAJW,KAIFC,EAJE,KAMlB5D,qBAAU,WAAM,4CACd,8BAAA0C,EAAA,sEACiCY,IADjC,gBACgBG,EADhB,EACUjG,KACRkG,EAAUD,GACVG,GAAW,GAHb,4CADc,uBAAC,WAAD,wBAMdC,KACC,IAEH,IAAMC,EAAY,CAChB,CAAExG,MAAO3B,EAAE,WAAYmC,MAAO2F,EAAOM,UACrC,CAAEzG,MAAO3B,EAAE,WAAYmC,MAAO2F,EAAOO,UACrC,CAAE1G,MAAO3B,EAAE,eAAgBmC,MAAO2F,EAAOQ,aACzC,CAAE3G,MAAO3B,EAAE,WAAYmC,MAAO2F,EAAOS,UAoBjCC,EACJ,yBAAKtI,UAAU,wBACb,2BACE,uBACEC,KAAK,2BACLuE,OAAO,SACP+D,IAAI,sBACJC,MAAO,CAAEC,MAAO,YAEf3I,EAAE,cAGP,0DAGE,uBACEG,KAAK,uBACLuE,OAAO,SACP+D,IAAI,sBACJC,MAAO,CAAEC,MAAO,YAJlB,uBAYAC,EACJ,yBAAK1I,UAAU,eACb,2BAAIF,EAAE,WACN,uBACEG,KAAK,uCACLuE,OAAO,SACP+D,IAAI,uBAEJ,yBACErI,IAAI,wDACJI,IAAI,kBACJkI,MAAO,CAAEnI,OAAQ,GAAID,MAAO,SAMpC,OACE,kBAAC,EAAD,CAAOS,GAAG,QAAQE,MAAOjB,EAAE,UA7DvBgI,EAAgB,kBAAC,EAAD,MAGlB,2BAAO9H,UAAU,SACf,+BACGiI,EAAUnG,KAAI,SAAC6G,GAAD,OACb,wBAAI3G,IAAK2G,EAAKlH,OACZ,wBAAImH,MAAM,OAAOD,EAAKlH,OACtB,4BAAKkH,EAAK1G,aAuDjByG,EACAJ,ICjEDO,G,MAAoB,kBACxBC,OAAOC,WAAapG,SAASqG,gBAAgBC,cAEhCC,EA7BE,SAAC,GAAqB,IAAnBnI,EAAkB,EAAlBA,MAAO6E,EAAW,EAAXA,KACnBuD,EAAUpI,EACVqI,EAAazG,SAASiD,KAAKyD,UAAUC,SAAS,kBAEhDH,IAAYC,GAEdzG,SAASiD,KAAK4C,MAAMe,aAAeV,IAAsB,KACzDlG,SAASiD,KAAKyD,UAAUG,IAAI,oBAElBL,GAAWC,IACrBzG,SAASiD,KAAK4C,MAAMe,aAAe,EACnC5G,SAASiD,KAAKyD,UAAUI,OAAO,mBAGjC,IAAMC,EACJ,2BAA6BP,EAAU,qBAAuB,IAGhE,OACE,yBAAKnJ,UAAW0J,GACd,wBAAI1J,UAAU,cAAce,GAC5B,wBAAIf,UAAU,cAAc4F,KCNnB+D,EAfM,SAAC,GAAsB,IAApBC,EAAmB,EAAnBA,aACdC,EAAmBD,EAAnBC,QAAS9I,EAAU6I,EAAV7I,MAETjB,EAAMC,cAAND,EAER,OACE,yBAAKE,UAAU,qBACb,wBAAIA,UAAU,wBACDF,EAAV+J,EAAY,UAAe,YAE9B,wBAAI7J,UAAU,YAAYe,K,gBCGjB+I,EAXS,SAAC,GAAD,SAAGD,QAEvB,4BAAQ7J,UAAU,iBAAiBqH,QAASlB,EAAMvF,aAAW,QAC3D,kBAAC,IAAD,CAAiBmJ,KAAMC,OAGzB,4BAAQhK,UAAU,eAAeqH,QAASpB,EAAMrF,aAAW,QACzD,kBAAC,IAAD,CAAiBmJ,KAAME,QCmCdC,EAtCQ,SAAC,GAAsB,IAApBN,EAAmB,EAAnBA,aAChB9J,EAAMC,cAAND,EAEFqK,EAAkC,MAApBP,EAAaQ,IAE3BC,EAAe,uCAAG,WAAMhE,GAAN,qBAAAQ,EAAA,sEACMT,EAAUC,GADhB,gBACR+D,EADQ,EACdzI,KAEQ,MACV2I,EAJgB,UAIFxK,EAAE,UAJA,aAIcsK,EAJd,KAKhBG,EAAY,CAAErD,QAFJ,MAEasD,UAAWC,KACpCnF,IAAMoF,SAHM,OAGapF,IAAM6B,OAHnB,MAGmC,CAAEF,OAAQqD,IACxDhF,IAAMqF,KAAKL,EAAUC,GAPJ,2CAAH,sDAUfK,EAAkB,SAACvE,EAAO0D,EAAMtI,GAAd,OACtB,4BACEzB,UAAU,mBACV6K,SAAUV,EACV9C,QAAS,kBAAMgD,EAAgBhE,IAC/BzF,aAAYa,GAEZ,kBAAC,IAAD,CAAiBsI,KAAMA,MAI3B,OACE,yBACE/J,UAAU,sCACVqH,QAAS,SAAA/C,GAAC,OAAIA,EAAEwG,oBAEfF,EAAgB,KAAMG,IAAc,eACpCH,EAAgB,KAAMI,IAAY,aACnC,kBAAC,EAAD,CAAiBnB,QAASD,EAAaC,YCnB9BoB,I,MAlBA,SAAC,GAAsB,IAApBrB,EAAmB,EAAnBA,aAShB,OACE,yBAAK5J,UAAU,UACb,kBAAC,EAAD,CAAc4J,aAAcA,IAT9B,yBACE1J,IAAKgL,EAAQ,IACb5K,IAAI,OACJN,UAAU,oBAQV,kBAAC,EAAD,CAAgB4J,aAAcA,OCGrBuB,GAlBG,SAAC,GAAyB,IAAvBlJ,EAAsB,EAAtBA,MAAOoC,EAAe,EAAfA,SAClBvE,EAAMC,cAAND,EAER,OACE,2BACEE,UAAU,oBACVO,KAAK,OACLM,GAAG,QACHyG,YAAaxH,EAAE,UACfc,aAAYd,EAAE,UACdsL,aAAa,MACbnJ,MAAOA,EACPoC,SAAU,SAAAC,GAAC,OAAID,EAASC,EAAEE,OAAOvC,QACjCoJ,QAAS,kBAAMhH,EAAS,Q,UCPxBiH,G,4MACJC,MAAQ,CAAEC,QAAS,GAAI1D,SAAS,EAAM2D,MAAO,I,EAO7CC,UAAY,SAAAxJ,GACV,OACEA,IAAS,EAAKyJ,MAAM/B,aAAa7I,OAAS,EAAK4K,MAAM/B,aAAaC,S,EAItE+B,gB,uCAAkB,WAAM1J,GAAN,mBAAA2E,EAAA,2DACU,EAAK8E,MAAvB7L,EADQ,EACRA,EAAG+L,EADK,EACLA,YAEP,EAAKH,UAAUxJ,GAHH,wDAKhB2J,EAAW/L,EAAE,WAAYoC,GALT,kBAORoE,EAAUpE,GAPF,uDASV,KAAG+C,UAAmC,MAAvB,KAAGA,SAASI,QAC7BC,IAAMH,MAAMrF,EAAE,kBAVF,yD,wDAclBgM,eAAiB,SAAA5J,GACf,IAAMwH,EAAU,0CAChB,OAAO,EAAKgC,UAAUxJ,GAClBwH,EAAU,SACVA,EAAU,0B,EAGhBqC,aAAe,SAAAN,GACb,EAAKO,SAAS,CAAEP,W,oMCxCXvF,EAAKR,IAHM,Y,gBDWF8F,E,EAAN7J,KACRsK,KAAKD,SAAS,CAAER,UAAS1D,SAAS,I,8IAkCjB,IAAD,EACWmE,KAAKV,MAAxBC,EADQ,EACRA,QAASC,EADD,EACCA,MAEjB,GAAc,KAAVA,EAAc,OAAOD,EAEzB,IAAIU,EAAW,GACf,IAAK,IAAIC,KAAKX,EACRW,EAAEC,cAAcC,SAASZ,EAAMW,iBAAmBZ,EAAQW,KAC5DD,EAASC,GAAKX,EAAQW,IAG1B,OAAOD,I,mCAGK,IAAD,OACLV,EAAUS,KAAKK,kBAErB,OAAoC,IAAhCC,OAAOC,KAAKhB,GAAStI,OAChB,wBAAIlD,UAAU,OAAOiM,KAAKN,MAAM7L,EAAE,cAGzC,wBAAIE,UAAU,+BACXuM,OAAOC,KAAKhB,GAAS1J,KAAI,SAAAI,GAAI,OAC5BsJ,EAAQtJ,GACN,wBAAIlC,UAAU,2BAA2BgC,IAAKE,GAC3CA,GAGH,wBACElC,UAAW,EAAK8L,eAAe5J,GAC/BF,IAAKE,EACLmF,QAAS,kBAAM,EAAKuE,gBAAgB1J,KAEnCA,S,+BASX,OAAI+J,KAAKV,MAAMzD,QAAgB,kBAAC,EAAD,MAG7B,yBAAK9H,UAAU,WACb,kBAAC,GAAD,CAAWiC,MAAOgK,KAAKV,MAAME,MAAOpH,SAAU4H,KAAKF,eAClDE,KAAKQ,kB,GAtFQC,aA4FPC,iBAAkBrB,IE/ElBsB,I,MAlBI,SAAC,GAAsB,IAApBhD,EAAmB,EAAnBA,aACZ7I,EAAmB6I,EAAnB7I,MAAO8I,EAAYD,EAAZC,QAEf,OACE,yBAAK7J,UAAU,eACb,yBAAKA,UAAU,8BACZe,GAEH,yBACEf,UAAU,qBACVqH,QAAS,SAAA/C,GAAC,OAAIA,EAAEwG,oBAEhB,kBAAC,EAAD,CAAiBjB,QAASA,QCgEnBgD,I,kNAxEbtB,MAAQ,CAAEuB,MAAM,G,EAEhBC,OAAS,WACP,EAAKf,SAAS,CAAEc,MAAO,EAAKvB,MAAMuB,Q,EAGpCE,YAAc,WACZ,EAAKD,U,EAGPE,iBAAmB,SAAC3I,GAElB,GAAIA,EAAE4I,QAAQhK,OAAS,EAAG,OAAO,EAAK8I,SAAS,CAAEmB,YAAa,OAE9D,EAAKnB,SAAS,CAAEmB,YAAa7I,EAAE4I,QAAQ,GAAGE,W,EAG5CC,gBAAkB,SAAC/I,GAAO,IAAD,EACO,EAAKiH,MAA3BuB,EADe,EACfA,KAAMK,EADS,EACTA,YAGd,KAAoB,OAAhBA,GAAwB7I,EAAE4I,QAAQhK,OAAS,GAA/C,CAEA,IAAMoK,EAAYhJ,EAAEiJ,eAAe,GAAGH,SAEpBE,EAAYH,GAEbL,GAHDQ,EAAYH,IAIPL,IADE,EAAKC,W,EAI9BS,mBAAqB,kBACnB,4BACExN,UAAU,0CACVY,aAAW,iBAEX,kBAAC,IAAD,CACEmJ,KAAM,EAAKwB,MAAMuB,KAAOW,IAAgBC,IACxC1N,UAAU,Y,uDAKN,IACA4J,EAAiBqC,KAAKN,MAAtB/B,aACAkD,EAASb,KAAKV,MAAduB,KAEJpD,EAAU,iDAOd,OALIoD,GACFpD,GAAW,gBACX/G,SAASiD,KAAKyD,UAAUG,IAAI,iBACvB7G,SAASiD,KAAKyD,UAAUI,OAAO,gBAGpC,yBACEzJ,UAAW0J,EACXrC,QAAS4E,KAAKe,YACdW,aAAc1B,KAAKgB,iBACnBW,YAAa3B,KAAKoB,iBAEjBpB,KAAKuB,qBACLV,EACC,kBAAC,GAAD,CAAQlD,aAAcA,IAEtB,kBAAC,GAAD,CAAYA,aAAcA,S,GAlEf8C,cCWNmB,I,MAZF,SAAC,GAAkC,IAAhCjE,EAA+B,EAA/BA,aAAciC,EAAiB,EAAjBA,WAC5B,OACE,0BAAM7L,UAAU,QACd,kBAAC,GAAD,CAAQ4J,aAAcA,IACtB,yBAAK5J,UAAU,2BACb,kBAAC,GAAD,CAAS6L,WAAYA,EAAYjC,aAAcA,IAC/C,kBAAC,GAAD,CAAQA,aAAcA,QCExBkE,I,kNACJvC,MAAQ,CACN3B,aAAc,GACd9B,SAAS,EACTiG,cAAc,EACdC,SAAU,I,EAsBZC,eAAiB,SAAClN,GAAsB,IAAf6E,EAAc,uDAAP,GAC9B,EAAKoG,SAAS,CAAEgC,SAAU,CAAEjN,QAAO6E,UACnCsI,YAAW,kBAAM,EAAKlC,SAAS,CAAEgC,SAAU,OAAOG,M,EAGpDC,iBAAmB,WAAO,IAAD,EACwB,EAAK7C,MAA9BlG,EADC,EACfuE,cADe,EACOmE,cAET1I,EAAOwE,QAC1BlH,SAAS5B,MAAQ,qBAAasE,EAAOtE,MAClC4B,SAAS5B,MAAQ,c,kEA5BtBkL,KAAKoC,uB,2CAILpC,KAAKmC,qB,6LhBfAlI,EAAKR,IAVM,W,gBgB8BAkE,E,EAANjI,KACRsK,KAAKD,SAAS,CAAEpC,eAAc9B,SAAS,EAAOiG,cAAc,I,gDAE5D9B,KAAKD,SAAS,CAAElE,SAAS,EAAOiG,cAAc,I,QAGhDG,YAAW,kBAAM,EAAKG,uBAAsBC,K,8IAgBpC,IAAD,EACmDrC,KAAKV,MAAvDzD,EADD,EACCA,QAASiG,EADV,EACUA,aAAcC,EADxB,EACwBA,SAAUpE,EADlC,EACkCA,aACjC9J,EAAMmM,KAAKN,MAAX7L,EAER,OAAIiO,EAAqB,kBAAC,EAAD,CAAUhN,MAAOjB,EAAE,kBACxCgI,EAAgB,kBAAC,EAAD,MACf8B,EAAa2E,QAGhB,yBAAKvO,UAAU,OACb,kBAAC,IAAD,CAAgBwO,kBAAkB,IAClC,kBAAC,EAAD,CAAUzN,MAAOiN,EAASjN,MAAO6E,KAAMoI,EAASpI,OAChD,kBAAC,EAAD,MACA,kBAAC,GAAD,CAAMiG,WAAYI,KAAKgC,eAAgBrE,aAAcA,IACrD,kBAAC,EAAD,MACA,kBAAC,EAAD,MACA,kBAAC,EAAD,OAV8B,kBAAC,EAAD,CAAU7I,MAAOjB,EAAE,yB,GA9CvC4M,cA8DHC,iBAAkBmB,IChEbW,QACW,cAA7B3F,OAAO4F,SAASC,UAEe,UAA7B7F,OAAO4F,SAASC,UAEhB7F,OAAO4F,SAASC,SAASC,MACvB,2D,wCCTNrL,KAGG2B,IAAI2J,MAGJ3J,IAAI4J,MAEJ5J,IAAI6J,MAGJC,KAAK,CACJC,YAAa,KACbC,MAAOnK,4IAAYoK,qBACnBC,KAAM,cACNC,mBAAmB,EAEnBC,cAAe,CACbC,aAAa,KAKnBhM,KAAKiM,GAAG,mBAAmB,SAAA3L,GACzBlB,SAASqG,gBAAgBnG,aAAa,OAAQgB,MAGjCN,GAAf,E,kBCxBAa,EAAM/B,QAENoN,IAASxI,OAEP,kBAAC,WAAD,CAAUyI,SAAU,kBAAC,EAAD,OAClB,kBAAC,GAAD,OAEF/M,SAASgN,eAAe,SFgHpB,kBAAmBC,WACrBA,UAAUC,cAAcC,MAAMC,MAAK,SAAAC,GACjCA,EAAaC,kB","file":"static/js/main.4bed24b2.chunk.js","sourcesContent":["module.exports = __webpack_public_path__ + \"static/media/logo.91554ce9.svg\";","import React from 'react';\nimport { useTranslation } from 'react-i18next';\nimport './navBar.scss';\nimport logo from '../assets/logo.svg';\n\nconst NavBar = () => {\n const { t } = useTranslation();\n\n return (\n \n );\n};\nexport default NavBar;\n","import React from 'react';\nimport { useTranslation } from 'react-i18next';\n\nconst Modal = ({ id, title, footer, children }) => {\n const { t } = useTranslation();\n\n const defaultFooter = (\n \n );\n\n return (\n \n
\n
\n
\n
\n {title}\n
\n \n ×\n \n
\n
{children}
\n
{footer ? footer : defaultFooter}
\n
\n
\n
\n );\n};\n\nexport default Modal;\n","import React from 'react';\n\nconst Select = ({ id, label, row, data, ...rest }) => (\n
\n \n
\n \n
\n
\n);\n\nexport default Select;\n","const DEFAULT_THEME_ID = 'darkly';\n\nconst STORAGE_KEY = 'theme';\n\nconst getThemePath = themeId =>\n `https://stackpath.bootstrapcdn.com/bootswatch/4.4.1/${themeId}/bootstrap.min.css`;\n\nconst availableThemes = [\n { id: 'darkly', name: 'Darkly', themeColor: '#375a7f' },\n { id: 'lux', name: 'Lux', themeColor: '#1a1a1a' }\n];\n\nfunction change(themeId) {\n localStorage.setItem(STORAGE_KEY, themeId);\n apply();\n}\n\nfunction apply() {\n const themeId = getCurrentId();\n const themePath = getThemePath(themeId);\n const themeColor = availableThemes.find(t => t.id === themeId).themeColor;\n\n const linkEl = document.querySelector('link[title=\"theme\"]');\n linkEl.setAttribute('href', themePath);\n\n const metaEl = document.querySelector('meta[name=\"theme-color\"]');\n metaEl.setAttribute('content', themeColor);\n}\n\nfunction getCurrentId() {\n const localId = localStorage.getItem(STORAGE_KEY);\n\n if (localId === '') return DEFAULT_THEME_ID;\n if (availableThemes.filter(t => t.id === localId).length === 0) {\n localStorage.removeItem(STORAGE_KEY);\n return DEFAULT_THEME_ID;\n }\n\n return localId;\n}\n\nexport default {\n availableThemes,\n getCurrentId,\n change,\n apply\n};\n","import React, { useState, useEffect } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport ISO6391 from 'iso-639-1';\nimport localeEmoji from 'locale-emoji';\nimport Modal from '../common/modal';\nimport Select from '../common/select';\nimport theme from '../../theme';\nimport { languages } from '../../config.json';\n\nconst Settings = () => {\n const { t, i18n } = useTranslation();\n\n const [themeId, setThemeId] = useState('');\n\n const languagesData = languages.sort().map(lang => {\n const isoCode = lang.slice(0, 2);\n return {\n id: lang,\n name: `${localeEmoji(lang)} ${ISO6391.getNativeName(isoCode)}`\n };\n });\n\n const handleThemeChange = ({ target }) => {\n const newThemeId = target.value;\n theme.change(newThemeId);\n setThemeId(newThemeId);\n };\n\n useEffect(() => {\n setThemeId(theme.getCurrentId());\n }, []);\n\n return (\n \n handleThemeChange(e)}\n />\n i18n.changeLanguage(e.target.value)}\n />\n \n );\n};\n\nexport default Settings;\n","import React from 'react';\nimport axios from 'axios';\nimport { toast } from 'react-toastify';\nimport { Translation } from 'react-i18next';\n\naxios.defaults.baseURL = process.env.REACT_APP_API_URL;\n\naxios.interceptors.response.use(null, error => {\n const expectedError =\n error.response &&\n error.response.status >= 400 &&\n error.response.status < 500;\n\n // Some errors cause our app to only render a backdrop warning.\n // Queuing toasts would be redundant.\n const hasToastify = document.querySelector('.Toastify');\n\n if (hasToastify) {\n if (!expectedError)\n toast.error({t => t('errorUnexpected')});\n\n // Universal expected error\n if (error.response && error.response.status === 403)\n toast.error({t => t('errorForbidden')});\n }\n\n return Promise.reject(error);\n});\n\nexport default {\n get: axios.get,\n post: axios.post\n};\n","import http from './httpService.js';\n\nconst apiEndpoint = '/player';\n\nfunction body(method, params = null) {\n const body = new FormData();\n body.set('method', method);\n if (params) body.set('params', params);\n return body;\n}\n\nexport function getStatus() {\n return http.get(apiEndpoint);\n}\n\nexport function play() {\n return http.post(apiEndpoint, body('play'));\n}\n\nexport function stop() {\n return http.post(apiEndpoint, body('stop'));\n}\n\nexport function changeVol(delta) {\n return http.post(apiEndpoint, body('change_vol', delta));\n}\n\nexport function playRadio(name) {\n return http.post(apiEndpoint, body('play_radios', name));\n}\n\nexport function playURL(url) {\n return http.post(apiEndpoint, body('play_urls', url));\n}\n","import React, { useState } from 'react';\nimport { toast } from 'react-toastify';\nimport { useTranslation } from 'react-i18next';\nimport Modal from '../common/modal';\nimport { playURL } from '../../services/playerService';\n\nconst URLDialog = () => {\n const [url, setURL] = useState('');\n\n const { t } = useTranslation();\n\n const handleOK = () => {\n if (url === '') return;\n doPlayURL(url);\n setURL('');\n };\n\n const doPlayURL = async url => {\n const errorToastOpts = {\n type: toast.TYPE.ERROR,\n render: t('errorNotFound')\n };\n\n const toastId = toast(t('tryingURL'));\n\n try {\n await playURL(url);\n } catch (ex) {\n if (ex.response && ex.response.status === 400)\n toast.update(toastId, errorToastOpts);\n }\n };\n\n const handleChange = ({ target: input }) => {\n setURL(input.value);\n };\n\n const handleKeyDown = e => {\n if (e.key === 'Enter') handleOK();\n };\n\n const renderFooter = () => (\n \n \n {t('ok')}\n \n setURL('')}\n data-dismiss=\"modal\"\n >\n {t('cancel')}\n \n \n );\n\n return (\n \n \n \n );\n};\n\nexport default URLDialog;\n","import http from './httpService';\n\nconst apiEndpoint = '/config';\n\nexport function getConfig() {\n return http.get(apiEndpoint);\n}\n","import React from 'react';\nimport './loader.scss';\n\nconst Loader = () => (\n
\n
\n Loading...\n
\n
\n);\n\nexport default Loader;\n","import React from 'react';\nimport { useEffect, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport Modal from '../common/modal';\nimport { getConfig } from '../../services/configService';\nimport Loader from '../common/loader';\n\nconst About = () => {\n const { t } = useTranslation();\n\n const [config, setConfig] = useState({});\n const [loading, setLoading] = useState(true);\n\n useEffect(() => {\n async function fetchData() {\n const { data: config } = await getConfig();\n setConfig(config);\n setLoading(false);\n }\n fetchData();\n }, []);\n\n const tableData = [\n { label: t('mpdHost'), value: config.mpd_host },\n { label: t('mpdPort'), value: config.mpd_port },\n { label: t('environment'), value: config.environment },\n { label: t('version'), value: config.version },\n ];\n\n const renderTable = () => {\n if (loading) return ;\n\n return (\n \n \n {tableData.map((item) => (\n \n \n \n \n ))}\n \n
{item.label}{item.value}
\n );\n };\n\n const copyright = (\n
\n

\n \n {t('goToDocs')}\n \n

\n

\n Copyright © 2017-2020 \n {/* Use the default color, as some themes give a different color for links. */}\n \n Rafael Cavalcanti\n \n

\n
\n );\n\n const coffee = (\n
\n

{t('coffee')}

\n \n \n \n
\n );\n\n return (\n \n {renderTable()}\n {coffee}\n {copyright}\n \n );\n};\n\nexport default About;\n","import React from 'react';\nimport './backdrop.scss';\n\nconst Backdrop = ({ title, body }) => {\n const visible = title;\n const bodyStyled = document.body.classList.contains('body--backdrop');\n\n if (visible && !bodyStyled) {\n // Calculate this BEFORE adding the class.\n document.body.style.paddingRight = getScrollbarWidth() + 'px';\n document.body.classList.add('body--backdrop');\n // We need this check because Bootstrap modals also style paddingRight\n } else if (!visible && bodyStyled) {\n document.body.style.paddingRight = 0;\n document.body.classList.remove('body--backdrop');\n }\n\n const classes =\n 'backdrop p-2 text-white' + (visible ? ' backdrop--visible' : '');\n\n // We need text-white on h* tags because some themes override it\n return (\n
\n

{title}

\n
{body}
\n
\n );\n};\n\nconst getScrollbarWidth = () =>\n window.innerWidth - document.documentElement.clientWidth;\n\nexport default Backdrop;\n","import React from 'react';\nimport { useTranslation } from 'react-i18next';\n\nconst PlayerStatus = ({ playerStatus }) => {\n const { playing, title } = playerStatus;\n\n const { t } = useTranslation();\n\n return (\n
\n
\n {playing ? t('playing') : t('stopped')}\n
\n

{title}

\n
\n );\n};\n\nexport default PlayerStatus;\n","import React from 'react';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { faStop, faPlay } from '@fortawesome/free-solid-svg-icons';\nimport { play, stop } from '../../services/playerService';\n\nconst PlayStopControl = ({ playing }) =>\n playing ? (\n \n ) : (\n \n );\n\nexport default PlayStopControl;\n","import React from 'react';\nimport PlayStopControl from './playStopControl';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { faVolumeDown, faVolumeUp } from '@fortawesome/free-solid-svg-icons';\nimport { toast } from 'react-toastify';\nimport { useTranslation } from 'react-i18next';\nimport { changeVol } from '../../services/playerService';\nimport { volTimeout } from '../../config.json';\n\nconst PlayerControls = ({ playerStatus }) => {\n const { t } = useTranslation();\n\n const volDisabled = playerStatus.vol == null;\n\n const handleVolChange = async delta => {\n const { data: vol } = await changeVol(delta);\n\n const toastId = 'vol';\n const toastMsg = `${t('volume')}: ${vol}%`;\n const toastOpts = { toastId, autoClose: volTimeout };\n if (toast.isActive(toastId)) toast.update(toastId, { render: toastMsg });\n else toast.info(toastMsg, toastOpts);\n };\n\n const renderVolButton = (delta, icon, label) => (\n handleVolChange(delta)}\n aria-label={label}\n >\n \n \n );\n\n return (\n e.stopPropagation()}\n >\n {renderVolButton('-5', faVolumeDown, 'Volume down')}\n {renderVolButton('+5', faVolumeUp, 'Volume up')}\n \n \n );\n};\n\nexport default PlayerControls;\n","import React from 'react';\nimport PlayerStatus from './playerStatus';\nimport PlayerControls from './playerControls';\nimport './player.scss';\n\nconst Player = ({ playerStatus }) => {\n const renderLogo = () => (\n \n );\n\n return (\n
\n \n {renderLogo()}\n \n
\n );\n};\n\nexport default Player;\n","import React from 'react';\nimport { useTranslation } from 'react-i18next';\n\nconst SearchBox = ({ value, onChange }) => {\n const { t } = useTranslation();\n\n return (\n onChange(e.target.value)}\n onFocus={() => onChange('')}\n >\n );\n};\n\nexport default SearchBox;\n","import React, { Component } from 'react';\nimport { withTranslation } from 'react-i18next';\nimport { toast } from 'react-toastify';\nimport Loader from './common/loader';\nimport SearchBox from './common/searchBox';\nimport { playRadio } from '../services/playerService';\nimport { getStreams } from '../services/streamsService';\nimport './streams.scss';\n\nclass Streams extends Component {\n state = { streams: {}, loading: true, query: '' };\n\n async componentDidMount() {\n const { data: streams } = await getStreams();\n this.setState({ streams, loading: false });\n }\n\n isPlaying = name => {\n return (\n name === this.props.playerStatus.title && this.props.playerStatus.playing\n );\n };\n\n handleItemClick = async name => {\n const { t, onBackdrop } = this.props;\n\n if (this.isPlaying(name)) return;\n\n onBackdrop(t('tunning'), name);\n try {\n await playRadio(name);\n } catch (ex) {\n if (ex.response && ex.response.status === 400)\n toast.error(t('errorNotFound'));\n }\n };\n\n getItemClasses = name => {\n const classes = 'streams__item ellipsis list-group-item ';\n return this.isPlaying(name)\n ? classes + 'active'\n : classes + 'list-group-item-action';\n };\n\n handleSearch = query => {\n this.setState({ query });\n };\n\n filteredStreams() {\n const { streams, query } = this.state;\n\n if (query === '') return streams;\n\n let filtered = {};\n for (let k in streams) {\n if (k.toLowerCase().includes(query.toLowerCase()) && !streams[k]) {\n filtered[k] = streams[k];\n }\n }\n return filtered;\n }\n\n renderList() {\n const streams = this.filteredStreams();\n\n if (Object.keys(streams).length === 0)\n return

{this.props.t('noStreams')}

;\n\n return (\n
    \n {Object.keys(streams).map(name =>\n streams[name] ? (\n
  • \n {name}\n
  • \n ) : (\n this.handleItemClick(name)}\n >\n {name}\n \n )\n )}\n
\n );\n }\n\n render() {\n if (this.state.loading) return ;\n\n return (\n
\n \n {this.renderList()}\n
\n );\n }\n}\n\nexport default withTranslation()(Streams);\n","import http from './httpService';\n\nconst apiEndpoint = '/streams';\n\nexport function getStreams() {\n return http.get(apiEndpoint);\n}\n","import React from 'react';\nimport PlayStopControl from './playStopControl';\nimport './miniPlayer.scss';\n\nconst MiniPlayer = ({ playerStatus }) => {\n const { title, playing } = playerStatus;\n\n return (\n
\n
\n {title}\n
\n e.stopPropagation()}\n >\n \n
\n \n );\n};\n\nexport default MiniPlayer;\n","import React, { Component } from 'react';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { faChevronDown, faChevronUp } from '@fortawesome/free-solid-svg-icons';\nimport MiniPlayer from './player/miniPlayer';\nimport Player from './player/player';\nimport './drawer.scss';\n\nclass Drawer extends Component {\n state = { open: false };\n\n toggle = () => {\n this.setState({ open: !this.state.open });\n };\n\n handleClick = () => {\n this.toggle();\n };\n\n handleTouchStart = (e) => {\n // Ignore multitouch\n if (e.touches.length > 1) return this.setState({ touchStartY: null });\n\n this.setState({ touchStartY: e.touches[0].clientY });\n };\n\n handleTouchMove = (e) => {\n const { open, touchStartY } = this.state;\n\n // Ignore multitouch\n if (touchStartY === null || e.touches.length > 1) return;\n\n const touchEndY = e.changedTouches[0].clientY;\n const touchUp = touchEndY < touchStartY;\n const touchDown = touchEndY > touchStartY;\n\n if (touchDown && open) this.toggle();\n else if (touchUp && !open) this.toggle();\n };\n\n renderToggleButton = () => (\n \n \n \n );\n\n render() {\n const { playerStatus } = this.props;\n const { open } = this.state;\n\n let classes = 'drawer fixed-bottom bg-secondary shadow-lg p-2';\n\n if (open) {\n classes += ' drawer--open';\n document.body.classList.add('body--drawer');\n } else document.body.classList.remove('body--drawer');\n\n return (\n \n {this.renderToggleButton()}\n {open ? (\n \n ) : (\n \n )}\n \n );\n }\n}\n\nexport default Drawer;\n","import React from 'react';\nimport Player from './player/player';\nimport Streams from './streams';\nimport Drawer from './drawer';\nimport './main.scss';\n\nconst Main = ({ playerStatus, onBackdrop }) => {\n return (\n
\n \n
\n \n \n
\n
\n );\n};\n\nexport default Main;\n","import React, { Component } from 'react';\nimport { ToastContainer } from 'react-toastify';\nimport { withTranslation } from 'react-i18next';\nimport NavBar from './components/navBar';\nimport Settings from './components/modals/settings';\nimport URLDialog from './components/modals/urlDialog';\nimport About from './components/modals/about';\nimport Loader from './components/common/loader';\nimport Backdrop from './components/common/backdrop';\nimport Main from './components/main';\nimport { getStatus } from './services/playerService';\nimport { updateInterval, backdropTimeout } from './config.json';\nimport 'react-toastify/dist/ReactToastify.css';\n\nclass App extends Component {\n state = {\n playerStatus: {},\n loading: true,\n networkError: false,\n backdrop: {},\n };\n\n componentDidMount() {\n this.updatePlayerStatus();\n }\n\n componentDidUpdate() {\n this.setDocumentTitle();\n }\n\n async updatePlayerStatus() {\n try {\n const { data: playerStatus } = await getStatus();\n this.setState({ playerStatus, loading: false, networkError: false });\n } catch (ex) {\n this.setState({ loading: false, networkError: true });\n }\n\n setTimeout(() => this.updatePlayerStatus(), updateInterval);\n }\n\n handleBackdrop = (title, body = '') => {\n this.setState({ backdrop: { title, body } });\n setTimeout(() => this.setState({ backdrop: {} }), backdropTimeout);\n };\n\n setDocumentTitle = () => {\n const { playerStatus: status, networkError } = this.state;\n\n if (!networkError && status.playing)\n document.title = 'PiFi 🔊 ' + status.title;\n else document.title = 'PiFi Radio';\n };\n\n render() {\n const { loading, networkError, backdrop, playerStatus } = this.state;\n const { t } = this.props;\n\n if (networkError) return ;\n if (loading) return ;\n if (!playerStatus.con_mpd) return ;\n\n return (\n
\n \n \n \n
\n \n \n \n
\n );\n }\n}\n\nexport default withTranslation()(App);\n","// This optional code is used to register a service worker.\n// register() is not called by default.\n\n// This lets the app load faster on subsequent visits in production, and gives\n// it offline capabilities. However, it also means that developers (and users)\n// will only see deployed updates on subsequent visits to a page, after all the\n// existing tabs open on the page have been closed, since previously cached\n// resources are updated in the background.\n\n// To learn more about the benefits of this model and instructions on how to\n// opt-in, read https://bit.ly/CRA-PWA\n\nconst isLocalhost = Boolean(\n window.location.hostname === 'localhost' ||\n // [::1] is the IPv6 localhost address.\n window.location.hostname === '[::1]' ||\n // 127.0.0.0/8 are considered localhost for IPv4.\n window.location.hostname.match(\n /^127(?:\\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/\n )\n);\n\nexport function register(config) {\n if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {\n // The URL constructor is available in all browsers that support SW.\n const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);\n if (publicUrl.origin !== window.location.origin) {\n // Our service worker won't work if PUBLIC_URL is on a different origin\n // from what our page is served on. This might happen if a CDN is used to\n // serve assets; see https://github.com/facebook/create-react-app/issues/2374\n return;\n }\n\n window.addEventListener('load', () => {\n const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;\n\n if (isLocalhost) {\n // This is running on localhost. Let's check if a service worker still exists or not.\n checkValidServiceWorker(swUrl, config);\n\n // Add some additional logging to localhost, pointing developers to the\n // service worker/PWA documentation.\n navigator.serviceWorker.ready.then(() => {\n console.log(\n 'This web app is being served cache-first by a service ' +\n 'worker. To learn more, visit https://bit.ly/CRA-PWA'\n );\n });\n } else {\n // Is not localhost. Just register service worker\n registerValidSW(swUrl, config);\n }\n });\n }\n}\n\nfunction registerValidSW(swUrl, config) {\n navigator.serviceWorker\n .register(swUrl)\n .then(registration => {\n registration.onupdatefound = () => {\n const installingWorker = registration.installing;\n if (installingWorker == null) {\n return;\n }\n installingWorker.onstatechange = () => {\n if (installingWorker.state === 'installed') {\n if (navigator.serviceWorker.controller) {\n // At this point, the updated precached content has been fetched,\n // but the previous service worker will still serve the older\n // content until all client tabs are closed.\n console.log(\n 'New content is available and will be used when all ' +\n 'tabs for this page are closed. See https://bit.ly/CRA-PWA.'\n );\n\n // Execute callback\n if (config && config.onUpdate) {\n config.onUpdate(registration);\n }\n } else {\n // At this point, everything has been precached.\n // It's the perfect time to display a\n // \"Content is cached for offline use.\" message.\n console.log('Content is cached for offline use.');\n\n // Execute callback\n if (config && config.onSuccess) {\n config.onSuccess(registration);\n }\n }\n }\n };\n };\n })\n .catch(error => {\n console.error('Error during service worker registration:', error);\n });\n}\n\nfunction checkValidServiceWorker(swUrl, config) {\n // Check if the service worker can be found. If it can't reload the page.\n fetch(swUrl, {\n headers: { 'Service-Worker': 'script' }\n })\n .then(response => {\n // Ensure service worker exists, and that we really are getting a JS file.\n const contentType = response.headers.get('content-type');\n if (\n response.status === 404 ||\n (contentType != null && contentType.indexOf('javascript') === -1)\n ) {\n // No service worker found. Probably a different app. Reload the page.\n navigator.serviceWorker.ready.then(registration => {\n registration.unregister().then(() => {\n window.location.reload();\n });\n });\n } else {\n // Service worker found. Proceed as normal.\n registerValidSW(swUrl, config);\n }\n })\n .catch(() => {\n console.log(\n 'No internet connection found. App is running in offline mode.'\n );\n });\n}\n\nexport function unregister() {\n if ('serviceWorker' in navigator) {\n navigator.serviceWorker.ready.then(registration => {\n registration.unregister();\n });\n }\n}\n","import i18n from 'i18next';\nimport { initReactI18next } from 'react-i18next';\n\nimport Backend from 'i18next-http-backend';\nimport LanguageDetector from 'i18next-browser-languagedetector';\n// not like to use this?\n// have a look at the Quick start guide\n// for passing in lng and translations on init\n\ni18n\n // load translation using xhr -> see /public/locales\n // learn more: https://github.com/i18next/i18next-xhr-backend\n .use(Backend)\n // detect user language\n // learn more: https://github.com/i18next/i18next-browser-languageDetector\n .use(LanguageDetector)\n // pass the i18n instance to react-i18next.\n .use(initReactI18next)\n // init i18next\n // for all options read: https://www.i18next.com/overview/configuration-options\n .init({\n fallbackLng: 'en',\n debug: process.env.REACT_APP_I18N_DEBUG,\n load: 'currentOnly',\n returnEmptyString: false,\n\n interpolation: {\n escapeValue: false // not needed for react as it escapes by default\n }\n });\n\n// Set language on html tag\ni18n.on('languageChanged', lang => {\n document.documentElement.setAttribute('lang', lang);\n});\n\nexport default i18n;\n","import React, { Suspense } from 'react';\nimport ReactDOM from 'react-dom';\nimport App from './App';\nimport Loader from './components/common/loader';\nimport * as serviceWorker from './serviceWorker';\nimport './i18n';\nimport theme from './theme';\nimport './index.scss';\n// Bootstrap dependencies\nimport 'jquery/dist/jquery.min.js';\nimport 'bootstrap/dist/js/bootstrap.js';\n\ntheme.apply();\n\nReactDOM.render(\n // Suspense needed for i18n\n }>\n \n ,\n document.getElementById('root')\n);\n\n// If you want your app to work offline and load faster, you can change\n// unregister() to register() below. Note this comes with some pitfalls.\n// Learn more about service workers: https://bit.ly/CRA-PWA\nserviceWorker.unregister();\n"],"sourceRoot":""}
@@ -1,3 +1,3 @@
1
1
  module PiFi
2
- VERSION = "0.4.6".freeze
2
+ VERSION = "0.4.7".freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pifi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.6
4
+ version: 0.4.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rafael Cavalcanti
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-07-06 00:00:00.000000000 Z
11
+ date: 2020-07-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sinatra
@@ -114,6 +114,7 @@ files:
114
114
  - lib/pifi/public/favicon-32x32.png
115
115
  - lib/pifi/public/favicon.ico
116
116
  - lib/pifi/public/index.html
117
+ - lib/pifi/public/locales/de-DE/translation.json
117
118
  - lib/pifi/public/locales/en/translation.json
118
119
  - lib/pifi/public/locales/fr-FR/translation.json
119
120
  - lib/pifi/public/locales/nl-NL/translation.json
@@ -125,7 +126,7 @@ files:
125
126
  - lib/pifi/public/mstile-310x150.png
126
127
  - lib/pifi/public/mstile-310x310.png
127
128
  - lib/pifi/public/mstile-70x70.png
128
- - lib/pifi/public/precache-manifest.2c90c6fbdaaa7d18bbe102974b424a55.js
129
+ - lib/pifi/public/precache-manifest.9dcd6ace3f74e77109acd0095f020876.js
129
130
  - lib/pifi/public/robots.txt
130
131
  - lib/pifi/public/safari-pinned-tab.svg
131
132
  - lib/pifi/public/service-worker.js
@@ -136,8 +137,8 @@ files:
136
137
  - lib/pifi/public/static/js/2.6c0ded8a.chunk.js
137
138
  - lib/pifi/public/static/js/2.6c0ded8a.chunk.js.LICENSE.txt
138
139
  - lib/pifi/public/static/js/2.6c0ded8a.chunk.js.map
139
- - lib/pifi/public/static/js/main.8e5c89f3.chunk.js
140
- - lib/pifi/public/static/js/main.8e5c89f3.chunk.js.map
140
+ - lib/pifi/public/static/js/main.4bed24b2.chunk.js
141
+ - lib/pifi/public/static/js/main.4bed24b2.chunk.js.map
141
142
  - lib/pifi/public/static/js/runtime-main.5aae5a31.js
142
143
  - lib/pifi/public/static/js/runtime-main.5aae5a31.js.map
143
144
  - lib/pifi/public/static/media/getFetch.5e98861f.cjs
@@ -1,2 +0,0 @@
1
- (this.webpackJsonppifi_frontend=this.webpackJsonppifi_frontend||[]).push([[0],{13:function(e){e.exports=JSON.parse('{"b":["en","fr-FR","nl-NL","pl-PL","pt-BR"],"c":1000,"a":2500,"d":3000}')},30:function(e,t,a){e.exports=a.p+"static/media/logo.91554ce9.svg"},50:function(e,t,a){e.exports=a(94)},56:function(e,t,a){},79:function(e,t,a){},80:function(e,t,a){},83:function(e,t,a){},84:function(e,t,a){},85:function(e,t,a){},86:function(e,t,a){},87:function(e,t,a){},89:function(e,t,a){},94:function(e,t,a){"use strict";a.r(t);var n=a(0),r=a.n(n),l=a(12),o=a.n(l),c=a(2),s=a.n(c),i=a(8),u=a(9),m=a(10),d=a(19),p=a(20),b=a(3),f=a(98),v=a(26),h=(a(56),a(30)),g=a.n(h),y=function(){var e=Object(v.a)().t;return r.a.createElement("nav",{className:"navbar navbar-expand-sm navbar-dark bg-primary"},r.a.createElement("div",{className:"container"},r.a.createElement("a",{className:"navbar-brand",href:"/"},r.a.createElement("img",{src:g.a,width:"30",height:"30",className:"d-inline-block align-text-bottom mr-2",alt:""}),"PiFi Radio"),r.a.createElement("button",{className:"navbar-toggler",type:"button","data-toggle":"collapse","data-target":"#navbarNavAltMarkup","aria-controls":"navbarNavAltMarkup","aria-expanded":"false","aria-label":"Toggle navigation"},r.a.createElement("span",{className:"navbar-toggler-icon"})),r.a.createElement("div",{className:"collapse navbar-collapse",id:"navbarNavAltMarkup"},r.a.createElement("div",{className:"navbar-nav pt-1 ml-2"},r.a.createElement("button",{className:"btn btn-link nav-link","data-toggle":"modal","data-target":"#url-dialog"},e("playURL")),r.a.createElement("button",{className:"btn btn-link nav-link","data-toggle":"modal","data-target":"#settings"},e("settings")),r.a.createElement("button",{className:"btn btn-link nav-link","data-toggle":"modal","data-target":"#about"},e("about"))))))},E=a(15),k=a(48),N=a(44),S=a.n(N),w=function(e){var t=e.id,a=e.title,n=e.footer,l=e.children,o=Object(v.a)().t,c=r.a.createElement("button",{className:"btn btn-secondary","data-dismiss":"modal"},o("close"));return r.a.createElement("div",{className:"modal fade",id:t,tabIndex:"-1",role:"dialog","aria-labelledby":"staticBackdropLabel","aria-hidden":"true"},r.a.createElement("div",{className:"modal-dialog",role:"document"},r.a.createElement("div",{className:"modal-content"},r.a.createElement("div",{className:"modal-header"},r.a.createElement("h5",{className:"modal-title",id:"staticBackdropLabel"},a),r.a.createElement("button",{type:"button",className:"close","data-dismiss":"modal","aria-label":"Close"},r.a.createElement("span",{"aria-hidden":"true"},"\xd7"))),r.a.createElement("div",{className:"modal-body"},l),r.a.createElement("div",{className:"modal-footer"},n||c))))},O=a(49),j=function(e){var t=e.id,a=e.label,n=e.row,l=e.data,o=Object(O.a)(e,["id","label","row","data"]);return r.a.createElement("div",{className:n?"form-group row":"form-group"},r.a.createElement("label",{htmlFor:t,className:"col-sm-2 col-form-label"},a),r.a.createElement("div",{className:"col-sm-10"},r.a.createElement("select",Object.assign({id:t,className:"form-control"},o),l.map((function(e){return r.a.createElement("option",{key:e.id||e,value:e.id||e},e.name||e)})))))},C=[{id:"darkly",name:"Darkly",themeColor:"#375a7f"},{id:"lux",name:"Lux",themeColor:"#1a1a1a"}];function _(){var e=x(),t=function(e){return"https://stackpath.bootstrapcdn.com/bootswatch/4.4.1/".concat(e,"/bootstrap.min.css")}(e),a=C.find((function(t){return t.id===e})).themeColor;document.querySelector('link[title="theme"]').setAttribute("href",t),document.querySelector('meta[name="theme-color"]').setAttribute("content",a)}function x(){var e=localStorage.getItem("theme");return""===e?"darkly":0===C.filter((function(t){return t.id===e})).length?(localStorage.removeItem("theme"),"darkly"):e}var T={availableThemes:C,getCurrentId:x,change:function(e){localStorage.setItem("theme",e),_()},apply:_},L=a(13),P=function(){var e=Object(v.a)(),t=e.t,a=e.i18n,l=Object(n.useState)(""),o=Object(E.a)(l,2),c=o[0],s=o[1],i=L.b.sort().map((function(e){var t=e.slice(0,2);return{id:e,name:"".concat(S()(e)," ").concat(k.a.getNativeName(t))}}));return Object(n.useEffect)((function(){s(T.getCurrentId())}),[]),r.a.createElement(w,{id:"settings",title:t("settings")},r.a.createElement(j,{id:"theme-select",label:t("theme"),data:T.availableThemes,row:!0,value:c,onChange:function(e){return function(e){var t=e.target.value;T.change(t),s(t)}(e)}}),r.a.createElement(j,{id:"language-select",label:t("language"),data:i,row:!0,value:a.language,onChange:function(e){return a.changeLanguage(e.target.value)}}))},R=a(24),A=a.n(R),B=a(97);A.a.defaults.baseURL="/api",A.a.interceptors.response.use(null,(function(e){var t=e.response&&e.response.status>=400&&e.response.status<500;return document.querySelector(".Toastify")&&(t||b.b.error(r.a.createElement(B.a,null,(function(e){return e("errorUnexpected")}))),e.response&&403===e.response.status&&b.b.error(r.a.createElement(B.a,null,(function(e){return e("errorForbidden")})))),Promise.reject(e)}));var D={get:A.a.get,post:A.a.post};function I(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null,a=new FormData;return a.set("method",e),t&&a.set("params",t),a}function F(){return D.post("/player",I("play"))}function U(){return D.post("/player",I("stop"))}function M(e){return D.post("/player",I("change_vol",e))}function q(e){return D.post("/player",I("play_radios",e))}function W(e){return D.post("/player",I("play_urls",e))}var Y=function(){var e=Object(n.useState)(""),t=Object(E.a)(e,2),a=t[0],l=t[1],o=Object(v.a)().t,c=function(){""!==a&&(u(a),l(""))},u=function(){var e=Object(i.a)(s.a.mark((function e(t){var a,n;return s.a.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return a={type:b.b.TYPE.ERROR,render:o("errorNotFound")},n=Object(b.b)(o("tryingURL")),e.prev=2,e.next=5,W(t);case 5:e.next=10;break;case 7:e.prev=7,e.t0=e.catch(2),e.t0.response&&400===e.t0.response.status&&b.b.update(n,a);case 10:case"end":return e.stop()}}),e,null,[[2,7]])})));return function(t){return e.apply(this,arguments)}}();return r.a.createElement(w,{id:"url-dialog",title:o("playURL"),footer:r.a.createElement(r.a.Fragment,null,r.a.createElement("button",{className:"btn btn-primary","data-dismiss":"modal",onClick:c},o("ok")),r.a.createElement("button",{className:"btn btn-secondary",onClick:function(){return l("")},"data-dismiss":"modal"},o("cancel")))},r.a.createElement("input",{className:"form-control mb-4",type:"text",placeholder:"URL",value:a,onChange:function(e){var t=e.target;l(t.value)},onKeyDown:function(e){"Enter"===e.key&&c()}}))};function K(){return D.get("/config")}a(79);var V=function(){return r.a.createElement("div",{className:"loader"},r.a.createElement("div",{className:"spinner-border",role:"status"},r.a.createElement("span",{className:"sr-only"},"Loading...")))},H=function(){var e=Object(v.a)().t,t=Object(n.useState)({}),a=Object(E.a)(t,2),l=a[0],o=a[1],c=Object(n.useState)(!0),u=Object(E.a)(c,2),m=u[0],d=u[1];Object(n.useEffect)((function(){function e(){return(e=Object(i.a)(s.a.mark((function e(){var t,a;return s.a.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,K();case 2:t=e.sent,a=t.data,o(a),d(!1);case 6:case"end":return e.stop()}}),e)})))).apply(this,arguments)}!function(){e.apply(this,arguments)}()}),[]);var p=[{label:e("mpdHost"),value:l.mpd_host},{label:e("mpdPort"),value:l.mpd_port},{label:e("environment"),value:l.environment},{label:e("version"),value:l.version}],b=r.a.createElement("div",{className:"copyright small mt-5"},r.a.createElement("p",null,r.a.createElement("a",{href:"https://rafaelc.org/pifi",target:"_blank",rel:"noopener noreferrer",style:{color:"inherit"}},e("goToDocs"))),r.a.createElement("p",null,"Copyright \xa9 2017-2020\xa0",r.a.createElement("a",{href:"https://rafaelc.org/",target:"_blank",rel:"noopener noreferrer",style:{color:"inherit"}},"Rafael Cavalcanti"))),f=r.a.createElement("div",{className:"coffee mt-5"},r.a.createElement("p",null,e("coffee")),r.a.createElement("a",{href:"https://www.buymeacoffee.com/rafaelc",target:"_blank",rel:"noopener noreferrer"},r.a.createElement("img",{src:"https://cdn.buymeacoffee.com/buttons/default-blue.png",alt:"Buy Me A Coffee",style:{height:51,width:217}})));return r.a.createElement(w,{id:"about",title:e("about")},m?r.a.createElement(V,null):r.a.createElement("table",{className:"table"},r.a.createElement("tbody",null,p.map((function(e){return r.a.createElement("tr",{key:e.label},r.a.createElement("th",{scope:"row"},e.label),r.a.createElement("td",null,e.value))})))),f,b)},J=(a(80),function(){return window.innerWidth-document.documentElement.clientWidth}),G=function(e){var t=e.title,a=e.body,n=t,l=document.body.classList.contains("body--backdrop");n&&!l?(document.body.style.paddingRight=J()+"px",document.body.classList.add("body--backdrop")):!n&&l&&(document.body.style.paddingRight=0,document.body.classList.remove("body--backdrop"));var o="backdrop p-2 text-white"+(n?" backdrop--visible":"");return r.a.createElement("div",{className:o},r.a.createElement("h3",{className:"text-white"},t),r.a.createElement("h5",{className:"text-white"},a))},$=function(e){var t=e.playerStatus,a=t.playing,n=t.title,l=Object(v.a)().t;return r.a.createElement("div",{className:"text-center w-100"},r.a.createElement("h5",{className:"small text-uppercase"},l(a?"playing":"stopped")),r.a.createElement("h3",{className:"ellipsis"},n))},z=a(14),Q=a(11),X=function(e){return e.playing?r.a.createElement("button",{className:"btn btn-danger",onClick:U,"aria-label":"Stop"},r.a.createElement(z.a,{icon:Q.d})):r.a.createElement("button",{className:"btn btn-dark",onClick:F,"aria-label":"Play"},r.a.createElement(z.a,{icon:Q.c}))},Z=function(e){var t=e.playerStatus,a=Object(v.a)().t,n=null==t.vol,l=function(){var e=Object(i.a)(s.a.mark((function e(t){var n,r,l,o;return s.a.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,M(t);case 2:n=e.sent,r=n.data,"vol",l="".concat(a("volume"),": ").concat(r,"%"),o={toastId:"vol",autoClose:L.d},b.b.isActive("vol")?b.b.update("vol",{render:l}):b.b.info(l,o);case 8:case"end":return e.stop()}}),e)})));return function(t){return e.apply(this,arguments)}}(),o=function(e,t,a){return r.a.createElement("button",{className:"btn btn-dark p-3",disabled:n,onClick:function(){return l(e)},"aria-label":a},r.a.createElement(z.a,{icon:t}))};return r.a.createElement("div",{className:"player-controls btn-group w-100 m-2",onClick:function(e){return e.stopPropagation()}},o("-5",Q.e,"Volume down"),o("+5",Q.f,"Volume up"),r.a.createElement(X,{playing:t.playing}))},ee=(a(83),function(e){var t=e.playerStatus;return r.a.createElement("div",{className:"player"},r.a.createElement($,{playerStatus:t}),r.a.createElement("img",{src:a(30),alt:"Logo",className:"player-logo m-4"}),r.a.createElement(Z,{playerStatus:t}))}),te=function(e){var t=e.value,a=e.onChange,n=Object(v.a)().t;return r.a.createElement("input",{className:"form-control mb-4",type:"text",id:"query",placeholder:n("search"),"aria-label":n("search"),autoComplete:"off",value:t,onChange:function(e){return a(e.target.value)},onFocus:function(){return a("")}})};a(84);var ae=function(e){Object(p.a)(a,e);var t=Object(d.a)(a);function a(){var e;Object(u.a)(this,a);for(var n=arguments.length,r=new Array(n),l=0;l<n;l++)r[l]=arguments[l];return(e=t.call.apply(t,[this].concat(r))).state={streams:{},loading:!0,query:""},e.isPlaying=function(t){return t===e.props.playerStatus.title&&e.props.playerStatus.playing},e.handleItemClick=function(){var t=Object(i.a)(s.a.mark((function t(a){var n,r,l;return s.a.wrap((function(t){for(;;)switch(t.prev=t.next){case 0:if(n=e.props,r=n.t,l=n.onBackdrop,!e.isPlaying(a)){t.next=3;break}return t.abrupt("return");case 3:return l(r("tunning"),a),t.prev=4,t.next=7,q(a);case 7:t.next=12;break;case 9:t.prev=9,t.t0=t.catch(4),t.t0.response&&400===t.t0.response.status&&b.b.error(r("errorNotFound"));case 12:case"end":return t.stop()}}),t,null,[[4,9]])})));return function(e){return t.apply(this,arguments)}}(),e.getItemClasses=function(t){var a="streams__item ellipsis list-group-item ";return e.isPlaying(t)?a+"active":a+"list-group-item-action"},e.handleSearch=function(t){e.setState({query:t})},e}return Object(m.a)(a,[{key:"componentDidMount",value:function(){var e=Object(i.a)(s.a.mark((function e(){var t,a;return s.a.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,D.get("/streams");case 2:t=e.sent,a=t.data,this.setState({streams:a,loading:!1});case 5:case"end":return e.stop()}}),e,this)})));return function(){return e.apply(this,arguments)}}()},{key:"filteredStreams",value:function(){var e=this.state,t=e.streams,a=e.query;if(""===a)return t;var n={};for(var r in t)r.toLowerCase().includes(a.toLowerCase())&&!t[r]&&(n[r]=t[r]);return n}},{key:"renderList",value:function(){var e=this,t=this.filteredStreams();return 0===Object.keys(t).length?r.a.createElement("h4",{className:"p-4"},this.props.t("noStreams")):r.a.createElement("ul",{className:"list-group list-group-flush"},Object.keys(t).map((function(a){return t[a]?r.a.createElement("li",{className:"streams__header ellipsis",key:a},a):r.a.createElement("li",{className:e.getItemClasses(a),key:a,onClick:function(){return e.handleItemClick(a)}},a)})))}},{key:"render",value:function(){return this.state.loading?r.a.createElement(V,null):r.a.createElement("div",{className:"streams"},r.a.createElement(te,{value:this.state.query,onChange:this.handleSearch}),this.renderList())}}]),a}(n.Component),ne=Object(f.a)()(ae),re=(a(85),function(e){var t=e.playerStatus,a=t.title,n=t.playing;return r.a.createElement("div",{className:"mini-player"},r.a.createElement("div",{className:"mini-player__left ellipsis"},a),r.a.createElement("div",{className:"mini-player__right",onClick:function(e){return e.stopPropagation()}},r.a.createElement(X,{playing:n})))}),le=(a(86),function(e){Object(p.a)(a,e);var t=Object(d.a)(a);function a(){var e;Object(u.a)(this,a);for(var n=arguments.length,l=new Array(n),o=0;o<n;o++)l[o]=arguments[o];return(e=t.call.apply(t,[this].concat(l))).state={open:!1},e.toggle=function(){e.setState({open:!e.state.open})},e.handleClick=function(){e.toggle()},e.handleTouchStart=function(t){if(t.touches.length>1)return e.setState({touchStartY:null});e.setState({touchStartY:t.touches[0].clientY})},e.handleTouchMove=function(t){var a=e.state,n=a.open,r=a.touchStartY;if(!(null===r||t.touches.length>1)){var l=t.changedTouches[0].clientY;(l>r&&n||l<r&&!n)&&e.toggle()}},e.renderToggleButton=function(){return r.a.createElement("button",{className:"drawer__toggler btn btn-primary-outline","aria-label":"Toggle player"},r.a.createElement(z.a,{icon:e.state.open?Q.a:Q.b,className:"fa-lg"}))},e}return Object(m.a)(a,[{key:"render",value:function(){var e=this.props.playerStatus,t=this.state.open,a="drawer fixed-bottom bg-secondary shadow-lg p-2";return t?(a+=" drawer--open",document.body.classList.add("body--drawer")):document.body.classList.remove("body--drawer"),r.a.createElement("div",{className:a,onClick:this.handleClick,onTouchStart:this.handleTouchStart,onTouchMove:this.handleTouchMove},this.renderToggleButton(),t?r.a.createElement(ee,{playerStatus:e}):r.a.createElement(re,{playerStatus:e}))}}]),a}(n.Component)),oe=(a(87),function(e){var t=e.playerStatus,a=e.onBackdrop;return r.a.createElement("main",{className:"main"},r.a.createElement(le,{playerStatus:t}),r.a.createElement("div",{className:"main__primary container"},r.a.createElement(ne,{onBackdrop:a,playerStatus:t}),r.a.createElement(ee,{playerStatus:t})))}),ce=(a(88),function(e){Object(p.a)(a,e);var t=Object(d.a)(a);function a(){var e;Object(u.a)(this,a);for(var n=arguments.length,r=new Array(n),l=0;l<n;l++)r[l]=arguments[l];return(e=t.call.apply(t,[this].concat(r))).state={playerStatus:{},loading:!0,networkError:!1,backdrop:{}},e.handleBackdrop=function(t){var a=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";e.setState({backdrop:{title:t,body:a}}),setTimeout((function(){return e.setState({backdrop:{}})}),L.a)},e.setDocumentTitle=function(){var t=e.state,a=t.playerStatus;!t.networkError&&a.playing?document.title="PiFi \ud83d\udd0a "+a.title:document.title="PiFi Radio"},e}return Object(m.a)(a,[{key:"componentDidMount",value:function(){this.updatePlayerStatus()}},{key:"componentDidUpdate",value:function(){this.setDocumentTitle()}},{key:"updatePlayerStatus",value:function(){var e=Object(i.a)(s.a.mark((function e(){var t,a,n=this;return s.a.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.prev=0,e.next=3,D.get("/player");case 3:t=e.sent,a=t.data,this.setState({playerStatus:a,loading:!1,networkError:!1}),e.next=11;break;case 8:e.prev=8,e.t0=e.catch(0),this.setState({loading:!1,networkError:!0});case 11:setTimeout((function(){return n.updatePlayerStatus()}),L.c);case 12:case"end":return e.stop()}}),e,this,[[0,8]])})));return function(){return e.apply(this,arguments)}}()},{key:"render",value:function(){var e=this.state,t=e.loading,a=e.networkError,n=e.backdrop,l=e.playerStatus,o=this.props.t;return a?r.a.createElement(G,{title:o("errorNetwork")}):t?r.a.createElement(V,null):l.con_mpd?r.a.createElement("div",{className:"app"},r.a.createElement(b.a,{pauseOnFocusLoss:!1}),r.a.createElement(G,{title:n.title,body:n.body}),r.a.createElement(y,null),r.a.createElement(oe,{onBackdrop:this.handleBackdrop,playerStatus:l}),r.a.createElement(Y,null),r.a.createElement(P,null),r.a.createElement(H,null)):r.a.createElement(G,{title:o("disconnectedMPD")})}}]),a}(n.Component)),se=Object(f.a)()(ce);Boolean("localhost"===window.location.hostname||"[::1]"===window.location.hostname||window.location.hostname.match(/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/));var ie=a(29),ue=a(21),me=a(47),de=a(46);ie.a.use(me.a).use(de.a).use(ue.f).init({fallbackLng:"en",debug:Object({NODE_ENV:"production",PUBLIC_URL:"",WDS_SOCKET_HOST:void 0,WDS_SOCKET_PATH:void 0,WDS_SOCKET_PORT:void 0,REACT_APP_API_URL:"/api"}).REACT_APP_I18N_DEBUG,load:"currentOnly",returnEmptyString:!1,interpolation:{escapeValue:!1}}),ie.a.on("languageChanged",(function(e){document.documentElement.setAttribute("lang",e)}));ie.a,a(89),a(90),a(91);T.apply(),o.a.render(r.a.createElement(n.Suspense,{fallback:r.a.createElement(V,null)},r.a.createElement(se,null)),document.getElementById("root")),"serviceWorker"in navigator&&navigator.serviceWorker.ready.then((function(e){e.unregister()}))}},[[50,1,2]]]);
2
- //# sourceMappingURL=main.8e5c89f3.chunk.js.map