pifi 0.4.6 → 0.4.12
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 +4 -4
- data/INSTALL.md +1 -1
- data/README.md +19 -7
- data/lib/pifi/public/asset-manifest.json +10 -10
- data/lib/pifi/public/index.html +1 -1
- data/lib/pifi/public/locales/de-DE/translation.json +28 -0
- data/lib/pifi/public/locales/{en → en-US}/translation.json +1 -1
- data/lib/pifi/public/locales/fr-FR/translation.json +23 -23
- data/lib/pifi/public/locales/nl-NL/translation.json +1 -1
- data/lib/pifi/public/locales/pl-PL/translation.json +1 -1
- data/lib/pifi/public/locales/pt-BR/translation.json +1 -1
- data/lib/pifi/public/{precache-manifest.2c90c6fbdaaa7d18bbe102974b424a55.js → precache-manifest.7acd7ef058033a1ded72e03e499bd33f.js} +8 -8
- data/lib/pifi/public/service-worker.js +1 -1
- data/lib/pifi/public/static/css/2.1781c263.chunk.css +2 -0
- data/lib/pifi/public/static/css/2.1781c263.chunk.css.map +1 -0
- data/lib/pifi/public/static/css/main.48912641.chunk.css +2 -0
- data/lib/pifi/public/static/css/main.48912641.chunk.css.map +1 -0
- data/lib/pifi/public/static/js/main.11609572.chunk.js +2 -0
- data/lib/pifi/public/static/js/main.11609572.chunk.js.map +1 -0
- data/lib/pifi/version.rb +1 -1
- metadata +11 -10
- data/lib/pifi/public/static/css/2.d34346ea.chunk.css +0 -2
- data/lib/pifi/public/static/css/2.d34346ea.chunk.css.map +0 -1
- data/lib/pifi/public/static/css/main.221e80d3.chunk.css +0 -2
- data/lib/pifi/public/static/css/main.221e80d3.chunk.css.map +0 -1
- data/lib/pifi/public/static/js/main.8e5c89f3.chunk.js +0 -2
- data/lib/pifi/public/static/js/main.8e5c89f3.chunk.js.map +0 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0cc958e39e24a421db5d4844d545788ca48b8fcc641c7798be51f351b5a5fb07
|
|
4
|
+
data.tar.gz: b1e0423a339d9b0c33d4bb8054e8b8cab2069535f601e1c688cfacd385979062
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ded815507746674af611e5f97f4d49481863b5fd834973879ac4a7278bd1f79cfeaf4116cdf5fad645286e9c1017d358c1e2f2eb7f0f1ce774954ceb275014cb
|
|
7
|
+
data.tar.gz: b77605e7f9455a36d098c5227dc4430cfcc6adb44fe5b61ff060ee3a58502e3e715127bebedc6f41ea5950435da7ed64c8c7c2949c198f8a7b1aca437fd10db6
|
data/INSTALL.md
CHANGED
data/README.md
CHANGED
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
- [PiFi configuration](#pifi-configuration)
|
|
18
18
|
- [Usage](#usage)
|
|
19
19
|
- [Help me translate](#help-me-translate)
|
|
20
|
+
- [Some projects using PiFi Radio](#some-projects-using-pifi-radio)
|
|
20
21
|
- [Credits](#credits)
|
|
21
22
|
- [Buy me a coffee](#buy-me-a-coffee)
|
|
22
23
|
- [License](#license)
|
|
@@ -66,6 +67,12 @@ Run:
|
|
|
66
67
|
$ sudo gem update pifi --no-document
|
|
67
68
|
```
|
|
68
69
|
|
|
70
|
+
Restart PiFi. If you are using the systemd service, this is done by:
|
|
71
|
+
|
|
72
|
+
```
|
|
73
|
+
$ sudo systemctl restart pifi
|
|
74
|
+
```
|
|
75
|
+
|
|
69
76
|
## Configuration
|
|
70
77
|
|
|
71
78
|
### List of streams
|
|
@@ -99,14 +106,14 @@ It's now completely optional to have a configuration file for PiFi. You only nee
|
|
|
99
106
|
|
|
100
107
|
The path is `/etc/pifi/config.json` and these are the options:
|
|
101
108
|
|
|
102
|
-
| Key | Default
|
|
103
|
-
| ------------------- |
|
|
109
|
+
| Key | Default | Description |
|
|
110
|
+
| ------------------- | -------------------------- | ----------------------------------------------------------------------------------------------------------------- |
|
|
104
111
|
| `mpd_host` | `"127.0.0.1"` | MPD host. |
|
|
105
112
|
| `mpd_port` | `6600` | MPD port. |
|
|
106
113
|
| `mpd_password` | `""` (none) | MPD password. |
|
|
107
114
|
| `streams_path` | `"/etc/pifi/streams.json"` | Path to the JSON file containing the streams. |
|
|
108
115
|
| `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"]`
|
|
116
|
+
| `special_ips` | `[]` (none) | The IPs of the devices to show additional streams. Example: `["10.0.0.1", "10.0.0.2"]` |
|
|
110
117
|
| `serve_static` | `true` | If we should serve static resources. Set it to `false` if your web server is already doing it. |
|
|
111
118
|
|
|
112
119
|
If you want to change any of these options, download the sample file and edit it to your needs:
|
|
@@ -135,7 +142,7 @@ You can help me adding a new language to PiFi or improving an existing translati
|
|
|
135
142
|
|
|
136
143
|
The default language for PiFi is English, so you should use it as a reference.
|
|
137
144
|
|
|
138
|
-
1. Open [the translation file](https://github.com/rccavalcanti/pifi-radio/tree/master/frontend/public/locales) and [the English file](https://github.com/rccavalcanti/pifi-radio/blob/master/frontend/public/locales/en/translation.json).
|
|
145
|
+
1. Open [the translation file](https://github.com/rccavalcanti/pifi-radio/tree/master/frontend/public/locales) and [the English file](https://github.com/rccavalcanti/pifi-radio/blob/master/frontend/public/locales/en-US/translation.json).
|
|
139
146
|
2. Fill empty strings and fix any bad translations.
|
|
140
147
|
3. Send a pull request.
|
|
141
148
|
|
|
@@ -145,9 +152,14 @@ The default language for PiFi is English, so you should use it as a reference.
|
|
|
145
152
|
2. On `translation.json`, translate the strings. If you aren't sure of some, please make them empty.
|
|
146
153
|
3. Send a pull request.
|
|
147
154
|
|
|
155
|
+
## Some projects using PiFi Radio
|
|
156
|
+
|
|
157
|
+
- [Internet Radio from broken Bose Dockstation](https://piamble.wordpress.com/2021/01/30/internet-radio-from-broken-bose-dockstation-part-1/)
|
|
158
|
+
|
|
148
159
|
## Credits
|
|
149
160
|
|
|
150
|
-
-
|
|
161
|
+
- de-de: [cedege](https://github.com/cedege)
|
|
162
|
+
- fr-fr: [Florent Segouin](https://github.com/fsegouin), [Francis Chavanon](https://github.com/rimeno)
|
|
151
163
|
- pl-pl: [Struart88](https://github.com/Struart88)
|
|
152
164
|
- nl-nl: [Heimen Stoffels](https://github.com/Vistaus)
|
|
153
165
|
|
|
@@ -157,10 +169,10 @@ The default language for PiFi is English, so you should use it as a reference.
|
|
|
157
169
|
|
|
158
170
|
If you find PiFi useful, you can show your support here:
|
|
159
171
|
|
|
160
|
-
<a href="https://
|
|
172
|
+
<a href="https://rafaelc.org/coffee" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/default-orange.png" alt="Buy Me A Coffee" width="200" ></a>
|
|
161
173
|
|
|
162
174
|
## License
|
|
163
175
|
|
|
164
176
|
Licensed under [GPLv3](LICENSE)
|
|
165
177
|
|
|
166
|
-
Copyright (C) 2017-
|
|
178
|
+
Copyright (C) 2017-2021 [Rafael Cavalcanti](https://rafaelc.org/)
|
|
@@ -1,27 +1,27 @@
|
|
|
1
1
|
{
|
|
2
2
|
"files": {
|
|
3
|
-
"main.css": "/static/css/main.
|
|
4
|
-
"main.js": "/static/js/main.
|
|
5
|
-
"main.js.map": "/static/js/main.
|
|
3
|
+
"main.css": "/static/css/main.48912641.chunk.css",
|
|
4
|
+
"main.js": "/static/js/main.11609572.chunk.js",
|
|
5
|
+
"main.js.map": "/static/js/main.11609572.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
|
-
"static/css/2.
|
|
8
|
+
"static/css/2.1781c263.chunk.css": "/static/css/2.1781c263.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.
|
|
12
|
+
"precache-manifest.7acd7ef058033a1ded72e03e499bd33f.js": "/precache-manifest.7acd7ef058033a1ded72e03e499bd33f.js",
|
|
13
13
|
"service-worker.js": "/service-worker.js",
|
|
14
|
-
"static/css/2.
|
|
15
|
-
"static/css/main.
|
|
14
|
+
"static/css/2.1781c263.chunk.css.map": "/static/css/2.1781c263.chunk.css.map",
|
|
15
|
+
"static/css/main.48912641.chunk.css.map": "/static/css/main.48912641.chunk.css.map",
|
|
16
16
|
"static/js/2.6c0ded8a.chunk.js.LICENSE.txt": "/static/js/2.6c0ded8a.chunk.js.LICENSE.txt",
|
|
17
17
|
"static/media/getFetch.cjs": "/static/media/getFetch.5e98861f.cjs",
|
|
18
18
|
"static/media/logo.svg": "/static/media/logo.91554ce9.svg"
|
|
19
19
|
},
|
|
20
20
|
"entrypoints": [
|
|
21
21
|
"static/js/runtime-main.5aae5a31.js",
|
|
22
|
-
"static/css/2.
|
|
22
|
+
"static/css/2.1781c263.chunk.css",
|
|
23
23
|
"static/js/2.6c0ded8a.chunk.js",
|
|
24
|
-
"static/css/main.
|
|
25
|
-
"static/js/main.
|
|
24
|
+
"static/css/main.48912641.chunk.css",
|
|
25
|
+
"static/js/main.11609572.chunk.js"
|
|
26
26
|
]
|
|
27
27
|
}
|
data/lib/pifi/public/index.html
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
<!doctype html><html
|
|
1
|
+
<!doctype html><html><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.1781c263.chunk.css" rel="stylesheet"><link href="/static/css/main.48912641.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.11609572.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
|
+
"tuning": "Senderwechsel...",
|
|
26
|
+
"version": "Version",
|
|
27
|
+
"volume": "Lautstärke"
|
|
28
|
+
}
|
|
@@ -1,28 +1,28 @@
|
|
|
1
1
|
{
|
|
2
|
-
"about": "",
|
|
3
|
-
"cancel": "",
|
|
4
|
-
"close": "",
|
|
5
|
-
"coffee": "",
|
|
2
|
+
"about": "À Propos",
|
|
3
|
+
"cancel": "Annuler",
|
|
4
|
+
"close": "Fermer",
|
|
5
|
+
"coffee": "Si vous aimez PiFi Radio, vous pouvez montrer votre soutien en m'offrant un café.",
|
|
6
6
|
"disconnectedMPD": "Déconnecté de MPD",
|
|
7
|
-
"environment": "",
|
|
8
|
-
"errorForbidden": "",
|
|
9
|
-
"errorNetwork": "Pas de connexion",
|
|
10
|
-
"errorNotFound": "",
|
|
11
|
-
"errorUnexpected": "",
|
|
12
|
-
"goToDocs": "",
|
|
13
|
-
"language": "",
|
|
14
|
-
"mpdHost": "",
|
|
15
|
-
"mpdPort": "",
|
|
16
|
-
"noStreams": "",
|
|
17
|
-
"ok": "",
|
|
7
|
+
"environment": "Environnement",
|
|
8
|
+
"errorForbidden": "Requête interdite. Veuillez vérifier le mot de passe de MPD et les permissions.",
|
|
9
|
+
"errorNetwork": "Pas de connexion au server PiFi",
|
|
10
|
+
"errorNotFound": "Le flux est introuvable.",
|
|
11
|
+
"errorUnexpected": "Une erreur inattendue s'est produite.",
|
|
12
|
+
"goToDocs": "Référez-vous à la documentation",
|
|
13
|
+
"language": "Langue",
|
|
14
|
+
"mpdHost": "MPD hôte",
|
|
15
|
+
"mpdPort": "MPD port",
|
|
16
|
+
"noStreams": "Aucune station n'est disponible.",
|
|
17
|
+
"ok": "Confirmer",
|
|
18
18
|
"playing": "Lecture",
|
|
19
|
-
"playURL": "",
|
|
20
|
-
"search": "",
|
|
21
|
-
"settings": "",
|
|
19
|
+
"playURL": "Ouvrir URL",
|
|
20
|
+
"search": "Rechercher...",
|
|
21
|
+
"settings": "Paramètres",
|
|
22
22
|
"stopped": "Arrêté",
|
|
23
|
-
"theme": "",
|
|
24
|
-
"tryingURL": "",
|
|
25
|
-
"
|
|
26
|
-
"version": "",
|
|
27
|
-
"volume": ""
|
|
23
|
+
"theme": "Thème",
|
|
24
|
+
"tryingURL": "URL en cours de lecture...",
|
|
25
|
+
"tuning": "Mise en mémoire tampon...",
|
|
26
|
+
"version": "Version",
|
|
27
|
+
"volume": "Volume"
|
|
28
28
|
}
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
self.__precacheManifest = (self.__precacheManifest || []).concat([
|
|
2
2
|
{
|
|
3
|
-
"revision": "
|
|
3
|
+
"revision": "7f9522f73b77875baa1b55e081156d27",
|
|
4
4
|
"url": "/index.html"
|
|
5
5
|
},
|
|
6
6
|
{
|
|
7
|
-
"revision": "
|
|
8
|
-
"url": "/static/css/2.
|
|
7
|
+
"revision": "59d428a63666535e7576",
|
|
8
|
+
"url": "/static/css/2.1781c263.chunk.css"
|
|
9
9
|
},
|
|
10
10
|
{
|
|
11
|
-
"revision": "
|
|
12
|
-
"url": "/static/css/main.
|
|
11
|
+
"revision": "d7bddd229628dd8638a5",
|
|
12
|
+
"url": "/static/css/main.48912641.chunk.css"
|
|
13
13
|
},
|
|
14
14
|
{
|
|
15
|
-
"revision": "
|
|
15
|
+
"revision": "59d428a63666535e7576",
|
|
16
16
|
"url": "/static/js/2.6c0ded8a.chunk.js"
|
|
17
17
|
},
|
|
18
18
|
{
|
|
@@ -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": "
|
|
24
|
-
"url": "/static/js/main.
|
|
23
|
+
"revision": "d7bddd229628dd8638a5",
|
|
24
|
+
"url": "/static/js/main.11609572.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.
|
|
17
|
+
"/precache-manifest.7acd7ef058033a1ded72e03e499bd33f.js"
|
|
18
18
|
);
|
|
19
19
|
|
|
20
20
|
self.addEventListener('message', (event) => {
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
.Toastify__toast-container{z-index:9999;-webkit-transform:translateZ(9999px);position:fixed;padding:4px;width:320px;box-sizing:border-box;color:#fff}.Toastify__toast-container--top-left{top:1em;left:1em}.Toastify__toast-container--top-center{top:1em;left:50%;transform:translateX(-50%)}.Toastify__toast-container--top-right{top:1em;right:1em}.Toastify__toast-container--bottom-left{bottom:1em;left:1em}.Toastify__toast-container--bottom-center{bottom:1em;left:50%;transform:translateX(-50%)}.Toastify__toast-container--bottom-right{bottom:1em;right:1em}@media only screen and (max-width:480px){.Toastify__toast-container{width:100vw;padding:0;left:0;margin:0}.Toastify__toast-container--top-center,.Toastify__toast-container--top-left,.Toastify__toast-container--top-right{top:0;transform:translateX(0)}.Toastify__toast-container--bottom-center,.Toastify__toast-container--bottom-left,.Toastify__toast-container--bottom-right{bottom:0;transform:translateX(0)}.Toastify__toast-container--rtl{right:0;left:auto}}.Toastify__toast{position:relative;min-height:64px;box-sizing:border-box;margin-bottom:1rem;padding:8px;border-radius:1px;box-shadow:0 1px 10px 0 rgba(0,0,0,.1),0 2px 15px 0 rgba(0,0,0,.05);display:flex;justify-content:space-between;max-height:800px;overflow:hidden;font-family:sans-serif;cursor:pointer;direction:ltr}.Toastify__toast--rtl{direction:rtl}.Toastify__toast--dark{background:#121212;color:#fff}.Toastify__toast--default{background:#fff;color:#aaa}.Toastify__toast--info{background:#3498db}.Toastify__toast--success{background:#07bc0c}.Toastify__toast--warning{background:#f1c40f}.Toastify__toast--error{background:#e74c3c}.Toastify__toast-body{margin:auto 0;flex:1 1 auto}@media only screen and (max-width:480px){.Toastify__toast{margin-bottom:0}}.Toastify__close-button{color:#fff;background:transparent;outline:none;border:none;padding:0;cursor:pointer;opacity:.7;transition:.3s ease;align-self:flex-start}.Toastify__close-button--default{color:#000;opacity:.3}.Toastify__close-button>svg{fill:currentColor;height:16px;width:14px}.Toastify__close-button:focus,.Toastify__close-button:hover{opacity:1}@keyframes Toastify__trackProgress{0%{transform:scaleX(1)}to{transform:scaleX(0)}}.Toastify__progress-bar{position:absolute;bottom:0;left:0;width:100%;height:5px;z-index:9999;opacity:.7;background-color:hsla(0,0%,100%,.7);transform-origin:left}.Toastify__progress-bar--animated{animation:Toastify__trackProgress linear 1 forwards}.Toastify__progress-bar--controlled{transition:transform .2s}.Toastify__progress-bar--rtl{right:0;left:auto;transform-origin:right}.Toastify__progress-bar--default{background:linear-gradient(90deg,#4cd964,#5ac8fa,#007aff,#34aadc,#5856d6,#ff2d55)}.Toastify__progress-bar--dark{background:#bb86fc}@keyframes Toastify__bounceInRight{0%,60%,75%,90%,to{animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;transform:translate3d(3000px,0,0)}60%{opacity:1;transform:translate3d(-25px,0,0)}75%{transform:translate3d(10px,0,0)}90%{transform:translate3d(-5px,0,0)}to{transform:none}}@keyframes Toastify__bounceOutRight{20%{opacity:1;transform:translate3d(-20px,0,0)}to{opacity:0;transform:translate3d(2000px,0,0)}}@keyframes Toastify__bounceInLeft{0%,60%,75%,90%,to{animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;transform:translate3d(-3000px,0,0)}60%{opacity:1;transform:translate3d(25px,0,0)}75%{transform:translate3d(-10px,0,0)}90%{transform:translate3d(5px,0,0)}to{transform:none}}@keyframes Toastify__bounceOutLeft{20%{opacity:1;transform:translate3d(20px,0,0)}to{opacity:0;transform:translate3d(-2000px,0,0)}}@keyframes Toastify__bounceInUp{0%,60%,75%,90%,to{animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;transform:translate3d(0,3000px,0)}60%{opacity:1;transform:translate3d(0,-20px,0)}75%{transform:translate3d(0,10px,0)}90%{transform:translate3d(0,-5px,0)}to{transform:translateZ(0)}}@keyframes Toastify__bounceOutUp{20%{transform:translate3d(0,-10px,0)}40%,45%{opacity:1;transform:translate3d(0,20px,0)}to{opacity:0;transform:translate3d(0,-2000px,0)}}@keyframes Toastify__bounceInDown{0%,60%,75%,90%,to{animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;transform:translate3d(0,-3000px,0)}60%{opacity:1;transform:translate3d(0,25px,0)}75%{transform:translate3d(0,-10px,0)}90%{transform:translate3d(0,5px,0)}to{transform:none}}@keyframes Toastify__bounceOutDown{20%{transform:translate3d(0,10px,0)}40%,45%{opacity:1;transform:translate3d(0,-20px,0)}to{opacity:0;transform:translate3d(0,2000px,0)}}.Toastify__bounce-enter--bottom-left,.Toastify__bounce-enter--top-left{animation-name:Toastify__bounceInLeft}.Toastify__bounce-enter--bottom-right,.Toastify__bounce-enter--top-right{animation-name:Toastify__bounceInRight}.Toastify__bounce-enter--top-center{animation-name:Toastify__bounceInDown}.Toastify__bounce-enter--bottom-center{animation-name:Toastify__bounceInUp}.Toastify__bounce-exit--bottom-left,.Toastify__bounce-exit--top-left{animation-name:Toastify__bounceOutLeft}.Toastify__bounce-exit--bottom-right,.Toastify__bounce-exit--top-right{animation-name:Toastify__bounceOutRight}.Toastify__bounce-exit--top-center{animation-name:Toastify__bounceOutUp}.Toastify__bounce-exit--bottom-center{animation-name:Toastify__bounceOutDown}@keyframes Toastify__zoomIn{0%{opacity:0;transform:scale3d(.3,.3,.3)}50%{opacity:1}}@keyframes Toastify__zoomOut{0%{opacity:1}50%{opacity:0;transform:scale3d(.3,.3,.3)}to{opacity:0}}.Toastify__zoom-enter{animation-name:Toastify__zoomIn}.Toastify__zoom-exit{animation-name:Toastify__zoomOut}@keyframes Toastify__flipIn{0%{transform:perspective(400px) rotateX(90deg);animation-timing-function:ease-in;opacity:0}40%{transform:perspective(400px) rotateX(-20deg);animation-timing-function:ease-in}60%{transform:perspective(400px) rotateX(10deg);opacity:1}80%{transform:perspective(400px) rotateX(-5deg)}to{transform:perspective(400px)}}@keyframes Toastify__flipOut{0%{transform:perspective(400px)}30%{transform:perspective(400px) rotateX(-20deg);opacity:1}to{transform:perspective(400px) rotateX(90deg);opacity:0}}.Toastify__flip-enter{animation-name:Toastify__flipIn}.Toastify__flip-exit{animation-name:Toastify__flipOut}@keyframes Toastify__slideInRight{0%{transform:translate3d(110%,0,0);visibility:visible}to{transform:translateZ(0)}}@keyframes Toastify__slideInLeft{0%{transform:translate3d(-110%,0,0);visibility:visible}to{transform:translateZ(0)}}@keyframes Toastify__slideInUp{0%{transform:translate3d(0,110%,0);visibility:visible}to{transform:translateZ(0)}}@keyframes Toastify__slideInDown{0%{transform:translate3d(0,-110%,0);visibility:visible}to{transform:translateZ(0)}}@keyframes Toastify__slideOutRight{0%{transform:translateZ(0)}to{visibility:hidden;transform:translate3d(110%,0,0)}}@keyframes Toastify__slideOutLeft{0%{transform:translateZ(0)}to{visibility:hidden;transform:translate3d(-110%,0,0)}}@keyframes Toastify__slideOutDown{0%{transform:translateZ(0)}to{visibility:hidden;transform:translate3d(0,500px,0)}}@keyframes Toastify__slideOutUp{0%{transform:translateZ(0)}to{visibility:hidden;transform:translate3d(0,-500px,0)}}.Toastify__slide-enter--bottom-left,.Toastify__slide-enter--top-left{animation-name:Toastify__slideInLeft}.Toastify__slide-enter--bottom-right,.Toastify__slide-enter--top-right{animation-name:Toastify__slideInRight}.Toastify__slide-enter--top-center{animation-name:Toastify__slideInDown}.Toastify__slide-enter--bottom-center{animation-name:Toastify__slideInUp}.Toastify__slide-exit--bottom-left,.Toastify__slide-exit--top-left{animation-name:Toastify__slideOutLeft}.Toastify__slide-exit--bottom-right,.Toastify__slide-exit--top-right{animation-name:Toastify__slideOutRight}.Toastify__slide-exit--top-center{animation-name:Toastify__slideOutUp}.Toastify__slide-exit--bottom-center{animation-name:Toastify__slideOutDown}
|
|
2
|
+
/*# sourceMappingURL=2.1781c263.chunk.css.map */
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../scss/_toastContainer.scss","../scss/_variables.scss","ReactToastify.css","../scss/_toast.scss","../scss/_closeButton.scss","../scss/_progressBar.scss","../scss/animations/_bounce.scss","../scss/animations/_zoom.scss","../scss/animations/_flip.scss","../scss/animations/_slide.scss"],"names":[],"mappings":"AAAA,2BACI,YCmBS,CDlBT,oCAAA,CACA,cAAA,CACA,WAAA,CACA,WCJa,CDKb,qBAAA,CACA,UECJ,CFAI,qCACI,OAAA,CACA,QEER,CFAI,uCACI,OAAA,CACA,QAAA,CACA,0BEER,CFAI,sCACI,OAAA,CACA,SEER,CFAI,wCACI,UAAA,CACA,QEER,CFAI,0CACI,UAAA,CACA,QAAA,CACA,0BEER,CFAI,yCACI,UAAA,CACA,SEER,CFEA,yCACI,2BACI,WAAA,CACA,SAAA,CACA,MAAA,CACA,QECN,CFAM,kHAGI,KAAA,CACA,uBEAV,CFEM,2HAGI,QAAA,CACA,uBEFV,CFIM,gCACE,OAAA,CACA,SEFR,CACF,CCvDA,iBACI,iBAAA,CACA,eFCkB,CEAlB,qBAAA,CACA,kBAAA,CACA,WAAA,CACA,iBAAA,CACA,mEAAA,CACA,YAAA,CACA,6BAAA,CACA,gBFNkB,CEOlB,eAAA,CACA,sBFOa,CENb,cAAA,CACA,aDyDJ,CCxDI,sBACI,aD0DR,CCxDI,uBACI,kBFZQ,CEaR,UD0DR,CCxDI,0BACI,eFjBW,CEkBX,UD0DR,CCxDI,uBACI,kBD0DR,CCxDI,0BACI,kBD0DR,CCxDI,0BACI,kBD0DR,CCxDI,wBACI,kBD0DR,CCxDI,sBACI,aAAA,CACA,aD0DR,CCtDA,yCACE,iBACE,eDyDF,CACF,CExGA,wBACE,UAAA,CACA,sBAAA,CACA,YAAA,CACA,WAAA,CACA,SAAA,CACA,cAAA,CACA,UAAA,CACA,mBAAA,CACA,qBF0GF,CExGE,iCACE,UAAA,CACA,UF0GJ,CEvGE,4BACE,iBAAA,CACA,WAAA,CACA,UFyGJ,CEtGE,4DACE,SFwGJ,CG/HA,mCACE,GACE,mBHkIF,CGhIA,GACE,mBHkIF,CACF,CG/HA,wBACE,iBAAA,CACA,QAAA,CACA,MAAA,CACA,UAAA,CACA,UAAA,CACA,YJKW,CIJX,UAAA,CACA,mCAAA,CACA,qBHiIF,CG/HE,kCACE,mDHiIJ,CG9HE,oCACE,wBHgIJ,CG7HE,6BACE,OAAA,CACA,SAAA,CACA,sBH+HJ,CG5HE,iCACE,iFH8HJ,CG3HE,8BACE,kBH6HJ,CIhKA,mCACI,kBAJA,uDJuKF,CI5JE,GACI,SAAA,CACA,iCJ8JN,CI5JE,IACI,SAAA,CACA,gCJ8JN,CI5JE,IACI,+BJ8JN,CI5JE,IACI,+BJ8JN,CI5JE,GACI,cJ8JN,CACF,CI3JA,oCACI,IACI,SAAA,CACA,gCJ6JN,CI3JE,GACI,SAAA,CACA,iCJ6JN,CACF,CI1JA,kCACI,kBA1CA,uDJuMF,CItJE,GACI,SAAA,CACA,kCJwJN,CItJE,IACI,SAAA,CACA,+BJwJN,CItJE,IACI,gCJwJN,CItJE,IACI,8BJwJN,CItJE,GACI,cJwJN,CACF,CIrJA,mCACI,IACI,SAAA,CACA,+BJuJN,CIrJE,GACI,SAAA,CACA,kCJuJN,CACF,CIpJA,gCACI,kBAhFA,uDJuOF,CIhJE,GACI,SAAA,CACA,iCJkJN,CIhJE,IACI,SAAA,CACA,gCJkJN,CIhJE,IACI,+BJkJN,CIhJE,IACI,+BJkJN,CIhJE,GACI,uBJkJN,CACF,CI/IA,iCACI,IACI,gCJiJN,CI/IE,QAEI,SAAA,CACA,+BJgJN,CI9IE,GACI,SAAA,CACA,kCJgJN,CACF,CI7IA,kCACI,kBA1HA,uDJ0QF,CIzIE,GACI,SAAA,CACA,kCJ2IN,CIzIE,IACI,SAAA,CACA,+BJ2IN,CIzIE,IACI,gCJ2IN,CIzIE,IACI,8BJ2IN,CIzIE,GACI,cJ2IN,CACF,CIxIA,mCACI,IACI,+BJ0IN,CIxIE,QAEI,SAAA,CACA,gCJyIN,CIvIE,GACI,SAAA,CACA,iCJyIN,CACF,CIrII,uEAEI,qCJsIR,CIpII,yEAEI,sCJqIR,CInII,oCACI,qCJqIR,CInII,uCACI,mCJqIR,CIhII,qEAEI,sCJkIR,CIhII,uEAEI,uCJiIR,CI/HI,mCACI,oCJiIR,CI/HI,sCACI,sCJiIR,CKnUA,4BACI,GACI,SAAA,CACA,2BLsUN,CKpUE,IACI,SLsUN,CACF,CKnUA,6BACI,GACI,SLqUN,CKnUE,IACI,SAAA,CACA,2BLqUN,CKnUE,GACI,SLqUN,CACF,CKlUA,sBACI,+BLoUJ,CKjUA,qBACI,gCLoUJ,CMhWA,4BACI,GACI,2CAAA,CACA,iCAAA,CACA,SNmWN,CMjWE,IACI,4CAAA,CACA,iCNmWN,CMjWE,IACI,2CAAA,CACA,SNmWN,CMjWE,IACI,2CNmWN,CMjWE,GACI,4BNmWN,CACF,CMhWA,6BACI,GACI,4BNkWN,CMhWE,IACI,4CAAA,CACA,SNkWN,CMhWE,GACI,2CAAA,CACA,SNkWN,CACF,CM/VA,sBACI,+BNiWJ,CM9VA,qBACI,gCNiWJ,COtYA,kCACI,GACI,+BAAA,CACA,kBPyYN,COvYE,GARA,uBPkZF,CACF,COtYA,iCACI,GACI,gCAAA,CACA,kBPwYN,COtYE,GAlBA,uBP2ZF,CACF,COrYA,+BACI,GACI,+BAAA,CACA,kBPuYN,COrYE,GA5BA,uBPoaF,CACF,COpYA,iCACI,GACI,gCAAA,CACA,kBPsYN,COpYE,GAtCA,uBP6aF,CACF,COnYA,mCACI,GA5CA,uBPkbF,COnYE,GACI,iBAAA,CACA,+BPqYN,CACF,COlYA,kCACI,GAtDA,uBP2bF,COlYE,GACI,iBAAA,CACA,gCPoYN,CACF,COjYA,kCACI,GAhEA,uBPocF,COjYE,GACI,iBAAA,CACA,gCPmYN,CACF,COhYA,gCACI,GA1EA,uBP6cF,COhYE,GACI,iBAAA,CACA,iCPkYN,CACF,CO9XI,qEAEI,oCP+XR,CO7XI,uEAEI,qCP8XR,CO5XI,mCACI,oCP8XR,CO5XI,sCACI,kCP8XR,COzXI,mEAEI,qCP2XR,COzXI,qEAEI,sCP0XR,COxXI,kCACI,mCP0XR,COxXI,qCACI,qCP0XR","file":"2.1781c263.chunk.css"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
.navbar{position:-webkit-sticky!important;position:sticky!important;top:0;z-index:5;margin-bottom:2rem;padding:.8rem 1rem;min-height:4.7793rem}.loader{height:100vh}.backdrop,.loader{z-index:10;display:flex;justify-content:center;align-items:center}.backdrop{position:fixed;width:100%;height:100%;background-color:#222;opacity:0;visibility:hidden;transition:all .2s ease;cursor:default;flex-direction:column;text-align:center}.backdrop--visible{opacity:.94;visibility:visible}.body--backdrop{overflow:hidden}.player{width:100%;max-width:450px;display:flex;flex-direction:column;justify-content:space-between;align-items:center}.player-logo{width:130px}@media (max-height:430px){.player-logo{display:none}}.streams{max-width:450px}.streams__header{font-size:1.3rem;margin-top:1em;padding:.5rem 1.25rem}.streams__item{padding:0}.streams__btn{padding:.75rem 1.25rem;width:100%;text-align:left}.mini-player{display:flex;align-items:center;justify-content:space-between}.mini-player button{padding:10px 20px}.mini-player__left{max-width:calc(100vw - 160px);margin-right:1rem}.drawer{z-index:5!important;height:5rem;cursor:pointer;touch-action:none;display:flex;align-items:center;transition:height .25s ease-out}.drawer>.mini-player{flex-grow:1;margin:0 .5rem 0 .25rem}.drawer--open{height:100%;flex-direction:column;justify-content:flex-end}.drawer--open .player{flex-grow:1}.drawer--open .drawer__toggler{margin-bottom:20px}@media (max-width:770px){.body--drawer{overflow:hidden}}.main__primary{padding-bottom:7rem}.main__primary .player{display:none}.main__primary .streams{margin:0 auto}@media (min-width:770px){.main__primary{padding-bottom:2rem;display:flex;justify-content:space-between}.main__primary>*{min-width:0;width:100%}.main__primary .player{display:inherit;position:-webkit-sticky;position:sticky;top:6.7793rem;margin-left:2rem;height:calc(100vh - 8.7793rem);max-height:550px}.main__primary .streams{margin:0}.drawer{display:none}}html{height:100%}body{min-height:100%;overflow-y:scroll}button[disabled]{cursor:default}.ellipsis{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
|
2
|
+
/*# sourceMappingURL=main.48912641.chunk.css.map */
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["navBar.scss","../_variables.scss","loader.scss","backdrop.scss","player.scss","streams.scss","miniPlayer.scss","drawer.scss","main.scss","index.scss"],"names":[],"mappings":"AAEA,QACE,iCAA2B,CAA3B,yBAA2B,CAC3B,KAAM,CACN,SAAU,CACV,kBCFe,CDKf,kBAAoB,CAEpB,oBCRoB,CCHtB,QAKE,YAAa,CCLf,kBDCE,UAAW,CACX,YAAa,CACb,sBAAuB,CACvB,kBCUkB,CAdpB,UAEE,cAAe,CACf,UAAW,CACX,WAAY,CACZ,qBAAyB,CACzB,SAAU,CACV,iBAAkB,CAClB,uBAAyB,CACzB,cAAe,CAEf,qBAAsB,CAGtB,iBAAkB,CAElB,mBACE,WAAa,CACb,kBAAmB,CACpB,gBAID,eAAgB,CCrBlB,QACE,UAAW,CACX,eAAgB,CAChB,YAAa,CACb,qBAAsB,CACtB,6BAA8B,CAC9B,kBAAmB,CACpB,aAGC,WAAY,CACb,0BAGC,aACE,YAAa,CACd,CChBH,SACE,eAAgB,CACjB,iBAGC,gBAAiB,CACjB,cAAe,CACf,qBAAuB,CACxB,eAGC,SAAU,CACX,cAGC,sBAAwB,CACxB,UAAW,CACX,eAAgB,CCnBlB,aACE,YAAa,CACb,kBAAmB,CACnB,6BAA8B,CAHhC,oBAMI,iBAAkB,CACnB,mBAKD,6BAA8B,CAC9B,iBAAkB,CCXpB,QACE,mBAAqB,CACrB,WNFkB,CMGlB,cAAe,CACf,iBAAkB,CAClB,YAAa,CACb,kBAAmB,CACnB,+BAAiC,CAPnC,qBAUI,WAAY,CACZ,uBAA0B,CAC3B,cAGC,WAAY,CACZ,qBAAsB,CACtB,wBAAyB,CAH1B,sBAMG,WAAY,CANf,+BAUG,kBAAmB,CACpB,yBAOH,cACE,eAAgB,CACjB,CChCH,eAGE,mBAAwC,CAH1C,uBAMI,YAAa,CANjB,wBAUI,aAAc,CACf,yBAID,eACE,mBAlBS,CAmBT,YAAa,CACb,6BAA8B,CAHhC,iBAMI,WAAY,CACZ,UAAW,CAPf,uBAWI,eAAgB,CAChB,uBAAgB,CAAhB,eAAgB,CAChB,aP3B8B,CO4B9B,gBAAiB,CACjB,8BAA4C,CAC5C,gBAAiB,CAhBrB,wBAoBI,QAAS,CACV,QAID,YAAa,CACd,CC7CH,KACE,WAAY,CACb,KAGC,eAAgB,CAChB,iBAAkB,CACnB,iBAGC,cAAe,CAChB,UAGC,kBAAmB,CACnB,eAAgB,CAChB,sBAAuB","file":"main.48912641.chunk.css","sourcesContent":["@import '../variables';\n\n.navbar {\n position: sticky !important;\n top: 0;\n z-index: 5;\n margin-bottom: $nav-margin;\n // The following let us have the same height on all themes.\n // 1. prevent lux to increment padding\n padding: 0.8rem 1rem;\n // 2. make darkly as high as lux\n min-height: $nav-height;\n}\n","$for-medium-up: 770px;\n$for-short-down: 430px;\n$drawer-height: 5rem;\n$nav-height: 4.7793rem; // calculated value for higher theme\n$nav-margin: 2rem;\n$nav-size: $nav-height + $nav-margin;\n",".loader {\n z-index: 10;\n display: flex;\n justify-content: center;\n align-items: center;\n height: 100vh;\n}\n",".backdrop {\n z-index: 10;\n position: fixed;\n width: 100%;\n height: 100%;\n background-color: #222222;\n opacity: 0;\n visibility: hidden;\n transition: all 0.2s ease;\n cursor: default;\n display: flex;\n flex-direction: column;\n justify-content: center;\n align-items: center;\n text-align: center;\n\n &--visible {\n opacity: 0.94;\n visibility: visible;\n }\n}\n\n.body--backdrop {\n overflow: hidden;\n}\n","@import '../../variables';\n\n.player {\n width: 100%;\n max-width: 450px;\n display: flex;\n flex-direction: column;\n justify-content: space-between;\n align-items: center;\n}\n\n.player-logo {\n width: 130px;\n}\n\n@media(max-height: $for-short-down) {\n .player-logo {\n display: none;\n }\n}\n","@import '../variables';\n\n.streams {\n max-width: 450px;\n}\n\n.streams__header {\n font-size: 1.3rem;\n margin-top: 1em;\n padding: 0.5rem 1.25rem;\n}\n\n.streams__item {\n padding: 0; // transfer .list-group-item padding to .streams__btn\n}\n\n.streams__btn {\n padding: 0.75rem 1.25rem;\n width: 100%;\n text-align: left;\n}\n",".mini-player {\n display: flex;\n align-items: center;\n justify-content: space-between;\n\n button {\n padding: 10px 20px;\n }\n}\n\n.mini-player__left {\n // Dirty workaround for ellipsis to work\n max-width: calc(100vw - 160px);\n margin-right: 1rem;\n}\n","@import '../variables';\n\n.drawer {\n z-index: 5 !important;\n height: $drawer-height;\n cursor: pointer;\n touch-action: none; // don't scroll on touch\n display: flex;\n align-items: center;\n transition: height 0.25s ease-out;\n\n & > .mini-player {\n flex-grow: 1;\n margin: 0 0.5rem 0 0.25rem;\n }\n\n &--open {\n height: 100%;\n flex-direction: column;\n justify-content: flex-end;\n\n .player {\n flex-grow: 1;\n }\n\n .drawer__toggler {\n margin-bottom: 20px;\n }\n }\n}\n\n// The media query is for the edge case of an open drawer and the\n// window resized past the breakpoint. This brings the scrollbar back.\n@media (max-width: $for-medium-up) {\n .body--drawer {\n overflow: hidden;\n }\n}\n","@import '../variables';\n\n$margin: 2rem;\n\n.main__primary {\n // Use padding instead of margin.\n // This is as workaround for Chrome 87 ignoring margin-bottom on .main__primary.\n padding-bottom: $margin + $drawer-height;\n\n .player {\n display: none;\n }\n\n .streams {\n margin: 0 auto;\n }\n}\n\n@media (min-width: $for-medium-up) {\n .main__primary {\n padding-bottom: $margin; /* no drawer */\n display: flex;\n justify-content: space-between;\n\n & > * {\n min-width: 0; /* don't get bigger when text overflows */\n width: 100%; /* divide space equally */\n }\n\n .player {\n display: inherit;\n position: sticky;\n top: $nav-size;\n margin-left: 2rem;\n height: calc(100vh - #{$nav-size + $margin});\n max-height: 550px;\n }\n\n .streams {\n margin: 0;\n }\n }\n\n .drawer {\n display: none;\n }\n}\n","html {\n height: 100%;\n}\n\nbody {\n min-height: 100%;\n overflow-y: scroll; // so elements don't move if page fits view\n}\n\nbutton[disabled] {\n cursor: default;\n}\n\n.ellipsis {\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n"]}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
(this.webpackJsonppifi_frontend=this.webpackJsonppifi_frontend||[]).push([[0],{13:function(e){e.exports=JSON.parse('{"b":["en-US","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 L={availableThemes:C,getCurrentId:x,change:function(e){localStorage.setItem("theme",e),_()},apply:_},T=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=T.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(L.getCurrentId())}),[]),r.a.createElement(w,{id:"settings",title:t("settings")},r.a.createElement(j,{id:"theme-select",label:t("theme"),data:L.availableThemes,row:!0,value:c,onChange:function(e){return function(e){var t=e.target.value;L.change(t),s(t)}(e)}}),r.a.createElement(j,{id:"language-select",label:t("language"),data:i,row:!0,value:T.b.includes(a.language)?a.language:a.options.fallbackLng[0],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 U(){return D.post("/player",I("play"))}function F(){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-2021\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://rafaelc.org/coffee",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:F,"aria-label":"Stop"},r.a.createElement(z.a,{icon:Q.d})):r.a.createElement("button",{className:"btn btn-dark",onClick:U,"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:T.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("tuning"),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 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},r.a.createElement("button",{className:"streams__btn btn btn-outline ellipsis",onClick:function(){return e.handleItemClick(a)},disabled:e.isPlaying(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:{}})}),T.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()}),T.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-US",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);L.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.11609572.chunk.js.map
|
|
@@ -0,0 +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","includes","language","options","fallbackLng","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","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","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.11609572.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 <nav className=\"navbar navbar-expand-sm navbar-dark bg-primary\">\n <div className=\"container\">\n <a className=\"navbar-brand\" href=\"/\">\n <img\n src={logo}\n width=\"30\"\n height=\"30\"\n className=\"d-inline-block align-text-bottom mr-2\"\n alt=\"\"\n />\n PiFi Radio\n </a>\n <button\n className=\"navbar-toggler\"\n type=\"button\"\n data-toggle=\"collapse\"\n data-target=\"#navbarNavAltMarkup\"\n aria-controls=\"navbarNavAltMarkup\"\n aria-expanded=\"false\"\n aria-label=\"Toggle navigation\"\n >\n <span className=\"navbar-toggler-icon\"></span>\n </button>\n <div className=\"collapse navbar-collapse\" id=\"navbarNavAltMarkup\">\n <div className=\"navbar-nav pt-1 ml-2\">\n {/* We use buttons and different class names instead of Bootstrap's\n anchor, so we don't get a warning for href=\"#\". */}\n <button\n className=\"btn btn-link nav-link\"\n data-toggle=\"modal\"\n data-target=\"#url-dialog\"\n >\n {t('playURL')}\n </button>\n\n <button\n className=\"btn btn-link nav-link\"\n data-toggle=\"modal\"\n data-target=\"#settings\"\n >\n {t('settings')}\n </button>\n\n <button\n className=\"btn btn-link nav-link\"\n data-toggle=\"modal\"\n data-target=\"#about\"\n >\n {t('about')}\n </button>\n </div>\n </div>\n </div>\n </nav>\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 <button className=\"btn btn-secondary\" data-dismiss=\"modal\">\n {t('close')}\n </button>\n );\n\n return (\n <div\n className=\"modal fade\"\n id={id}\n tabIndex=\"-1\"\n role=\"dialog\"\n aria-labelledby=\"staticBackdropLabel\"\n aria-hidden=\"true\"\n >\n <div className=\"modal-dialog\" role=\"document\">\n <div className=\"modal-content\">\n <div className=\"modal-header\">\n <h5 className=\"modal-title\" id=\"staticBackdropLabel\">\n {title}\n </h5>\n <button\n type=\"button\"\n className=\"close\"\n data-dismiss=\"modal\"\n aria-label=\"Close\"\n >\n <span aria-hidden=\"true\">×</span>\n </button>\n </div>\n <div className=\"modal-body\">{children}</div>\n <div className=\"modal-footer\">{footer ? footer : defaultFooter}</div>\n </div>\n </div>\n </div>\n );\n};\n\nexport default Modal;\n","import React from 'react';\n\nconst Select = ({ id, label, row, data, ...rest }) => (\n <div className={row ? 'form-group row' : 'form-group'}>\n <label htmlFor={id} className=\"col-sm-2 col-form-label\">\n {label}\n </label>\n <div className=\"col-sm-10\">\n <select id={id} className=\"form-control\" {...rest}>\n {data.map(d => (\n <option key={d.id || d} value={d.id || d}>\n {d.name || d}\n </option>\n ))}\n </select>\n </div>\n </div>\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 <Modal id=\"settings\" title={t('settings')}>\n <Select\n id=\"theme-select\"\n label={t('theme')}\n data={theme.availableThemes}\n row\n value={themeId}\n onChange={e => handleThemeChange(e)}\n />\n <Select\n id=\"language-select\"\n label={t('language')}\n data={languagesData}\n row\n value={\n languages.includes(i18n.language)\n ? i18n.language\n : i18n.options.fallbackLng[0]\n }\n onChange={e => i18n.changeLanguage(e.target.value)}\n />\n </Modal>\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(<Translation>{t => t('errorUnexpected')}</Translation>);\n\n // Universal expected error\n if (error.response && error.response.status === 403)\n toast.error(<Translation>{t => t('errorForbidden')}</Translation>);\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 <React.Fragment>\n <button\n className=\"btn btn-primary\"\n data-dismiss=\"modal\"\n onClick={handleOK}\n >\n {t('ok')}\n </button>\n <button\n className=\"btn btn-secondary\"\n onClick={() => setURL('')}\n data-dismiss=\"modal\"\n >\n {t('cancel')}\n </button>\n </React.Fragment>\n );\n\n return (\n <Modal id=\"url-dialog\" title={t('playURL')} footer={renderFooter()}>\n <input\n className=\"form-control mb-4\"\n type=\"text\"\n placeholder=\"URL\"\n value={url}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n />\n </Modal>\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 <div className=\"loader\">\n <div className=\"spinner-border\" role=\"status\">\n <span className=\"sr-only\">Loading...</span>\n </div>\n </div>\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 <Loader />;\n\n return (\n <table className=\"table\">\n <tbody>\n {tableData.map((item) => (\n <tr key={item.label}>\n <th scope=\"row\">{item.label}</th>\n <td>{item.value}</td>\n </tr>\n ))}\n </tbody>\n </table>\n );\n };\n\n const copyright = (\n <div className=\"copyright small mt-5\">\n <p>\n <a\n href=\"https://rafaelc.org/pifi\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n style={{ color: 'inherit' }}\n >\n {t('goToDocs')}\n </a>\n </p>\n <p>\n Copyright © 2017-2021 \n {/* Use the default color, as some themes give a different color for links. */}\n <a\n href=\"https://rafaelc.org/\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n style={{ color: 'inherit' }}\n >\n Rafael Cavalcanti\n </a>\n </p>\n </div>\n );\n\n const coffee = (\n <div className=\"coffee mt-5\">\n <p>{t('coffee')}</p>\n <a\n href=\"https://rafaelc.org/coffee\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n <img\n src=\"https://cdn.buymeacoffee.com/buttons/default-blue.png\"\n alt=\"Buy Me A Coffee\"\n style={{ height: 51, width: 217 }}\n />\n </a>\n </div>\n );\n\n return (\n <Modal id=\"about\" title={t('about')}>\n {renderTable()}\n {coffee}\n {copyright}\n </Modal>\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 <div className={classes}>\n <h3 className=\"text-white\">{title}</h3>\n <h5 className=\"text-white\">{body}</h5>\n </div>\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 <div className=\"text-center w-100\">\n <h5 className=\"small text-uppercase\">\n {playing ? t('playing') : t('stopped')}\n </h5>\n <h3 className=\"ellipsis\">{title}</h3>\n </div>\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 <button className=\"btn btn-danger\" onClick={stop} aria-label=\"Stop\">\n <FontAwesomeIcon icon={faStop} />\n </button>\n ) : (\n <button className=\"btn btn-dark\" onClick={play} aria-label=\"Play\">\n <FontAwesomeIcon icon={faPlay} />\n </button>\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 <button\n className=\"btn btn-dark p-3\"\n disabled={volDisabled}\n onClick={() => handleVolChange(delta)}\n aria-label={label}\n >\n <FontAwesomeIcon icon={icon} />\n </button>\n );\n\n return (\n <div\n className=\"player-controls btn-group w-100 m-2\"\n onClick={e => e.stopPropagation()}\n >\n {renderVolButton('-5', faVolumeDown, 'Volume down')}\n {renderVolButton('+5', faVolumeUp, 'Volume up')}\n <PlayStopControl playing={playerStatus.playing} />\n </div>\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 <img\n src={require('../../assets/logo.svg')}\n alt=\"Logo\"\n className=\"player-logo m-4\"\n />\n );\n\n return (\n <div className=\"player\">\n <PlayerStatus playerStatus={playerStatus} />\n {renderLogo()}\n <PlayerControls playerStatus={playerStatus} />\n </div>\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 <input\n className=\"form-control mb-4\"\n type=\"text\"\n id=\"query\"\n placeholder={t('search')}\n aria-label={t('search')}\n autoComplete=\"off\"\n value={value}\n onChange={e => onChange(e.target.value)}\n onFocus={() => onChange('')}\n ></input>\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('tuning'), 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 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 <h4 className=\"p-4\">{this.props.t('noStreams')}</h4>;\n\n return (\n <ul className=\"list-group list-group-flush\">\n {Object.keys(streams).map(name =>\n streams[name] ? (\n <li className=\"streams__header ellipsis\" key={name}>\n {name}\n </li>\n ) : (\n <li className={this.getItemClasses(name)} key={name}>\n <button\n className=\"streams__btn btn btn-outline ellipsis\"\n onClick={() => this.handleItemClick(name)}\n disabled={this.isPlaying(name)}\n >\n {name}\n </button>\n </li>\n )\n )}\n </ul>\n );\n }\n\n render() {\n if (this.state.loading) return <Loader />;\n\n return (\n <div className=\"streams\">\n <SearchBox value={this.state.query} onChange={this.handleSearch} />\n {this.renderList()}\n </div>\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 <div className=\"mini-player\">\n <div className=\"mini-player__left ellipsis\">\n {title}\n </div>\n <div\n className=\"mini-player__right\"\n onClick={e => e.stopPropagation()}\n >\n <PlayStopControl playing={playing} />\n </div>\n </div>\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 <button\n className=\"drawer__toggler btn btn-primary-outline\"\n aria-label=\"Toggle player\"\n >\n <FontAwesomeIcon\n icon={this.state.open ? faChevronDown : faChevronUp}\n className=\"fa-lg\"\n />\n </button>\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 <div\n className={classes}\n onClick={this.handleClick}\n onTouchStart={this.handleTouchStart}\n onTouchMove={this.handleTouchMove}\n >\n {this.renderToggleButton()}\n {open ? (\n <Player playerStatus={playerStatus} />\n ) : (\n <MiniPlayer playerStatus={playerStatus} />\n )}\n </div>\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 <main className=\"main\">\n <Drawer playerStatus={playerStatus} />\n <div className=\"main__primary container\">\n <Streams onBackdrop={onBackdrop} playerStatus={playerStatus} />\n <Player playerStatus={playerStatus} />\n </div>\n </main>\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 <Backdrop title={t('errorNetwork')} />;\n if (loading) return <Loader />;\n if (!playerStatus.con_mpd) return <Backdrop title={t('disconnectedMPD')} />;\n\n return (\n <div className=\"app\">\n <ToastContainer pauseOnFocusLoss={false} />\n <Backdrop title={backdrop.title} body={backdrop.body} />\n <NavBar />\n <Main onBackdrop={this.handleBackdrop} playerStatus={playerStatus} />\n <URLDialog />\n <Settings />\n <About />\n </div>\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-US',\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 <Suspense fallback={<Loader />}>\n <App />\n </Suspense>,\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":""}
|
data/lib/pifi/version.rb
CHANGED
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.
|
|
4
|
+
version: 0.4.12
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Rafael Cavalcanti
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2021-04-08 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: sinatra
|
|
@@ -114,7 +114,8 @@ 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/
|
|
117
|
+
- lib/pifi/public/locales/de-DE/translation.json
|
|
118
|
+
- lib/pifi/public/locales/en-US/translation.json
|
|
118
119
|
- lib/pifi/public/locales/fr-FR/translation.json
|
|
119
120
|
- lib/pifi/public/locales/nl-NL/translation.json
|
|
120
121
|
- lib/pifi/public/locales/pl-PL/translation.json
|
|
@@ -125,19 +126,19 @@ 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.
|
|
129
|
+
- lib/pifi/public/precache-manifest.7acd7ef058033a1ded72e03e499bd33f.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
|
|
132
|
-
- lib/pifi/public/static/css/2.
|
|
133
|
-
- lib/pifi/public/static/css/2.
|
|
134
|
-
- lib/pifi/public/static/css/main.
|
|
135
|
-
- lib/pifi/public/static/css/main.
|
|
133
|
+
- lib/pifi/public/static/css/2.1781c263.chunk.css
|
|
134
|
+
- lib/pifi/public/static/css/2.1781c263.chunk.css.map
|
|
135
|
+
- lib/pifi/public/static/css/main.48912641.chunk.css
|
|
136
|
+
- lib/pifi/public/static/css/main.48912641.chunk.css.map
|
|
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.
|
|
140
|
-
- lib/pifi/public/static/js/main.
|
|
140
|
+
- lib/pifi/public/static/js/main.11609572.chunk.js
|
|
141
|
+
- lib/pifi/public/static/js/main.11609572.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
|
-
.Toastify__toast-container{z-index:9999;-webkit-transform:translateZ(9999px);position:fixed;padding:4px;width:320px;box-sizing:border-box;color:#fff}.Toastify__toast-container--top-left{top:1em;left:1em}.Toastify__toast-container--top-center{top:1em;left:50%;transform:translateX(-50%)}.Toastify__toast-container--top-right{top:1em;right:1em}.Toastify__toast-container--bottom-left{bottom:1em;left:1em}.Toastify__toast-container--bottom-center{bottom:1em;left:50%;transform:translateX(-50%)}.Toastify__toast-container--bottom-right{bottom:1em;right:1em}@media only screen and (max-width:480px){.Toastify__toast-container{width:100vw;padding:0;left:0;margin:0}.Toastify__toast-container--top-center,.Toastify__toast-container--top-left,.Toastify__toast-container--top-right{top:0;transform:translateX(0)}.Toastify__toast-container--bottom-center,.Toastify__toast-container--bottom-left,.Toastify__toast-container--bottom-right{bottom:0;transform:translateX(0)}.Toastify__toast-container--rtl{right:0;left:auto}}.Toastify__toast{position:relative;min-height:64px;box-sizing:border-box;margin-bottom:1rem;padding:8px;border-radius:1px;box-shadow:0 1px 10px 0 rgba(0,0,0,.1),0 2px 15px 0 rgba(0,0,0,.05);display:flex;justify-content:space-between;max-height:800px;overflow:hidden;font-family:sans-serif;cursor:pointer;direction:ltr}.Toastify__toast--rtl{direction:rtl}.Toastify__toast--dark{background:#121212;color:#fff}.Toastify__toast--default{background:#fff;color:#aaa}.Toastify__toast--info{background:#3498db}.Toastify__toast--success{background:#07bc0c}.Toastify__toast--warning{background:#f1c40f}.Toastify__toast--error{background:#e74c3c}.Toastify__toast-body{margin:auto 0;flex:1 1 auto}@media only screen and (max-width:480px){.Toastify__toast{margin-bottom:0}}.Toastify__close-button{color:#fff;background:transparent;outline:none;border:none;padding:0;cursor:pointer;opacity:.7;transition:.3s ease;align-self:flex-start}.Toastify__close-button--default{color:#000;opacity:.3}.Toastify__close-button>svg{fill:currentColor;height:16px;width:14px}.Toastify__close-button:focus,.Toastify__close-button:hover{opacity:1}@-webkit-keyframes Toastify__trackProgress{0%{transform:scaleX(1)}to{transform:scaleX(0)}}@keyframes Toastify__trackProgress{0%{transform:scaleX(1)}to{transform:scaleX(0)}}.Toastify__progress-bar{position:absolute;bottom:0;left:0;width:100%;height:5px;z-index:9999;opacity:.7;background-color:hsla(0,0%,100%,.7);transform-origin:left}.Toastify__progress-bar--animated{-webkit-animation:Toastify__trackProgress linear 1 forwards;animation:Toastify__trackProgress linear 1 forwards}.Toastify__progress-bar--controlled{transition:transform .2s}.Toastify__progress-bar--rtl{right:0;left:auto;transform-origin:right}.Toastify__progress-bar--default{background:linear-gradient(90deg,#4cd964,#5ac8fa,#007aff,#34aadc,#5856d6,#ff2d55)}.Toastify__progress-bar--dark{background:#bb86fc}@-webkit-keyframes Toastify__bounceInRight{0%,60%,75%,90%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;transform:translate3d(3000px,0,0)}60%{opacity:1;transform:translate3d(-25px,0,0)}75%{transform:translate3d(10px,0,0)}90%{transform:translate3d(-5px,0,0)}to{transform:none}}@keyframes Toastify__bounceInRight{0%,60%,75%,90%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;transform:translate3d(3000px,0,0)}60%{opacity:1;transform:translate3d(-25px,0,0)}75%{transform:translate3d(10px,0,0)}90%{transform:translate3d(-5px,0,0)}to{transform:none}}@-webkit-keyframes Toastify__bounceOutRight{20%{opacity:1;transform:translate3d(-20px,0,0)}to{opacity:0;transform:translate3d(2000px,0,0)}}@keyframes Toastify__bounceOutRight{20%{opacity:1;transform:translate3d(-20px,0,0)}to{opacity:0;transform:translate3d(2000px,0,0)}}@-webkit-keyframes Toastify__bounceInLeft{0%,60%,75%,90%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;transform:translate3d(-3000px,0,0)}60%{opacity:1;transform:translate3d(25px,0,0)}75%{transform:translate3d(-10px,0,0)}90%{transform:translate3d(5px,0,0)}to{transform:none}}@keyframes Toastify__bounceInLeft{0%,60%,75%,90%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;transform:translate3d(-3000px,0,0)}60%{opacity:1;transform:translate3d(25px,0,0)}75%{transform:translate3d(-10px,0,0)}90%{transform:translate3d(5px,0,0)}to{transform:none}}@-webkit-keyframes Toastify__bounceOutLeft{20%{opacity:1;transform:translate3d(20px,0,0)}to{opacity:0;transform:translate3d(-2000px,0,0)}}@keyframes Toastify__bounceOutLeft{20%{opacity:1;transform:translate3d(20px,0,0)}to{opacity:0;transform:translate3d(-2000px,0,0)}}@-webkit-keyframes Toastify__bounceInUp{0%,60%,75%,90%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;transform:translate3d(0,3000px,0)}60%{opacity:1;transform:translate3d(0,-20px,0)}75%{transform:translate3d(0,10px,0)}90%{transform:translate3d(0,-5px,0)}to{transform:translateZ(0)}}@keyframes Toastify__bounceInUp{0%,60%,75%,90%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;transform:translate3d(0,3000px,0)}60%{opacity:1;transform:translate3d(0,-20px,0)}75%{transform:translate3d(0,10px,0)}90%{transform:translate3d(0,-5px,0)}to{transform:translateZ(0)}}@-webkit-keyframes Toastify__bounceOutUp{20%{transform:translate3d(0,-10px,0)}40%,45%{opacity:1;transform:translate3d(0,20px,0)}to{opacity:0;transform:translate3d(0,-2000px,0)}}@keyframes Toastify__bounceOutUp{20%{transform:translate3d(0,-10px,0)}40%,45%{opacity:1;transform:translate3d(0,20px,0)}to{opacity:0;transform:translate3d(0,-2000px,0)}}@-webkit-keyframes Toastify__bounceInDown{0%,60%,75%,90%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;transform:translate3d(0,-3000px,0)}60%{opacity:1;transform:translate3d(0,25px,0)}75%{transform:translate3d(0,-10px,0)}90%{transform:translate3d(0,5px,0)}to{transform:none}}@keyframes Toastify__bounceInDown{0%,60%,75%,90%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;transform:translate3d(0,-3000px,0)}60%{opacity:1;transform:translate3d(0,25px,0)}75%{transform:translate3d(0,-10px,0)}90%{transform:translate3d(0,5px,0)}to{transform:none}}@-webkit-keyframes Toastify__bounceOutDown{20%{transform:translate3d(0,10px,0)}40%,45%{opacity:1;transform:translate3d(0,-20px,0)}to{opacity:0;transform:translate3d(0,2000px,0)}}@keyframes Toastify__bounceOutDown{20%{transform:translate3d(0,10px,0)}40%,45%{opacity:1;transform:translate3d(0,-20px,0)}to{opacity:0;transform:translate3d(0,2000px,0)}}.Toastify__bounce-enter--bottom-left,.Toastify__bounce-enter--top-left{-webkit-animation-name:Toastify__bounceInLeft;animation-name:Toastify__bounceInLeft}.Toastify__bounce-enter--bottom-right,.Toastify__bounce-enter--top-right{-webkit-animation-name:Toastify__bounceInRight;animation-name:Toastify__bounceInRight}.Toastify__bounce-enter--top-center{-webkit-animation-name:Toastify__bounceInDown;animation-name:Toastify__bounceInDown}.Toastify__bounce-enter--bottom-center{-webkit-animation-name:Toastify__bounceInUp;animation-name:Toastify__bounceInUp}.Toastify__bounce-exit--bottom-left,.Toastify__bounce-exit--top-left{-webkit-animation-name:Toastify__bounceOutLeft;animation-name:Toastify__bounceOutLeft}.Toastify__bounce-exit--bottom-right,.Toastify__bounce-exit--top-right{-webkit-animation-name:Toastify__bounceOutRight;animation-name:Toastify__bounceOutRight}.Toastify__bounce-exit--top-center{-webkit-animation-name:Toastify__bounceOutUp;animation-name:Toastify__bounceOutUp}.Toastify__bounce-exit--bottom-center{-webkit-animation-name:Toastify__bounceOutDown;animation-name:Toastify__bounceOutDown}@-webkit-keyframes Toastify__zoomIn{0%{opacity:0;transform:scale3d(.3,.3,.3)}50%{opacity:1}}@keyframes Toastify__zoomIn{0%{opacity:0;transform:scale3d(.3,.3,.3)}50%{opacity:1}}@-webkit-keyframes Toastify__zoomOut{0%{opacity:1}50%{opacity:0;transform:scale3d(.3,.3,.3)}to{opacity:0}}@keyframes Toastify__zoomOut{0%{opacity:1}50%{opacity:0;transform:scale3d(.3,.3,.3)}to{opacity:0}}.Toastify__zoom-enter{-webkit-animation-name:Toastify__zoomIn;animation-name:Toastify__zoomIn}.Toastify__zoom-exit{-webkit-animation-name:Toastify__zoomOut;animation-name:Toastify__zoomOut}@-webkit-keyframes Toastify__flipIn{0%{transform:perspective(400px) rotateX(90deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in;opacity:0}40%{transform:perspective(400px) rotateX(-20deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}60%{transform:perspective(400px) rotateX(10deg);opacity:1}80%{transform:perspective(400px) rotateX(-5deg)}to{transform:perspective(400px)}}@keyframes Toastify__flipIn{0%{transform:perspective(400px) rotateX(90deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in;opacity:0}40%{transform:perspective(400px) rotateX(-20deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}60%{transform:perspective(400px) rotateX(10deg);opacity:1}80%{transform:perspective(400px) rotateX(-5deg)}to{transform:perspective(400px)}}@-webkit-keyframes Toastify__flipOut{0%{transform:perspective(400px)}30%{transform:perspective(400px) rotateX(-20deg);opacity:1}to{transform:perspective(400px) rotateX(90deg);opacity:0}}@keyframes Toastify__flipOut{0%{transform:perspective(400px)}30%{transform:perspective(400px) rotateX(-20deg);opacity:1}to{transform:perspective(400px) rotateX(90deg);opacity:0}}.Toastify__flip-enter{-webkit-animation-name:Toastify__flipIn;animation-name:Toastify__flipIn}.Toastify__flip-exit{-webkit-animation-name:Toastify__flipOut;animation-name:Toastify__flipOut}@-webkit-keyframes Toastify__slideInRight{0%{transform:translate3d(110%,0,0);visibility:visible}to{transform:translateZ(0)}}@keyframes Toastify__slideInRight{0%{transform:translate3d(110%,0,0);visibility:visible}to{transform:translateZ(0)}}@-webkit-keyframes Toastify__slideInLeft{0%{transform:translate3d(-110%,0,0);visibility:visible}to{transform:translateZ(0)}}@keyframes Toastify__slideInLeft{0%{transform:translate3d(-110%,0,0);visibility:visible}to{transform:translateZ(0)}}@-webkit-keyframes Toastify__slideInUp{0%{transform:translate3d(0,110%,0);visibility:visible}to{transform:translateZ(0)}}@keyframes Toastify__slideInUp{0%{transform:translate3d(0,110%,0);visibility:visible}to{transform:translateZ(0)}}@-webkit-keyframes Toastify__slideInDown{0%{transform:translate3d(0,-110%,0);visibility:visible}to{transform:translateZ(0)}}@keyframes Toastify__slideInDown{0%{transform:translate3d(0,-110%,0);visibility:visible}to{transform:translateZ(0)}}@-webkit-keyframes Toastify__slideOutRight{0%{transform:translateZ(0)}to{visibility:hidden;transform:translate3d(110%,0,0)}}@keyframes Toastify__slideOutRight{0%{transform:translateZ(0)}to{visibility:hidden;transform:translate3d(110%,0,0)}}@-webkit-keyframes Toastify__slideOutLeft{0%{transform:translateZ(0)}to{visibility:hidden;transform:translate3d(-110%,0,0)}}@keyframes Toastify__slideOutLeft{0%{transform:translateZ(0)}to{visibility:hidden;transform:translate3d(-110%,0,0)}}@-webkit-keyframes Toastify__slideOutDown{0%{transform:translateZ(0)}to{visibility:hidden;transform:translate3d(0,500px,0)}}@keyframes Toastify__slideOutDown{0%{transform:translateZ(0)}to{visibility:hidden;transform:translate3d(0,500px,0)}}@-webkit-keyframes Toastify__slideOutUp{0%{transform:translateZ(0)}to{visibility:hidden;transform:translate3d(0,-500px,0)}}@keyframes Toastify__slideOutUp{0%{transform:translateZ(0)}to{visibility:hidden;transform:translate3d(0,-500px,0)}}.Toastify__slide-enter--bottom-left,.Toastify__slide-enter--top-left{-webkit-animation-name:Toastify__slideInLeft;animation-name:Toastify__slideInLeft}.Toastify__slide-enter--bottom-right,.Toastify__slide-enter--top-right{-webkit-animation-name:Toastify__slideInRight;animation-name:Toastify__slideInRight}.Toastify__slide-enter--top-center{-webkit-animation-name:Toastify__slideInDown;animation-name:Toastify__slideInDown}.Toastify__slide-enter--bottom-center{-webkit-animation-name:Toastify__slideInUp;animation-name:Toastify__slideInUp}.Toastify__slide-exit--bottom-left,.Toastify__slide-exit--top-left{-webkit-animation-name:Toastify__slideOutLeft;animation-name:Toastify__slideOutLeft}.Toastify__slide-exit--bottom-right,.Toastify__slide-exit--top-right{-webkit-animation-name:Toastify__slideOutRight;animation-name:Toastify__slideOutRight}.Toastify__slide-exit--top-center{-webkit-animation-name:Toastify__slideOutUp;animation-name:Toastify__slideOutUp}.Toastify__slide-exit--bottom-center{-webkit-animation-name:Toastify__slideOutDown;animation-name:Toastify__slideOutDown}
|
|
2
|
-
/*# sourceMappingURL=2.d34346ea.chunk.css.map */
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../scss/_toastContainer.scss","../scss/_variables.scss","ReactToastify.css","../scss/_toast.scss","../scss/_closeButton.scss","../scss/_progressBar.scss","../scss/animations/_bounce.scss","../scss/animations/_zoom.scss","../scss/animations/_flip.scss","../scss/animations/_slide.scss"],"names":[],"mappings":"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","file":"2.d34346ea.chunk.css"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
.navbar{position:-webkit-sticky!important;position:sticky!important;top:0;z-index:5;margin-bottom:2rem;padding:.8rem 1rem;min-height:4.7793rem}.loader{height:100vh}.backdrop,.loader{z-index:10;display:flex;justify-content:center;align-items:center}.backdrop{position:fixed;width:100%;height:100%;background-color:#222;opacity:0;visibility:hidden;transition:all .2s ease;cursor:default;flex-direction:column;text-align:center}.backdrop--visible{opacity:.94;visibility:visible}.body--backdrop{overflow:hidden}.player{width:100%;max-width:450px;display:flex;flex-direction:column;justify-content:space-between;align-items:center}.player-logo{width:130px}@media (max-height:430px){.player-logo{display:none}}.streams{max-width:450px}.streams__item{cursor:pointer}.streams__item.active{cursor:default}.streams__header{font-size:1.3rem;margin-top:1em;padding:.5rem 1.25rem}.mini-player{display:flex;align-items:center;justify-content:space-between}.mini-player button{padding:10px 20px}.mini-player__left{max-width:calc(100vw - 160px);margin-right:1rem}.drawer{z-index:5!important;height:5rem;cursor:pointer;touch-action:none;display:flex;align-items:center;transition:height .25s ease-out}.drawer>.mini-player{flex-grow:1;margin:0 .5rem 0 .25rem}.drawer--open{height:100%;flex-direction:column;justify-content:flex-end}.drawer--open .player{flex-grow:1}.drawer--open .drawer__toggler{margin-bottom:20px}@media (max-width:770px){.body--drawer{overflow:hidden}}.main__primary{margin-bottom:7rem}.main__primary .player{display:none}.main__primary .streams{margin:0 auto}@media (min-width:770px){.main__primary{margin-bottom:2rem;display:flex;justify-content:space-between}.main__primary>*{min-width:0;width:100%}.main__primary .player{display:inherit;position:-webkit-sticky;position:sticky;top:6.7793rem;margin-left:2rem;height:calc(100vh - 8.7793rem);max-height:550px}.main__primary .streams{margin:0}.drawer{display:none}}html{height:100%}body{min-height:100%;overflow-y:scroll}button[disabled]{cursor:default}.ellipsis{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
|
2
|
-
/*# sourceMappingURL=main.221e80d3.chunk.css.map */
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["navBar.scss","../_variables.scss","loader.scss","backdrop.scss","player.scss","streams.scss","miniPlayer.scss","drawer.scss","main.scss","index.scss"],"names":[],"mappings":"AAEA,QACE,iCAA2B,CAA3B,yBAA2B,CAC3B,KAAM,CACN,SAAU,CACV,kBCFe,CDKf,kBAAoB,CAEpB,oBCRoB,CCHtB,QAKE,YAAa,CCLf,kBDCE,UAAW,CACX,YAAa,CACb,sBAAuB,CACvB,kBCUkB,CAdpB,UAEE,cAAe,CACf,UAAW,CACX,WAAY,CACZ,qBAAyB,CACzB,SAAU,CACV,iBAAkB,CAClB,uBAAyB,CACzB,cAAe,CAEf,qBAAsB,CAGtB,iBAAkB,CAElB,mBACE,WAAa,CACb,kBAAmB,CACpB,gBAID,eAAgB,CCrBlB,QACE,UAAW,CACX,eAAgB,CAChB,YAAa,CACb,qBAAsB,CACtB,6BAA8B,CAC9B,kBAAmB,CACpB,aAGC,WAAY,CACb,0BAGC,aACE,YAAa,CACd,CChBH,SACE,eAAgB,CACjB,eAGC,cAAe,CADjB,sBAII,cAAe,CAChB,iBAID,gBAAiB,CACjB,cAAe,CACf,qBAAuB,CCjBzB,aACE,YAAa,CACb,kBAAmB,CACnB,6BAA8B,CAHhC,oBAMI,iBAAkB,CACnB,mBAKD,6BAA8B,CAC9B,iBAAkB,CCXpB,QACE,mBAAqB,CACrB,WNFkB,CMGlB,cAAe,CACf,iBAAkB,CAClB,YAAa,CACb,kBAAmB,CACnB,+BAAiC,CAPnC,qBAUI,WAAY,CACZ,uBAA0B,CAC3B,cAGC,WAAY,CACZ,qBAAsB,CACtB,wBAAyB,CAH1B,sBAMG,WAAY,CANf,+BAUG,kBAAmB,CACpB,yBAOH,cACE,eAAgB,CACjB,CChCH,eACE,kBAAuC,CADzC,uBAII,YAAa,CAJjB,wBAQI,aAAc,CACf,yBAID,eACE,kBAhBS,CAiBT,YAAa,CACb,6BAA8B,CAHhC,iBAMI,WAAY,CACZ,UAAW,CAPf,uBAWI,eAAgB,CAChB,uBAAgB,CAAhB,eAAgB,CAChB,aPzB8B,CO0B9B,gBAAiB,CACjB,8BAA4C,CAC5C,gBAAiB,CAhBrB,wBAoBI,QAAS,CACV,QAID,YAAa,CACd,CC3CH,KACE,WAAY,CACb,KAGC,eAAgB,CAChB,iBAAkB,CACnB,iBAGC,cAAe,CAChB,UAGC,kBAAmB,CACnB,eAAgB,CAChB,sBAAuB","file":"main.221e80d3.chunk.css","sourcesContent":["@import '../variables';\n\n.navbar {\n position: sticky !important;\n top: 0;\n z-index: 5;\n margin-bottom: $nav-margin;\n // The following let us have the same height on all themes.\n // 1. prevent lux to increment padding\n padding: 0.8rem 1rem;\n // 2. make darkly as high as lux\n min-height: $nav-height;\n}\n","$for-medium-up: 770px;\n$for-short-down: 430px;\n$drawer-height: 5rem;\n$nav-height: 4.7793rem; // calculated value for higher theme\n$nav-margin: 2rem;\n$nav-size: $nav-height + $nav-margin;\n",".loader {\n z-index: 10;\n display: flex;\n justify-content: center;\n align-items: center;\n height: 100vh;\n}\n",".backdrop {\n z-index: 10;\n position: fixed;\n width: 100%;\n height: 100%;\n background-color: #222222;\n opacity: 0;\n visibility: hidden;\n transition: all 0.2s ease;\n cursor: default;\n display: flex;\n flex-direction: column;\n justify-content: center;\n align-items: center;\n text-align: center;\n\n &--visible {\n opacity: 0.94;\n visibility: visible;\n }\n}\n\n.body--backdrop {\n overflow: hidden;\n}\n","@import '../../variables';\n\n.player {\n width: 100%;\n max-width: 450px;\n display: flex;\n flex-direction: column;\n justify-content: space-between;\n align-items: center;\n}\n\n.player-logo {\n width: 130px;\n}\n\n@media(max-height: $for-short-down) {\n .player-logo {\n display: none;\n }\n}\n","@import '../variables';\n\n.streams {\n max-width: 450px;\n}\n\n.streams__item {\n cursor: pointer;\n\n &.active {\n cursor: default;\n }\n}\n\n.streams__header {\n font-size: 1.3rem;\n margin-top: 1em;\n padding: 0.5rem 1.25rem;\n}\n",".mini-player {\n display: flex;\n align-items: center;\n justify-content: space-between;\n\n button {\n padding: 10px 20px;\n }\n}\n\n.mini-player__left {\n // Dirty workaround for ellipsis to work\n max-width: calc(100vw - 160px);\n margin-right: 1rem;\n}\n","@import '../variables';\n\n.drawer {\n z-index: 5 !important;\n height: $drawer-height;\n cursor: pointer;\n touch-action: none; // don't scroll on touch\n display: flex;\n align-items: center;\n transition: height 0.25s ease-out;\n\n & > .mini-player {\n flex-grow: 1;\n margin: 0 0.5rem 0 0.25rem;\n }\n\n &--open {\n height: 100%;\n flex-direction: column;\n justify-content: flex-end;\n\n .player {\n flex-grow: 1;\n }\n\n .drawer__toggler {\n margin-bottom: 20px;\n }\n }\n}\n\n// The media query is for the edge case of an open drawer and the\n// window resized past the breakpoint. This brings the scrollbar back.\n@media (max-width: $for-medium-up) {\n .body--drawer {\n overflow: hidden;\n }\n}\n","@import '../variables';\n\n$margin: 2rem;\n\n.main__primary {\n margin-bottom: $margin + $drawer-height;\n\n .player {\n display: none;\n }\n\n .streams {\n margin: 0 auto;\n }\n}\n\n@media (min-width: $for-medium-up) {\n .main__primary {\n margin-bottom: $margin; /* no drawer */\n display: flex;\n justify-content: space-between;\n\n & > * {\n min-width: 0; /* don't get bigger when text overflows */\n width: 100%; /* divide space equally */\n }\n\n .player {\n display: inherit;\n position: sticky;\n top: $nav-size;\n margin-left: 2rem;\n height: calc(100vh - #{$nav-size + $margin});\n max-height: 550px;\n }\n\n .streams {\n margin: 0;\n }\n }\n\n .drawer {\n display: none;\n }\n}\n","html {\n height: 100%;\n}\n\nbody {\n min-height: 100%;\n overflow-y: scroll; // so elements don't move if page fits view\n}\n\nbutton[disabled] {\n cursor: default;\n}\n\n.ellipsis {\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n"]}
|
|
@@ -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
|
|
@@ -1 +0,0 @@
|
|
|
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 <nav className=\"navbar navbar-expand-sm navbar-dark bg-primary\">\n <div className=\"container\">\n <a className=\"navbar-brand\" href=\"/\">\n <img\n src={logo}\n width=\"30\"\n height=\"30\"\n className=\"d-inline-block align-text-bottom mr-2\"\n alt=\"\"\n />\n PiFi Radio\n </a>\n <button\n className=\"navbar-toggler\"\n type=\"button\"\n data-toggle=\"collapse\"\n data-target=\"#navbarNavAltMarkup\"\n aria-controls=\"navbarNavAltMarkup\"\n aria-expanded=\"false\"\n aria-label=\"Toggle navigation\"\n >\n <span className=\"navbar-toggler-icon\"></span>\n </button>\n <div className=\"collapse navbar-collapse\" id=\"navbarNavAltMarkup\">\n <div className=\"navbar-nav pt-1 ml-2\">\n {/* We use buttons and different class names instead of Bootstrap's\n anchor, so we don't get a warning for href=\"#\". */}\n <button\n className=\"btn btn-link nav-link\"\n data-toggle=\"modal\"\n data-target=\"#url-dialog\"\n >\n {t('playURL')}\n </button>\n\n <button\n className=\"btn btn-link nav-link\"\n data-toggle=\"modal\"\n data-target=\"#settings\"\n >\n {t('settings')}\n </button>\n\n <button\n className=\"btn btn-link nav-link\"\n data-toggle=\"modal\"\n data-target=\"#about\"\n >\n {t('about')}\n </button>\n </div>\n </div>\n </div>\n </nav>\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 <button className=\"btn btn-secondary\" data-dismiss=\"modal\">\n {t('close')}\n </button>\n );\n\n return (\n <div\n className=\"modal fade\"\n id={id}\n tabIndex=\"-1\"\n role=\"dialog\"\n aria-labelledby=\"staticBackdropLabel\"\n aria-hidden=\"true\"\n >\n <div className=\"modal-dialog\" role=\"document\">\n <div className=\"modal-content\">\n <div className=\"modal-header\">\n <h5 className=\"modal-title\" id=\"staticBackdropLabel\">\n {title}\n </h5>\n <button\n type=\"button\"\n className=\"close\"\n data-dismiss=\"modal\"\n aria-label=\"Close\"\n >\n <span aria-hidden=\"true\">×</span>\n </button>\n </div>\n <div className=\"modal-body\">{children}</div>\n <div className=\"modal-footer\">{footer ? footer : defaultFooter}</div>\n </div>\n </div>\n </div>\n );\n};\n\nexport default Modal;\n","import React from 'react';\n\nconst Select = ({ id, label, row, data, ...rest }) => (\n <div className={row ? 'form-group row' : 'form-group'}>\n <label htmlFor={id} className=\"col-sm-2 col-form-label\">\n {label}\n </label>\n <div className=\"col-sm-10\">\n <select id={id} className=\"form-control\" {...rest}>\n {data.map(d => (\n <option key={d.id || d} value={d.id || d}>\n {d.name || d}\n </option>\n ))}\n </select>\n </div>\n </div>\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 <Modal id=\"settings\" title={t('settings')}>\n <Select\n id=\"theme-select\"\n label={t('theme')}\n data={theme.availableThemes}\n row\n value={themeId}\n onChange={e => handleThemeChange(e)}\n />\n <Select\n id=\"language-select\"\n label={t('language')}\n data={languagesData}\n row\n value={i18n.language}\n onChange={e => i18n.changeLanguage(e.target.value)}\n />\n </Modal>\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(<Translation>{t => t('errorUnexpected')}</Translation>);\n\n // Universal expected error\n if (error.response && error.response.status === 403)\n toast.error(<Translation>{t => t('errorForbidden')}</Translation>);\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 <React.Fragment>\n <button\n className=\"btn btn-primary\"\n data-dismiss=\"modal\"\n onClick={handleOK}\n >\n {t('ok')}\n </button>\n <button\n className=\"btn btn-secondary\"\n onClick={() => setURL('')}\n data-dismiss=\"modal\"\n >\n {t('cancel')}\n </button>\n </React.Fragment>\n );\n\n return (\n <Modal id=\"url-dialog\" title={t('playURL')} footer={renderFooter()}>\n <input\n className=\"form-control mb-4\"\n type=\"text\"\n placeholder=\"URL\"\n value={url}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n />\n </Modal>\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 <div className=\"loader\">\n <div className=\"spinner-border\" role=\"status\">\n <span className=\"sr-only\">Loading...</span>\n </div>\n </div>\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 <Loader />;\n\n return (\n <table className=\"table\">\n <tbody>\n {tableData.map((item) => (\n <tr key={item.label}>\n <th scope=\"row\">{item.label}</th>\n <td>{item.value}</td>\n </tr>\n ))}\n </tbody>\n </table>\n );\n };\n\n const copyright = (\n <div className=\"copyright small mt-5\">\n <p>\n <a\n href=\"https://rafaelc.org/pifi\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n style={{ color: 'inherit' }}\n >\n {t('goToDocs')}\n </a>\n </p>\n <p>\n Copyright © 2017-2020 \n {/* Use the default color, as some themes give a different color for links. */}\n <a\n href=\"https://rafaelc.org/\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n style={{ color: 'inherit' }}\n >\n Rafael Cavalcanti\n </a>\n </p>\n </div>\n );\n\n const coffee = (\n <div className=\"coffee mt-5\">\n <p>{t('coffee')}</p>\n <a\n href=\"https://www.buymeacoffee.com/rafaelc\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n <img\n src=\"https://cdn.buymeacoffee.com/buttons/default-blue.png\"\n alt=\"Buy Me A Coffee\"\n style={{ height: 51, width: 217 }}\n />\n </a>\n </div>\n );\n\n return (\n <Modal id=\"about\" title={t('about')}>\n {renderTable()}\n {coffee}\n {copyright}\n </Modal>\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 <div className={classes}>\n <h3 className=\"text-white\">{title}</h3>\n <h5 className=\"text-white\">{body}</h5>\n </div>\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 <div className=\"text-center w-100\">\n <h5 className=\"small text-uppercase\">\n {playing ? t('playing') : t('stopped')}\n </h5>\n <h3 className=\"ellipsis\">{title}</h3>\n </div>\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 <button className=\"btn btn-danger\" onClick={stop} aria-label=\"Stop\">\n <FontAwesomeIcon icon={faStop} />\n </button>\n ) : (\n <button className=\"btn btn-dark\" onClick={play} aria-label=\"Play\">\n <FontAwesomeIcon icon={faPlay} />\n </button>\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 <button\n className=\"btn btn-dark p-3\"\n disabled={volDisabled}\n onClick={() => handleVolChange(delta)}\n aria-label={label}\n >\n <FontAwesomeIcon icon={icon} />\n </button>\n );\n\n return (\n <div\n className=\"player-controls btn-group w-100 m-2\"\n onClick={e => e.stopPropagation()}\n >\n {renderVolButton('-5', faVolumeDown, 'Volume down')}\n {renderVolButton('+5', faVolumeUp, 'Volume up')}\n <PlayStopControl playing={playerStatus.playing} />\n </div>\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 <img\n src={require('../../assets/logo.svg')}\n alt=\"Logo\"\n className=\"player-logo m-4\"\n />\n );\n\n return (\n <div className=\"player\">\n <PlayerStatus playerStatus={playerStatus} />\n {renderLogo()}\n <PlayerControls playerStatus={playerStatus} />\n </div>\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 <input\n className=\"form-control mb-4\"\n type=\"text\"\n id=\"query\"\n placeholder={t('search')}\n aria-label={t('search')}\n autoComplete=\"off\"\n value={value}\n onChange={e => onChange(e.target.value)}\n onFocus={() => onChange('')}\n ></input>\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 <h4 className=\"p-4\">{this.props.t('noStreams')}</h4>;\n\n return (\n <ul className=\"list-group list-group-flush\">\n {Object.keys(streams).map(name =>\n streams[name] ? (\n <li className=\"streams__header ellipsis\" key={name}>\n {name}\n </li>\n ) : (\n <li\n className={this.getItemClasses(name)}\n key={name}\n onClick={() => this.handleItemClick(name)}\n >\n {name}\n </li>\n )\n )}\n </ul>\n );\n }\n\n render() {\n if (this.state.loading) return <Loader />;\n\n return (\n <div className=\"streams\">\n <SearchBox value={this.state.query} onChange={this.handleSearch} />\n {this.renderList()}\n </div>\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 <div className=\"mini-player\">\n <div className=\"mini-player__left ellipsis\">\n {title}\n </div>\n <div\n className=\"mini-player__right\"\n onClick={e => e.stopPropagation()}\n >\n <PlayStopControl playing={playing} />\n </div>\n </div>\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 <button\n className=\"drawer__toggler btn btn-primary-outline\"\n aria-label=\"Toggle player\"\n >\n <FontAwesomeIcon\n icon={this.state.open ? faChevronDown : faChevronUp}\n className=\"fa-lg\"\n />\n </button>\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 <div\n className={classes}\n onClick={this.handleClick}\n onTouchStart={this.handleTouchStart}\n onTouchMove={this.handleTouchMove}\n >\n {this.renderToggleButton()}\n {open ? (\n <Player playerStatus={playerStatus} />\n ) : (\n <MiniPlayer playerStatus={playerStatus} />\n )}\n </div>\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 <main className=\"main\">\n <Drawer playerStatus={playerStatus} />\n <div className=\"main__primary container\">\n <Streams onBackdrop={onBackdrop} playerStatus={playerStatus} />\n <Player playerStatus={playerStatus} />\n </div>\n </main>\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 <Backdrop title={t('errorNetwork')} />;\n if (loading) return <Loader />;\n if (!playerStatus.con_mpd) return <Backdrop title={t('disconnectedMPD')} />;\n\n return (\n <div className=\"app\">\n <ToastContainer pauseOnFocusLoss={false} />\n <Backdrop title={backdrop.title} body={backdrop.body} />\n <NavBar />\n <Main onBackdrop={this.handleBackdrop} playerStatus={playerStatus} />\n <URLDialog />\n <Settings />\n <About />\n </div>\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 <Suspense fallback={<Loader />}>\n <App />\n </Suspense>,\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":""}
|