diff --git a/sender/camera-sender.css b/sender/camera-sender.css index b85d011aba7f540f088b876545ab156fd9beb3a5..f69b6f27306f7d5e0d2d5877776dd4c5f360a73c 100644 --- a/sender/camera-sender.css +++ b/sender/camera-sender.css @@ -1,3 +1,139 @@ +*, +::after, +::before { + box-sizing: border-box; +} + +body { + font-size: 16px; + margin: 0; +} + +@keyframes rotate { + 0% { + transform: rotate(0deg); + } + 100% { + transform: rotate(-360deg); + } +} + .visually-hidden { visibility: hidden; } + +.main__seperator { + margin: 16px 0; +} + +.main { + margin: 32px auto; + width: calc(100% - 24px); + max-width: 400px; + padding: 16px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3); + border-radius: 8px; +} + +.main__header { + text-align: center; +} + +.main__header-title { + margin: 0; +} + +#connection-status { + margin-bottom: 8px; + text-align: center; + color: green; +} + +.spinner-wrapper { + margin: 16px 0; + display: flex; + align-items: center; + justify-content: center; +} + +.spinner { + animation: rotate 1.5s infinite linear; + width: 30px; + height: 30px; + border-radius: 50%; + border: solid transparent 2px; + --border-color: #00bfff; + border-top-color: var(--border-color); + border-bottom-color: var(--border-color); +} + +.main__room-form { + margin: 0; +} + +.form-control { + margin-bottom: 8px; + display: flex; + justify-content: space-between; + align-items: center; + flex-wrap: wrap; +} + +.form-control__label { + width: 120px; + padding-right: 4px; +} + +.form-control__input { + min-width: 100px; + width: 100px; + max-width: 200px; + flex-grow: 1; +} + +#preview-container { + height: 100px; + background: orange; + display: flex; + align-items: center; + justify-content: center; + margin-bottom: 16px; +} + +.main__options { + margin-bottom: 8px; +} + +.options__toggle-wrapper { + display: flex; + justify-content: center; + margin-bottom: 6px; +} + +.options__toggle { + text-align: center; + padding: 4px 8px; + border-radius: 4px; + background: #eee; +} + +.options__toggle:hover { + background: #ccc; +} + +.options__body--hidden { + display: none; +} + +.main__controls { + display: flex; + justify-content: space-around; + margin: 0 -4px; +} + +.main__control-button { + width: 100%; + max-width: 200px; + margin: 0 4px; + +} diff --git a/sender/camera-sender.html b/sender/camera-sender.html index 80444788cf1390c6d0d5243f30034987ebddaecd..28cb555eadcf90e9e61e71c7c1e07f3d58ba3564 100644 --- a/sender/camera-sender.html +++ b/sender/camera-sender.html @@ -1,60 +1,75 @@ <html> <head> <title>Camera Sender</title> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <script type="text/javascript" src="adapter.min.js"></script> <script type="text/javascript" src="janus.js"></script> <script type="text/javascript" src="socket.io.min.js"></script> <script type="text/javascript" src="camera-sender.js"></script> <link rel="stylesheet" href="camera-sender.css"> - <style> - /* temporary */ - div { - margin-bottom: 8px; - } - </style> </head> <body> - <h3 id="room-indicator"></h3> - - <div id="pin-hint"> - Leave the pin empty if the rooms has none set. - </div> - - <form id="room-form"> - <div> - <select id="res-select"> - <option value="lowres">320x240</option> - <option value="lowres-16:9">320x180</option> - <option value="stdres" selected>640x480</option> - <option value="stdres-16:9">640x360</option> - <option value="hires-4:3">960x720</option> - <option value="hires-16:9">1280x720</option> - </select> - </div> + <main class="main"> + <header class="main__header"> + <h3 id="room-indicator" class="main__header-title"> + Channel <span id="room"></span> • Camera <span id="slot"></span> + </h3> + </header> - <div id="name-container"> - <input required type="text" id="name-input" placeholder="Display name" /> - </div> + <hr class="main__seperator" /> - <div id="pin-container"> - <input type="password" id="pin-input" placeholder="Room pin" /> - </div> + <div id="connection-status">Connected</div> - <div> - <button type="submit" id="start" disabled>Start</button> - <button id="stop" disabled>Stop</button> + <div id="spinner" class="spinner-wrapper"> + <div class="spinner"></div> </div> - </form> - - <p> - <form id="bandwidth-form"> - <label>While the camera is running, a bandwidth cap can be set here. 0 or negative means no cap.</label> - <br /> - <input type="text" id="bandwidth-input" placeholder="New bitrate [in kbit/s]" /> - <input type="submit" id="bandwidth-submit" value="Change" disabled /> + + <form id="room-form" class="main__room-form"> + <div class="form-control"> + <label class="form-control__label" for="res-select">Resolution</label> + <select id="res-select" class="form-control__input"> + <option value="lowres">320x240</option> + <option value="lowres-16:9">320x180</option> + <option value="stdres" selected>640x480</option> + <option value="stdres-16:9">640x360</option> + <option value="hires-4:3">960x720</option> + <option value="hires-16:9">1280x720</option> + </select> + </div> + + <div id="name-control" class="form-control"> + <label class="form-control__label" for="name-input">Display name</label> + <input id="name-input" class="form-control__input" required type="text" /> + </div> + + <div id="pin-control" class="form-control"> + <label class="form-control__label" for="pin-input">Room PIN</label> + <input id="pin-input" class="form-control__input" type="password" placeholder="Leave empty if none" /> + </div> </form> - </p> - <div id="preview-container"></div> + <div id="preview-container">Preview</div> + + <section class="main__options"> + <div class="options__toggle-wrapper"> + <div id="options-toggle" class="options__toggle">Advanced options</div> + </div> + <div id="options" class="options__body options__body--hidden"> + <form id="bandwidth-form"> + <label>While the camera is running, a bandwidth cap can be set here. 0 or negative means no cap.</label> + <br /> + <input type="text" id="bandwidth-input" placeholder="New bitrate [in kbit/s]" /> + <input type="submit" id="bandwidth-submit" value="Change" disabled /> + </form> + </div> + </section> + + <hr class="main__seperator" /> + + <div class="main__controls"> + <button id="start" class="main__control-button" type="submit" disabled>Start</button> + <button id="stop" class="main__control-button" disabled>Stop</button> + </div> + </main> </body> </html> diff --git a/sender/camera-sender.js b/sender/camera-sender.js index eb57b9a77bc3187cecc2db703483945d2fee8b97..ec29de9069e4a104517258e60cec6d10d6ba96b7 100644 --- a/sender/camera-sender.js +++ b/sender/camera-sender.js @@ -8,7 +8,6 @@ document.addEventListener('DOMContentLoaded', function() { var roomForm = document.getElementById('room-form'); var startButton = document.getElementById('start'); var stopButton = document.getElementById('stop'); - var roomIndicator = document.getElementById('room-indicator'); var gotSocketInitResponse = false; var transmitting = false; @@ -26,13 +25,18 @@ document.addEventListener('DOMContentLoaded', function() { parseTokenFromURL(); parseCustomNameAllowed(); - roomIndicator.innerText = `Channel ${room - 1000}, Camera ${slot + 1}`; + document.getElementById('room').innerText = room - 1000; + document.getElementById('slot').innerText = slot + 1; const socketNumber = room + 4000; const socket = io('https://' + window.location.hostname, { path: '/socket.io/' + socketNumber }); + document.getElementById('options-toggle').onclick = function () { + document.getElementById('options').classList.toggle('options__body--hidden'); + }; + registerSocketHandlers(); function handleSenderInitResponse(data) {