vdo.ninja/electron.html
2021-05-13 02:50:43 -04:00

513 lines
14 KiB
HTML

<html>
<meta charset="UTF-8">
<head>
<link rel="stylesheet" href="./lineawesome/css/line-awesome.min.css" />
<style>
html {
border:0;
margin:0;
outline:0;
overflow: hidden;
}
video {
margin: 0;
padding: 0;
overflow: hidden;
cursor: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=), none;
user-select: none;
}
body {
padding: 0 0px;
height: 100%;
width: 100%;
background-color: -webkit-linear-gradient(to top, #363644, 50%, #151b29); /* Chrome 10-25, Safari 5.1-6 */
background: linear-gradient(to top, #363644, 50%, #151b29); /* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */
font-size: 2em;
font-family: Helvetica, Arial, sans-serif;
display: flex;
flex-flow: column;
border:0;
margin:0;
outline:0;
}
button.glyphicon-button:focus,
button.glyphicon-button:active:focus,
button.glyphicon-button.active:focus,
button.glyphicon-button.focus,
button.glyphicon-button:active.focus,
button.glyphicon-button.active.focus {
outline: none !important;
}
#gobutton{
padding: 1em;
font-size: 1em;
margin: auto auto;
height: 100%;
font-family: system-ui;
font-weight: bold;
border: 2px solid #6aab23;
background: #6aab23;
display: flex;
border-top-right-radius: 10px;
border-bottom-right-radius: 10px;
box-shadow: 0 12px 15px -10px #5ca70b;
position: relative;
right: 2px;
top: 1px;
color:white;
cursor:pointer;
}
#header{
width:100%;
background-color: #101520;
}
input#changeText {
font-size: 1em;
align-self: center;
width: 100%;
padding: 1em;
font-weight: bold;
font-family: system-ui;
background: white;
border-bottom: 4px solid #6aab23;
box-shadow: 0px 30px 40px -32px #6aab23;
border-top-left-radius: 10px;
border-bottom-left-radius: 10px;
transition: all 0.2s linear;
}
input#changeText:focus {
outline: none;
}
.container{
font-size: 20px;
align-self:center;
margin: auto auto;
}
label {
font: white;
font-size: 1em;
color: white;
}
input[type='checkbox'] {
-webkit-appearance:none;
width:30px;
height:30px;
background:white;
border-radius:5px;
border:2px solid #555;
cursor: pointer;
}
input[type='checkbox']:checked {
background: #1A1;
}
#audioOutput, #lastUrls {
font-size: calc(16px + 0.3vw);
width: 730px;
height: 100%;
flex: 20;
border-radius: 10px;
padding: 1em;
background: #eaeaea;
cursor:pointer;
}
label[for="audioOutput"] {
font-size: 3em;
color: #FE53BB;
text-shadow: 0px 0px 30px #fe53bb;
padding-top: 10px;
padding-right: 10px;
}
label[for="changeText"] {
font-size: 3em;
color: #00F6FF;
text-shadow: 0px 0px 30px #00f6ff;
padding-top: 10px;
padding-right: 10px;
}
label[for="lastUrls"] {
font-size: 3em;
color: #1a1;
text-shadow: 0px 0px 30px #1a1;
padding-top: 10px;
padding-right: 10px;
cursor: pointer;
}
div#audioOutputContainer, #history {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
justify-content: center;
margin: 4em;
}
@media only screen and (max-width: 1030px) {
body{
zoom: 0.9;
-moz-transform: scale(0.9);
-moz-transform-origin: 0 0;
}
}
@media only screen and (max-width: 940px) {
body{
zoom: 0.64;
-moz-transform: scale(0.64);
-moz-transform-origin: 0 0;
}
.container{
/* font-size: calc(14px + 1.4vw); */
max-width:750px;
}
}
#messageDiv {
font-size: .7em;
color: #DDD;
transition: all 0.5s linear;
font-style: italic;
opacity: 0;
text-align: center;
margin: 10px 0;
}
div#urlInput {
margin: 4em;
display: flex;
flex-direction: row;
}
label[for="audioOutput"], label[for="lastUrls"] {
font-size: 3em;
}
#warning4mac, #electronVersion {
background: #8500f7;
box-shadow: 0px 0px 50px 10px #8500f7ab, inset 0px 0px 10px 2px #8d08ffba;
border: 2px solid #8500f7;
border-radius: 10px;
width: 90%;
padding:1em;
margin:0 auto;
color:white;
font-size:1.3em;
margin-bottom: 20px;
}
#warning4mac a, #electronVersion a {
color:white;
}
ul#lastUrls {
list-style: none;
background: #101520;
color: white;
padding: 1em;
}
ul#lastUrls li {
padding: 5px 0px;
}
ul#lastUrls li:nth-child(even) {
background-color: #182031;
}
</style></head>
<body >
<div id="header" style="-webkit-app-region: drag;color:#6f6f6f;font-size:40px; line-height: 40px; padding: 20px; letter-spacing: 3; font-weight: bold;">OBS.Ninja</div>
<div class="container" >
<div id='warning4mac' style="display:none;"> ✨ Great News! OBS v26.1.2 <a href="https://github.com/obsproject/obs-browser/issues/209#issuecomment-748683083">now supports</a> OBS.Ninja without needing the Electron Capture app! 🥳</div>
<div id="electronVersion" style="display:none;">✨ Great News! <a href="https://github.com/steveseguin/electroncapture/releases/latest">Electron Capture <span id="currentElectronVersion"></span></a> is now available!<br>Update yours today to stay up-to-date with security patches.</div>
<div id="messageDiv" style='display:block'><br /></div>
<div class="container">
<div id="urlInput">
<label for="changeText">
<i class="las la-play"></i>
</label>
<input type="text" id="changeText" class="inputfield" value="http://obs.ninja/?view=" onchange="modURL" onkeyup="enterPressed(event, gohere);" />
<button onclick="gohere();" id="gobutton">GO</button>
</div>
<div id="audioOutputContainer">
<label for="audioOutput"><i class="las la-headphones"></i></label><select id="audioOutput"></select>
</div>
<div id="history">
<label for="lastUrls" onclick="resetHistory()">
<i class="las la-history"></i>
</label>
<select id="lastUrls" onchange="setUrl()"></select>
</div>
</div>
</div>
<script>
/*
* Copyright (c) 2020 Steve Seguin. All Rights Reserved.
*
* Use of this source code is governed by the APGLv3 open-source license
* that can be found in the LICENSE file in the root of the source
* tree. Alternative licencing options can be made available on request.
*
*/
var lastUrls = JSON.parse(localStorage.getItem('lastUrls'));
if (lastUrls != undefined) {
document.querySelector("#changeText").value = lastUrls[0];
if (lastUrls.length>0){
lastUrls.forEach((url)=>{
var o = document.createElement('option');
o.value = url;
o.text = url;
document.querySelector("#lastUrls").appendChild(o);
})
} else {
document.querySelector("#history").style.display="none";
}
} else {
document.querySelector("#history").style.display="none";
}
function setUrl(){
document.querySelector("#changeText").value = document.querySelector("#lastUrls").value;
gohere();
}
function resetHistory(){
localStorage.clear();
document.querySelector('#lastUrls').innerHTML = '';
lastUrls = [];
}
if (navigator.userAgent.indexOf('Mac OS X') != -1){
document.getElementById("warning4mac").style.display="block";
} else if (location.hostname.toLowerCase() == "obs.ninja"){
try {
if (navigator.userAgent.toLowerCase().indexOf(' electron/') > -1) { // for now, just PC or Linux versions only.
function compareVersions(version){
version = version.split(".");
fetch('https://api.github.com/repos/steveseguin/electroncapture/releases/latest')
.then(response => response.json())
.then(data => {
console.log("recentVersion: "+data.tag_name);
var recentVersion = data.tag_name.split(".");
var ood = false;
if (recentVersion[0]>version[0]){
ood = true;
} else if (recentVersion[0]==version[0]) {
if (recentVersion[1]>version[1]){
ood = true;
} else if (recentVersion[1]==version[1]) {
if (recentVersion[2]>version[2]){
ood = true;
}
}
}
if (ood){
document.getElementById("electronVersion").style.display = "block";
document.getElementById("currentElectronVersion").innerText = data.tag_name;
}
}).catch(console.error);
}
if (urlParams.has('version')){
var ver = urlParams.get('version');
console.log("version: "+ver);
compareVersions(ver);
} else{
var checkVersion = setTimeout(function(){ // pre 1.5.2
compareVersions("0.0.0");
},500);
const ipcRenderer = require('electron').ipcRenderer;
console.log("ELECTRON DETECTED");
ipcRenderer.on('appVersion', function(event, version) {
clearTimeout(checkVersion);
console.log("version: "+version);
compareVersions(version);
})
ipcRenderer.send('getAppVersion');
}
}
} catch(e){console.error(e);}
}
var audioOutputSelect = document.querySelector('select#audioOutput');
audioOutputSelect.disabled = !('sinkId' in HTMLMediaElement.prototype);
audioOutputSelect.onclick = getPermssions;
audioOutputSelect.onchange = updateOutputTarget;
var listed = false;
function updateOutputTarget(e){
console.log("change audio: "+audioOutputSelect.value);
var url = document.getElementById('changeText').value;
url=updateURLParameter(url, "sink", audioOutputSelect.value);
document.getElementById('changeText').value = url;
}
function getPermssions(e=null){
if (listed==true){
return;
}
if (e!==null){
e.currentTarget.blur();
}
navigator.mediaDevices.getUserMedia({audio: true,video: false}).then((stream)=>{
navigator.mediaDevices.enumerateDevices().then(gotDevices).catch(console.error); // list all devices
stream.getTracks().forEach(track => {
track.stop();
});
listed=true;
audioOutputSelect.focus();
}).catch(function(){
document.getElementById("messageDiv").innerHTML = "Failed to list available output devices\n\nPlease ensure you allowed the microphone permissions.";
document.getElementById("messageDiv").style.display="block";
setTimeout(function(){document.getElementById("messageDiv").style.opacity="1.0";},0);
});
}
function gotDevices(deviceInfos) {
for (let i = 0; i !== deviceInfos.length; ++i) {
const deviceInfo = deviceInfos[i];
const option = document.createElement('option');
option.value = deviceInfo.deviceId;
if (deviceInfo.kind === 'audiooutput'){
option.text = deviceInfo.label || `speaker ${audioOutputSelect.length + 1}`;
audioOutputSelect.appendChild(option);
} else {
console.log('Some other kind of source/device: ', deviceInfo);
}
}
listed=true;
}
function enterPressed(event, callback){
if (event.keyCode === 13){ // Number 13 is the "Enter" key on the keyboard
event.preventDefault(); // Cancel the default action, if needed
callback();
}
}
(function (w) {
w.URLSearchParams = w.URLSearchParams || function (searchString) {
var self = this;
self.searchString = searchString;
self.get = function (name) {
var results = new RegExp('[\?&]' + name + '=([^&#]*)').exec(self.searchString);
if (results == null) {
return null;
}
else {
return decodeURI(results[1]) || 0;
}
};
}
})(window)
var urlParams = new URLSearchParams(window.location.search);
var isMobile = false;
if( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)){ // does not detect iPad Pros.
isMobile=true; // if iOS, default to H264? meh. let's not.
}
// Windows can show the cursor, since it captures in a different way.
//if (navigator.platform.indexOf("Win") != -1){
// document.getElementById("showcursor").checked=true;
//}
function updateURLParameter(url, param, paramVal){
var TheAnchor = null;
var newAdditionalURL = "";
var tempArray = url.split("?");
var baseURL = tempArray[0];
var additionalURL = tempArray[1];
var temp = "";
if (additionalURL){
var tmpAnchor = additionalURL.split("#");
var TheParams = tmpAnchor[0];
TheAnchor = tmpAnchor[1];
if (TheAnchor){additionalURL = TheParams;}
tempArray = additionalURL.split("&");
for (var i=0; i<tempArray.length; i++){
if(tempArray[i].split('=')[0] != param){
newAdditionalURL += temp + tempArray[i];
temp = "&";
}
}
} else {
var tmpAnchor = baseURL.split("#");
var TheParams = tmpAnchor[0];
TheAnchor = tmpAnchor[1];
if(TheParams){baseURL = TheParams;}
}
if (paramVal===false){
temp="";
if(TheAnchor){temp += "#" + TheAnchor;}
var rows_txt = temp
} else if (paramVal===""){
if(TheAnchor){paramVal += "#" + TheAnchor;}
var rows_txt = temp + "" + param;
} else {
if(TheAnchor){paramVal += "#" + TheAnchor;}
var rows_txt = temp + "" + param + "=" + paramVal;
}
return baseURL + "?" + newAdditionalURL + rows_txt;
}
if (urlParams.has('name')){
var name = urlParams.get('name');
if (name!="OBSNinja"){
document.getElementById('changeText').value = "https://obs.ninja/?view="+name;
}
}
function addUrlToHistory(url){
if (lastUrls == undefined){
lastUrls = [];
}
if ( lastUrls[0] != url ) {
lastUrls.unshift(url);
if (lastUrls.length == 6) {
lastUrls.pop();
}
}
}
function modURL(ele=false){
var url = document.getElementById('changeText').value;
console.log(url);
document.getElementById('changeText').value = url;
console.log(url);
return url;
}
function gohere(){
addUrlToHistory(document.getElementById('changeText').value);
localStorage.setItem('lastUrls', JSON.stringify(lastUrls));
var url = modURL(true);
if (!(document.getElementById('changeText').value.includes("obs.ninja")) && (document.getElementById('changeText').value.includes("http")) && (document.getElementById('changeText').value.includes("&sink"))){
alert("Notice: The &sink command is domain specific.\nVisit https://YOURDOMAIN.com/electron instead.");
}
window.location = url;
};
getPermssions();
</script>
</body>
</html>