| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| { | ||
| "name": "mythtv-frontend", | ||
| "version": "1.0.0", | ||
| "scripts": { | ||
| "build": "rollup -c", | ||
| "dev": "rollup -c -w", | ||
| "start": "sirv public" | ||
| }, | ||
| "devDependencies": { | ||
| "@rollup/plugin-commonjs": "^14.0.0", | ||
| "@rollup/plugin-node-resolve": "^8.0.0", | ||
| "rollup": "^2.3.4", | ||
| "rollup-plugin-livereload": "^2.0.0", | ||
| "rollup-plugin-svelte": "^6.0.0", | ||
| "rollup-plugin-terser": "^7.0.0", | ||
| "svelte": "^3.0.0" | ||
| }, | ||
| "dependencies": { | ||
| "sirv-cli": "^1.0.0", | ||
| "svelte-routing": "^1.4.2" | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| <!DOCTYPE html> | ||
| <html lang="en"> | ||
| <head> | ||
| <meta charset="utf-8" /> | ||
| <meta name="viewport" content="width=device-width,initial-scale=1" /> | ||
|
|
||
| <title>MythTV Frontend Development Env</title> | ||
|
|
||
| <link rel="stylesheet" href="/build/frontend.css" /> | ||
|
|
||
| <script defer src="/build/frontend.js"></script> | ||
| </head> | ||
|
|
||
| <body> | ||
| <!-- This file is here to allow development using npm start --> | ||
| </body> | ||
| </html> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,75 @@ | ||
| import svelte from 'rollup-plugin-svelte'; | ||
| import resolve from '@rollup/plugin-node-resolve'; | ||
| import commonjs from '@rollup/plugin-commonjs'; | ||
| import livereload from 'rollup-plugin-livereload'; | ||
| import { terser } from 'rollup-plugin-terser'; | ||
|
|
||
| const production = !process.env.ROLLUP_WATCH; | ||
|
|
||
| function serve() { | ||
| let server; | ||
|
|
||
| function toExit() { | ||
| if (server) server.kill(0); | ||
| } | ||
|
|
||
| return { | ||
| writeBundle() { | ||
| if (server) return; | ||
| server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { | ||
| stdio: ['ignore', 'inherit', 'inherit'], | ||
| shell: true | ||
| }); | ||
|
|
||
| process.on('SIGTERM', toExit); | ||
| process.on('exit', toExit); | ||
| } | ||
| }; | ||
| } | ||
|
|
||
| export default { | ||
| input: 'src/frontend.js', | ||
| output: { | ||
| sourcemap: true, | ||
| format: 'iife', | ||
| name: 'app', | ||
| file: '../apps/frontend.js' | ||
| }, | ||
| plugins: [ | ||
| svelte({ | ||
| // enable run-time checks when not in production | ||
| dev: !production, | ||
| // we'll extract any component CSS out into | ||
| // a separate file - better for performance | ||
| css: css => { | ||
| css.write('frontend.css'); | ||
| } | ||
| }), | ||
|
|
||
| // If you have external dependencies installed from | ||
| // npm, you'll most likely need these plugins. In | ||
| // some cases you'll need additional configuration - | ||
| // consult the documentation for details: | ||
| // https://github.com/rollup/plugins/tree/master/packages/commonjs | ||
| resolve({ | ||
| browser: true, | ||
| dedupe: ['svelte'] | ||
| }), | ||
| commonjs(), | ||
|
|
||
| // In dev mode, call `npm run start` once | ||
| // the bundle has been generated | ||
| !production && serve(), | ||
|
|
||
| // Watch the `public` directory and refresh the | ||
| // browser on changes when not in production | ||
| !production && livereload('public'), | ||
|
|
||
| // If we're building for production (npm run build | ||
| // instead of npm run dev), minify | ||
| production && terser() | ||
| ], | ||
| watch: { | ||
| clearScreen: false | ||
| } | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| <script> | ||
| import { Router, Route } from "svelte-routing"; | ||
| import Home from "./routes/Home.svelte"; | ||
| import RemoteControl from "./remote/RemoteControl.svelte"; | ||
| export let url= ""; | ||
| </script> | ||
|
|
||
| <style> | ||
| :global(body) { | ||
| font: normal 13px Verdana, Geneva, sans-serif; | ||
| background-color: #657b83; | ||
| border: 0px; | ||
| margin: 0px; | ||
| padding: 0px; | ||
| max-width: 100%; | ||
| overflow-x: hidden; | ||
| text-overflow: ellipsis; | ||
| } | ||
| </style> | ||
|
|
||
| <Router url="{url}"> | ||
| <div> | ||
| <Route path="/MythFE/GetRemote" component="{RemoteControl}" /> | ||
| <Route path="/" component="{Home}" /> | ||
| </div> | ||
| </Router> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| import Frontend from './Frontend.svelte'; | ||
|
|
||
| var app = new Frontend({ | ||
| target: document.getElementById("app"), | ||
| }); | ||
|
|
||
| export default app; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| <style> | ||
| logo { color: #26c; } | ||
| </style> | ||
| <logo> | ||
| <img src="/images/mythtv.png" alt="MythTV logo"> | ||
| </logo> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| <script> | ||
| import Logo from "./Logo.svelte"; | ||
| </script> | ||
|
|
||
| <style> | ||
| topbar { | ||
| background-color: #000000; | ||
| background-image: linear-gradient(to bottom, #222222, #000000 60%); | ||
| position: fixed; | ||
| top: 0px; | ||
| right: 0px; | ||
| left: 0px; | ||
| height: 34px; | ||
| border-bottom: 4px solid #004570; | ||
| z-index: 90; | ||
| } | ||
| </style> | ||
|
|
||
| <topbar> | ||
| <Logo/> | ||
| </topbar> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| <script> | ||
| export let title, action; | ||
| export let icon = ""; | ||
| async function handleClick() { | ||
| const query = new URLSearchParams(); | ||
| query.append("Action", action); | ||
| const params = { | ||
| method: 'POST', | ||
| headers: { | ||
| 'Content-Type': 'application/x-www-form-urlencoded', | ||
| 'Accept': 'application/json' | ||
| }, | ||
| body: query | ||
| }; | ||
| const res = fetch('/Frontend/SendAction', params); | ||
| } | ||
| </script> | ||
|
|
||
| <div class="item left waves-effect waves-light btn-large" on:click={handleClick}> | ||
| {#if icon === ""} | ||
| {title} | ||
| {:else} | ||
| <i class={icon}></i> | ||
| {/if} | ||
| </div> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,66 @@ | ||
| <script> | ||
| import Link from "svelte-routing/src/Link.svelte"; | ||
| import RemoteButton from "./RemoteButton.svelte"; | ||
| function buttonNumber(num) { | ||
| // Passed 0-8, buttons listed as 1-9 | ||
| return (num + 1).toString(); | ||
| } | ||
| </script> | ||
|
|
||
| <style> | ||
| remote { | ||
| background-color: #073642; | ||
| } | ||
| remotelayout { | ||
| grid-template-columns: repeat(3, 80px); | ||
| grid-template-rows: repeat(4, 58px) 10px 58px 10px repeat(3, 58px) 10px repeat(2, 58px); | ||
| width: auto; | ||
| display: grid; | ||
| } | ||
| linktext { | ||
| color: #fdf6e3; | ||
| } | ||
| </style> | ||
|
|
||
| <remote> | ||
| <!-- Buttons: 0-9, menu, info, back, mute, up, down, left, right, enter, ffwd, rewind--> | ||
| <remotelayout> | ||
| {#each {length: 9} as _, num} | ||
| <RemoteButton title={buttonNumber(num)} action={buttonNumber(num)}/> | ||
| {/each} | ||
| <div class="item left"></div> | ||
| <RemoteButton title="0" action="0"/> | ||
| <div class="item left"></div> | ||
| <div class="item left"></div> | ||
| <div class="item left"></div> | ||
| <div class="item left"></div> | ||
| <RemoteButton title="Menu" action="MENU" icon="fas fa-bars"/> | ||
| <RemoteButton title="Mute" action="MUTE" icon="fas fa-volume-mute"/> | ||
| <RemoteButton title="Info" action="INFO" icon="fas fa-info"/> | ||
| <div class="item left"></div> | ||
| <div class="item left"></div> | ||
| <div class="item left"></div> | ||
| <div class="item left"></div> | ||
| <RemoteButton title="^" action="UP" icon="fas fa-angle-up"/> | ||
| <div class="item left"></div> | ||
| <RemoteButton title="<" action="LEFT" icon="fas fa-angle-left"/> | ||
| <RemoteButton title="ENTER" action="SELECT" icon="fas fa-check"/> | ||
| <RemoteButton title=">" action="RIGHT" icon="fas fa-angle-right"/> | ||
| <RemoteButton title="BACK" action="ESCAPE" icon="fas fa-backspace"/> | ||
| <RemoteButton title="v" action="DOWN" icon="fas fa-angle-down"/> | ||
| <div class="item left"></div> | ||
| <div class="item left"></div> | ||
| <div class="item left"></div> | ||
| <div class="item left"></div> | ||
| <RemoteButton title="<<" action="JUMPRWND" icon="fas fa-angle-double-left"/> | ||
| <RemoteButton title="II" action="PAUSE" icon="fas fa-pause"/> | ||
| <RemoteButton title=">>" action="JUMPFFWD" icon="fas fa-angle-double-right"/> | ||
| <RemoteButton title="SEEKRWND" action="SEEKRWND" icon="fas fa-step-backward"/> | ||
| <RemoteButton title="PLAY" action="PLAY" icon="fas fa-play"/> | ||
| <RemoteButton title="SEEKFFWD" action="SEEKFFWD" icon="fas fa-step-forward"/> | ||
| </remotelayout> | ||
| </remote> | ||
| <br> | ||
| <div class="item left waves-effect waves-light btn-large"> | ||
| <Link to="/"><linktext>Back to Status</linktext></Link> | ||
| </div> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| <script> | ||
| import Navbar from "../navbar/Navbar.svelte"; | ||
| import Status from "../status/Status.svelte"; | ||
| </script> | ||
|
|
||
| <Navbar/> | ||
| <Status/> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,84 @@ | ||
| <script> | ||
| import { onMount } from "svelte"; | ||
| import { Link } from "svelte-routing"; | ||
| let fe_status = getStatus(); | ||
| async function getStatus() { | ||
| const params = { | ||
| method: 'GET', | ||
| headers: { | ||
| 'Accept': 'application/json' | ||
| }, | ||
| }; | ||
| const res = await fetch('/Frontend/GetStatus', params); | ||
| const data = await res.json(); | ||
| if (res.ok) { | ||
| return data.FrontendStatus; | ||
| } else { | ||
| console.log ("failed to load status"); | ||
| } | ||
| } | ||
| onMount(getStatus); | ||
| </script> | ||
|
|
||
| <style> | ||
| status { | ||
| position: absolute; | ||
| top: 64px; | ||
| right: 0px; | ||
| left: 27px; | ||
| width: calc(100% - 27px); | ||
| height: calc(100% - 64px); | ||
| padding: 0px; | ||
| box-sizing: border-box; | ||
| } | ||
| detailbox { | ||
| width: 1000px; | ||
| border-top: 1px solid #002b36; | ||
| border-right: 1px solid #002b36; | ||
| border-bottom: 1px solid #002b36; | ||
| border-left: 10px solid #002b36; | ||
| padding: 10px; | ||
| border-radius: 8px 0px 0px 8px; | ||
| margin: auto; | ||
| margin-bottom: 20px; | ||
| color: #002b36; | ||
| background-color: #93a1a1; | ||
| display: flow-root; | ||
| } | ||
| linktext { | ||
| color: #002b36; | ||
| } | ||
| </style> | ||
|
|
||
| {#await fe_status} | ||
| <status> | ||
| <p>loading...</p> | ||
| </status> | ||
| {:then Status} | ||
| <status> | ||
| <h2 class="center">MythFrontend Status</h2> | ||
| <detailbox> | ||
| <h4>This frontend</h4> | ||
| Name: {Status.Name} | ||
| <br> | ||
| Version: {Status.Version} | ||
| </detailbox> | ||
| <detailbox> | ||
| <h4>Services</h4> | ||
| <div class="item left waves-effect waves-light btn-small"> | ||
| <Link to="/MythFE/GetRemote"><linktext>Remote Control</linktext></Link> | ||
| </div> | ||
| </detailbox> | ||
| <detailbox> | ||
| <h4>Machine Information</h4> | ||
| <span> | ||
| The current frontend status is: {Status.State.state} | ||
| {#if Status.State.state == "WatchingPreRecorded"} | ||
| , Title: {Status.State.title}, Subtitle: {Status.State.subtitle} | ||
| {/if} | ||
| </span> | ||
| </detailbox> | ||
| </status> | ||
| {/await} | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,115 +1,20 @@ | ||
| <!DOCTYPE html> | ||
| <html lang="en"> | ||
| <head> | ||
| <meta charset="utf-8" /> | ||
| <meta name="viewport" content="width=device-width,initial-scale=1" /> | ||
|
|
||
| <title>MythTV Frontend</title> | ||
|
|
||
| <link rel="stylesheet" href="/3rdParty/materialize/css/materialize.css"> | ||
| <link rel="stylesheet" href="/3rdParty/fontawesome-free-5.15.1-web/css/fontawesome.css"> | ||
| <link rel="stylesheet" href="/3rdParty/fontawesome-free-5.15.1-web/css/solid.css"> | ||
| <link rel="stylesheet" href="/apps/frontend.css"> | ||
|
|
||
| <script defer src="/apps/frontend.js"></script> | ||
| </head> | ||
|
|
||
| <body> | ||
| <div id="app"/> | ||
| </body> | ||
| </html> | ||