summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/index.css128
-rw-r--r--src/index.html260
2 files changed, 388 insertions, 0 deletions
diff --git a/src/index.css b/src/index.css
new file mode 100644
index 0000000..497da7d
--- /dev/null
+++ b/src/index.css
@@ -0,0 +1,128 @@
+#raw_json{
+ display: none;
+ overflow-y: scroll;
+ height: 400px;
+ width: 90%;
+ border: 2px solid black;
+ white-space: pre-wrap;
+}
+
+
+#volumes_control{
+ position: relative;
+ overflow-y: scroll;
+ max-width: 600px;
+ height: 500px;
+ border: 2px solid black;
+ padding: 10px;
+}
+#volumes_control > div{
+ display: flex;
+ background-color: rgb(230,230,230);
+ margin-bottom: 3px;
+ align-content: flex-start;
+ justify-content: center;
+ grid-gap: 3px;
+ padding: 3px;
+}
+#volumes_control textarea{
+ border: 2px inset rgb(120,120,120);
+ font-size: 15px;
+ width: 180px;
+ height: 15px;
+ resize: none;
+ overflow: hidden;
+}
+#volumes_control button{
+ height: 20px;
+ min-width: 20px;
+ align-items: center;
+ justify-items: center;
+}
+#volume_wrap{
+ position: relative;
+ max-width: 600px;
+}
+#vol_update_button{
+ background-color: rgb(200,200,200);
+ border: 2px solid black;
+ position: absolute;
+ display: block;
+ width: 100px;
+ height: 15px;
+ padding: 3px;
+ bottom: 3px;
+ left: calc(50% - 50px);
+ user-select: none;
+}
+#vol_update_button:hover{
+ background-color: rgb(190,190,190);
+}
+
+.vol_update_button_tooltip{
+ visibility: hidden;
+ position: absolute;
+ width: 120px;
+ left: calc(50% - (120px/2));
+ bottom: 50px;
+ border: 2px solid black;
+ padding: 3px;
+ background-color: rgb(260,260,260);
+ border-radius: 10px;
+}
+.vol_update_button_wrap:hover .vol_update_button_tooltip{
+ visibility: visible;
+}
+
+#vol_add_button{
+ background-color: rgb(200,200,200);
+ border: 2px solid black;
+ position: absolute;
+ display: block;
+ width: 50px;
+ height: 15px;
+ padding: 3px;
+ bottom: 3px;
+ left: 65%;
+ user-select: none;
+}
+
+
+.play_grid,.show_grid{
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ border: 2px solid black;
+ padding: 4px;
+}
+#airtime_next,#airtime_next_show{
+ border-left: 2px dashed rgb(120,120,120);
+ padding-left: 10px;
+}
+#airtime_np,#airtime_np_show{
+ padding-right: 5px;
+}
+
+#move_button{
+ position: absolute;
+ padding: 3px;
+ top: 5px;
+ right: 5px;
+ user-select: none;
+ border: 2px solid black;
+}
+
+#background_plate{
+ position: fixed;
+ left: 0px;
+ top: 0px;
+ width: 100vw;
+ height: 100vh;
+ background-color: rgba(255,255,255,1);
+ z-index: -1;
+}
+
+#error_box{
+ display: none;
+ padding: 4px;
+ background-color: rgba(255,50,50);
+} \ No newline at end of file
diff --git a/src/index.html b/src/index.html
new file mode 100644
index 0000000..8ea032f
--- /dev/null
+++ b/src/index.html
@@ -0,0 +1,260 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <title></title>
+ <link rel="stylesheet" href="index.css">
+</head>
+<body>
+ <div id="background_plate"></div>
+ <div id="error_box"></div>
+
+ <audio controls="controls" id="airtime_radio"></audio>
+ <div id="move_button">click to drag</div>
+
+ <div class="play_grid">
+ <div id="airtime_np"></div>
+ <div id="airtime_next"></div>
+ </div>
+ <div class="show_grid">
+ <div id="airtime_np_show"></div>
+ <div id="airtime_next_show"></div>
+ </div>
+ <div id="curr_date"></div>
+
+ <br>
+ <p>volumes for different things</p>
+ <div id="volume_wrap">
+ <div id="volumes_control"></div>
+ <div class="vol_update_button_wrap">
+ <div align="center" id="vol_update_button" onClick="update_conf()">
+ update
+ </div>
+ <span class="vol_update_button_tooltip">please dont spam this button</span>
+ <div align="center" id="vol_add_button" onClick="add_conf()">add</div>
+ </div>
+ </div>
+
+ <br><br>
+ <button onclick="toggle_raw_json()">toggle raw json data</button><br><br>
+ <div id="raw_json"></div>
+
+ <script language="javascript">
+ const fs=require('fs'),
+ path=require("path"),
+ {ipcRenderer}=require('electron');
+
+ //error box func
+ function set_error_box(err){
+ error_box.style.display="block";
+ error_box.innerHTML=err
+ }
+
+ //fetch config
+ let config_data={}
+ function fetch_config(){
+ try{
+ config_data=JSON.parse(fs.readFileSync(path.join(__dirname,"..","config.json")));
+ config_data["error"]=false
+ } catch(err){
+ config_data={err:err.toString(),"error":true}
+ set_error_box("config error:: "+err)
+ return
+ }
+ airtime_radio.innerHTML='<source src="'+config_data["airtime_data"]["stream_url"]
+ +'" type="audio/mp3">Your browser does not support the audio element.'
+
+ volumes_str=""
+ for(let i in config_data.volumes){
+ if(!config_data.volumes[i].default){
+ volumes_str+='<div id="volumes_control_'+i+'">'+
+ '<textarea style="resize: vertical;"></textarea> name:<textarea></textarea>volume: <input type="number" min="0" max="1"></input>'+
+ '<button onclick="move_conf_vol('+i+',\'+\')">+</button>'+
+ '<button onclick="move_conf_vol('+i+',\'-\')">-</button>'+
+ '<button onclick="del_conf('+i+')">del</button>'+
+ '</div>'
+ setTimeout(()=>{
+ document.getElementById("volumes_control_"+i).children[0].value=config_data.volumes[i].lookfor[0]
+ document.getElementById("volumes_control_"+i).children[1].value=config_data.volumes[i].lookfor[1]
+ document.getElementById("volumes_control_"+i).children[2].value=config_data.volumes[i].volume
+ },250)
+ } else {
+ volumes_str+='<div id="volumes_control_'+i+'">'+'default: <textarea></textarea></div>'
+ setTimeout(()=>{
+ document.getElementById("volumes_control_"+i).children[0].value=config_data.volumes[i].default
+ },250)
+ }
+ }
+ volumes_str+='<div id="spacer" style="background-color: rgba(0,0,0,0); margin-bottom: 20px"></div>'
+ volumes_control.innerHTML=volumes_str
+ }
+ console.log(fetch_config());
+
+ //move volume config
+ function move_conf_vol(id,dir){
+ if(dir=="+"){
+ arraymove(config_data.volumes,id,id-1)
+ }
+ if(dir=="-"){
+ arraymove(config_data.volumes,id,id+1)
+ }
+ if(config_data.volumes[1].default){
+ arraymove(config_data.volumes,1,0)
+ }
+ fs.writeFileSync(path.join(__dirname,"..","config.json"),JSON.stringify(config_data,null,2))
+ fetch_config()
+ }
+
+ //misc function to move arrays via index to index
+ function arraymove(arr, fromIndex, toIndex) {
+ let element = arr[fromIndex];
+ arr.splice(fromIndex, 1);
+ arr.splice(toIndex, 0, element);
+ return arr
+ }
+
+ //edit config
+ function update_conf(){
+ for(i in config_data.volumes){
+ if(config_data.volumes[i].default){
+ config_data.volumes[i].default=volumes_control.children[i].children[0].value
+ } else {
+ config_data.volumes[i].lookfor[0]=volumes_control.children[i].children[0].value.split(",")
+ config_data.volumes[i].lookfor[1]=volumes_control.children[i].children[1].value
+ config_data.volumes[i].volume=parseFloat(volumes_control.children[i].children[2].value)
+ }
+
+ }
+ fs.writeFileSync(path.join(__dirname,"..","config.json"),JSON.stringify(config_data,null,2))
+ fetch_config()
+ fetch_api_data()
+ }
+
+ //del config
+ function del_conf(id){
+ config_data.volumes.splice(id,1)
+ fs.writeFileSync(path.join(__dirname,"..","config.json"),JSON.stringify(config_data,null,2))
+ fetch_config()
+ fetch_api_data()
+ }
+
+ //addconf
+ function add_conf(){
+ config_data.volumes.push({"lookfor":[["currentShow",0,"name"],"n/a"],"volume":0.5})
+ fs.writeFileSync(path.join(__dirname,"..","config.json"),JSON.stringify(config_data,null,2))
+ fetch_config()
+ fetch_api_data()
+ }
+
+ //fetch api data and use it??
+ async function fetch_api_data(){
+ if(config_data["airtime_data"]["api_url"]&&config_data["airtime_data"]["api_url"]!=""){
+ await fetch(config_data["airtime_data"]["api_url"],{cache:"no-cache"})
+ .then(res=>res.json())
+ .then(res=>{
+ api_data=res;
+ raw_json.innerHTML=JSON.stringify(res, null, 4); //put in the raw json data in json box
+ np_next(res)
+ //set volume based on "volumes" config
+ set_volume(res)
+ set_date();
+ });
+ return true
+ } else {
+ return "api not set"
+ }
+ }
+
+ //this loop is set seperately so the fetch api could be called seperately on song changes
+ //please do not change the timeout, the api it fetches is not mine, no need to spam it
+ function loop_fetch_api_data(){
+ if(config_data["error"]==false){
+ fetch_api_data()
+ .then(res=>{
+ if(res=="api not set"){
+ set_error_box("api not set")
+ } else {
+ setTimeout(loop_fetch_api_data,13000)
+ }
+ })
+ }
+ }
+ loop_fetch_api_data()
+
+
+ function set_date(){
+ let date=new Date();
+ let dateconstruct=date.getUTCFullYear()+"-"+(date.getUTCMonth()+1)+"-"+(date.getUTCDay()-1)+" "+date.getUTCHours()+
+ ":"+date.getUTCMinutes()+":"+date.getUTCSeconds()+" UTC";
+ curr_date.innerHTML=dateconstruct
+ }
+
+ function np_next(data){
+ airtime_np.innerHTML="<h1>now playing</h1>"+
+ "<p>track</p>"+data["current"]["name"]
+
+ airtime_next.innerHTML="<h1>next</h1>"+
+ "<p>track</p>"+data["next"]["name"]
+
+ airtime_np_show.innerHTML="<h1>current show</h1>"+
+ data["currentShow"][0]["name"]
+
+ airtime_next_show.innerHTML="<h1>next show</h1>"+
+ data["nextShow"][0]["name"]+'<p>starts at</p>'+data["nextShow"][0]["start_timestamp"]+
+ '<span style="padding:4px"></span>'+data["timezone"]
+ }
+
+ function toggle_raw_json(){
+ if(getComputedStyle(raw_json).display=="none"){
+ raw_json.style.display="block"
+ } else {
+ raw_json.style.display="none"
+ }
+ }
+
+ function set_volume(data){
+ for(elem of document.getElementById("volumes_control").children){
+ if(elem.id!="update_button"&elem.id!="spacer"){
+ elem.style.backgroundColor="rgb(230,230,230)"
+ }
+ }
+
+ for(vol in config_data.volumes){
+ if(!config_data.volumes[vol].default){
+
+ if(config_data.volumes[vol].lookfor[0]){
+ if(getNested(data,config_data.volumes[vol].lookfor[0]).includes(config_data.volumes[vol].lookfor[1])){
+ airtime_radio.volume=config_data.volumes[vol].volume
+ document.getElementById('volumes_control_'+(vol)).style.backgroundColor="rgb(0,255,0)"
+ return
+ }
+ }
+ }
+ }
+ airtime_radio.volume=config_data.volumes[0].default
+ document.getElementById('volumes_control_0').style.backgroundColor="rgb(0,255,0)"
+ }
+
+ function getNested(obj, arr) {
+ const keys=[...arr];
+ if (keys.length === 0) return obj;
+
+ if(obj[keys[0]]){
+ return getNested(obj[keys.shift()], keys)
+ } else {
+ return undefined
+ }
+ }
+
+
+ //move window with cursor bs because electron doesnt have this >:(
+ move_button.addEventListener("mousedown",(eve)=>{
+ ipcRenderer.send("setpos",{x:eve.clientX,y:eve.clientY})
+ })
+ move_button.addEventListener("mouseup",(eve)=>{
+ ipcRenderer.send("stoppos",{})
+ })
+ </script>
+</body>
+</html>