Add Wall View API Endpoint
parent
21c44fcc27
commit
5e37b8b3b9
web
assets
pages
|
@ -54,6 +54,8 @@ module.exports = function(s,config,lang,io){
|
||||||
if(config.renderPaths.grid === undefined){config.renderPaths.grid='pages/grid'}
|
if(config.renderPaths.grid === undefined){config.renderPaths.grid='pages/grid'}
|
||||||
//slick.js (cycle) page
|
//slick.js (cycle) page
|
||||||
if(config.renderPaths.cycle === undefined){config.renderPaths.cycle='pages/cycle'}
|
if(config.renderPaths.cycle === undefined){config.renderPaths.cycle='pages/cycle'}
|
||||||
|
//WallView page
|
||||||
|
if(config.renderPaths.wallview === undefined){config.renderPaths.wallview='pages/wallview'}
|
||||||
// Use uws/cws
|
// Use uws/cws
|
||||||
if(config.useUWebsocketJs === undefined){config.useUWebsocketJs=true}
|
if(config.useUWebsocketJs === undefined){config.useUWebsocketJs=true}
|
||||||
if(config.webBlocksPreloaded === undefined){
|
if(config.webBlocksPreloaded === undefined){
|
||||||
|
|
|
@ -415,4 +415,34 @@ module.exports = function(s,config,lang,app){
|
||||||
},res,req);
|
},res,req);
|
||||||
},res,req);
|
},res,req);
|
||||||
});
|
});
|
||||||
|
/**
|
||||||
|
* Page : Get WallView
|
||||||
|
*/
|
||||||
|
app.get(config.webPaths.apiPrefix+':auth/wallview/:ke', function (req,res){
|
||||||
|
s.auth(req.params,function(user){
|
||||||
|
const authKey = req.params.auth
|
||||||
|
const groupKey = req.params.ke
|
||||||
|
if(
|
||||||
|
user.permissions.watch_stream === "0"
|
||||||
|
|| user.details.sub
|
||||||
|
&& user.details.allmonitors !== '1'
|
||||||
|
){
|
||||||
|
res.end(user.lang['Not Permitted'])
|
||||||
|
return
|
||||||
|
}
|
||||||
|
s.renderPage(req,res,config.renderPaths.wallview,{
|
||||||
|
forceUrlPrefix: req.query.host || '',
|
||||||
|
data: req.params,
|
||||||
|
protocol: req.protocol,
|
||||||
|
baseUrl: req.protocol + '://' + req.hostname,
|
||||||
|
config: s.getConfigWithBranding(req.hostname),
|
||||||
|
define: s.getDefinitonFile(user.details ? user.details.lang : config.lang),
|
||||||
|
lang: lang,
|
||||||
|
$user: user,
|
||||||
|
authKey: authKey,
|
||||||
|
groupKey: groupKey,
|
||||||
|
originalURL: s.getOriginalUrl(req)
|
||||||
|
});
|
||||||
|
},res,req);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
#wallview-container {
|
||||||
|
position: fixed;
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
background: rgba(0, 0, 0, 0.9);
|
||||||
|
}
|
||||||
|
|
||||||
|
#wallview-canvas {
|
||||||
|
position: relative;
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
flex-grow: 1;
|
||||||
|
overflow: hidden;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#wallview-controls{
|
||||||
|
position: absolute;
|
||||||
|
top: 20px;
|
||||||
|
right: 20px;
|
||||||
|
opacity: 0;
|
||||||
|
transition: 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
#wallview-controls:hover{
|
||||||
|
opacity: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#wallview-monitorList i{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#wallview-monitorList .active i{
|
||||||
|
display: inlin-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
#wallview-canvas .wallview-video {
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
#wallview-canvas .wallview-video .overlay {
|
||||||
|
position: absolute;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
#wallview-canvas .wallview-video iframe {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#wallview-canvas .wallview-video.col-md-4 {
|
||||||
|
height:30vh;
|
||||||
|
}
|
||||||
|
#wallview-canvas .wallview-video.col-md-6 {
|
||||||
|
height: 40vh;
|
||||||
|
}
|
||||||
|
#wallview-canvas .wallview-video.col-md-12 {
|
||||||
|
height: 80vh;
|
||||||
|
margin-bottom: 0.5rem !important;
|
||||||
|
}
|
||||||
|
#wallview-canvas .wallview-video:not(.no-video){
|
||||||
|
background-color: #000!important;
|
||||||
|
}
|
||||||
|
#wallview-canvas .wallview-video.no-video{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
#wallview-canvas.show-non-playing .wallview-video.no-video{
|
||||||
|
display: flex;
|
||||||
|
}
|
|
@ -0,0 +1,119 @@
|
||||||
|
var loadedMonitors = {}
|
||||||
|
var selectedMonitors = {}
|
||||||
|
$(document).ready(function(){
|
||||||
|
var wallViewMonitorList = $('#wallview-monitorList')
|
||||||
|
var wallViewControls = $('#wallview-controls')
|
||||||
|
var wallViewCanvas = $('#wallview-canvas')
|
||||||
|
function getApiPrefix(innerPart){
|
||||||
|
return `${urlPrefix}${authKey}${innerPart ? `/${innerPart}/${groupKey}` : ''}`
|
||||||
|
}
|
||||||
|
function getWindowName(){
|
||||||
|
const urlParams = new URLSearchParams(window.location.search);
|
||||||
|
const theWindow = urlParams.get('window');
|
||||||
|
return theWindow || '1'
|
||||||
|
}
|
||||||
|
function drawMonitorListItem(monitor){
|
||||||
|
wallViewMonitorList.append(`<li><a class="dropdown-item" select-monitor="${monitor.mid}" href="#"><i class="fa fa-check"></i> ${monitor.name}</a></li>`)
|
||||||
|
}
|
||||||
|
function drawMonitorList(){
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
$.get(getApiPrefix('monitor'),function(monitors){
|
||||||
|
$.each(monitors, function(n,monitor){
|
||||||
|
if(monitor.mode !== 'stop' && monitor.mode !== 'idle'){
|
||||||
|
loadedMonitors[monitor.mid] = monitor;
|
||||||
|
drawMonitorListItem(monitor)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
resolve(monitors)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function getMonitorListItem(monitorId){
|
||||||
|
return wallViewMonitorList.find(`[select-monitor="${monitorId}"]`)
|
||||||
|
}
|
||||||
|
|
||||||
|
function selectMonitor(monitorId, css){
|
||||||
|
css = css || {};
|
||||||
|
selectedMonitors[monitorId] = Object.assign({}, loadedMonitors[monitorId]);
|
||||||
|
wallViewCanvas.append(`<div class="wallview-video p-0 m-0" live-stream="${monitorId}" style="left:${css.left || 0}px;top:${css.top || 0}px;width:${css.width ? css.width + 'px' : '50vw'};height:${css.height ? css.height + 'px' : '40vh'};"><div class="overlay"></div><iframe src="${getApiPrefix('embed')}/${monitorId}/fullscreen%7Cjquery%7Crelative?host=/"></iframe></div>`)
|
||||||
|
wallViewCanvas.find(`[live-stream="${monitorId}"]`)
|
||||||
|
.draggable({
|
||||||
|
grid: [10, 10],
|
||||||
|
snap: '#wallview-canvas',
|
||||||
|
containment: "window",
|
||||||
|
stop: function(){
|
||||||
|
saveLayout()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.resizable({
|
||||||
|
grid: [10, 10],
|
||||||
|
snap: '#wallview-canvas',
|
||||||
|
containment: "window",
|
||||||
|
stop: function(){
|
||||||
|
saveLayout()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
getMonitorListItem(monitorId).addClass('active')
|
||||||
|
}
|
||||||
|
function deselectMonitor(monitorId){
|
||||||
|
delete(selectedMonitors[monitorId])
|
||||||
|
var monitorItem = wallViewCanvas.find(`[live-stream="${monitorId}"]`);
|
||||||
|
monitorItem.find('iframe').attr('src','about:blank')
|
||||||
|
monitorItem.remove()
|
||||||
|
getMonitorListItem(monitorId).removeClass('active')
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCurrentLayout(){
|
||||||
|
var layout = []
|
||||||
|
wallViewCanvas.find('.wallview-video').each(function(n,v){
|
||||||
|
var el = $(v)
|
||||||
|
var monitorId = el.attr('live-stream')
|
||||||
|
var position = el.position()
|
||||||
|
console.log(monitorId,position)
|
||||||
|
layout.push({
|
||||||
|
monitorId,
|
||||||
|
css: {
|
||||||
|
left: position.left,
|
||||||
|
top: position.top,
|
||||||
|
width: el.width(),
|
||||||
|
height: el.height(),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
return layout
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveLayout(){
|
||||||
|
var windowName = getWindowName();
|
||||||
|
var layout = getCurrentLayout();
|
||||||
|
localStorage.setItem(`windowLayout_${windowName}`, JSON.stringify(layout))
|
||||||
|
}
|
||||||
|
|
||||||
|
function getLayout(){
|
||||||
|
var windowName = getWindowName();
|
||||||
|
var layout = JSON.parse(localStorage.getItem(`windowLayout_${windowName}`) || '[]')
|
||||||
|
return layout;
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadSavedLayout(){
|
||||||
|
var layout = getLayout()
|
||||||
|
layout.forEach(function({ monitorId, css }, n){
|
||||||
|
selectMonitor(monitorId, css)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
drawMonitorList().then(loadSavedLayout)
|
||||||
|
$('body').on('click', '[select-monitor]', function(e){
|
||||||
|
e.preventDefault()
|
||||||
|
var el = $(this);
|
||||||
|
var monitorId = el.attr('select-monitor')
|
||||||
|
var isSelected = selectedMonitors[monitorId]
|
||||||
|
if(isSelected){
|
||||||
|
deselectMonitor(monitorId)
|
||||||
|
}else{
|
||||||
|
selectMonitor(monitorId)
|
||||||
|
}
|
||||||
|
saveLayout()
|
||||||
|
})
|
||||||
|
})
|
|
@ -0,0 +1,65 @@
|
||||||
|
<title><%- lang.Shinobi %></title>
|
||||||
|
<%
|
||||||
|
var forceUrlPrefix
|
||||||
|
var urlPrefix = ``
|
||||||
|
var targetPort = config.ssl && config.ssl.port && protocol === 'https' ? config.ssl.port : config.port
|
||||||
|
var addonsEnabled = {}
|
||||||
|
var rawAddonList = decodeURI(data.addon || '').split('|');
|
||||||
|
rawAddonList.forEach(function(piece){
|
||||||
|
var pieceParts = piece.split('=');
|
||||||
|
var key = pieceParts[0];
|
||||||
|
var value = pieceParts[1] || true;
|
||||||
|
addonsEnabled[key] = value;
|
||||||
|
});
|
||||||
|
function getAddon(addonTag){
|
||||||
|
return addonsEnabled[addonTag];
|
||||||
|
}
|
||||||
|
var streamWidth = parseInt(getAddon('width')) || 640
|
||||||
|
var streamHeight = parseInt(getAddon('height')) || 480
|
||||||
|
var hasGUI = getAddon('gui')
|
||||||
|
var isFullscreen = getAddon('fullscreen')
|
||||||
|
var isRelativeUrl = getAddon('relative')
|
||||||
|
if(forceUrlPrefix){
|
||||||
|
urlPrefix = forceUrlPrefix
|
||||||
|
}else if(isRelativeUrl){
|
||||||
|
urlPrefix = ''
|
||||||
|
}else if(config.baseURL){
|
||||||
|
urlPrefix = config.baseURL
|
||||||
|
}else if(!targetPort || targetPort === '' || targetPort == 80 || targetPort == 443){
|
||||||
|
urlPrefix = baseUrl
|
||||||
|
}else{
|
||||||
|
urlPrefix = `${baseUrl}:${targetPort}`
|
||||||
|
}
|
||||||
|
if(urlPrefix.endsWith('/') === false){
|
||||||
|
urlPrefix += '/'
|
||||||
|
}
|
||||||
|
var originalURL = `${urlPrefix}`
|
||||||
|
%>
|
||||||
|
<%- include('blocks/header-favicon') %>
|
||||||
|
<script>window.$user=<%- JSON.stringify($user) %>;</script>
|
||||||
|
<script>window.urlPrefix = "<%- urlPrefix || '' %>";</script>
|
||||||
|
<script>window.groupKey = "<%- groupKey || '' %>";</script>
|
||||||
|
<script>window.authKey = "<%- authKey || '' %>";</script>
|
||||||
|
<script src="<%- urlPrefix %>assets/vendor/js/socket.io.min.js"></script>
|
||||||
|
<script src="<%- urlPrefix %>assets/vendor/js/jquery.min.js"></script>
|
||||||
|
<link rel="stylesheet" href="<%- urlPrefix %>assets/vendor/font-awesome/css/font-awesome.min.css">
|
||||||
|
<link rel="stylesheet" href="<%- urlPrefix %>assets/vendor/bootstrap5/css/bootstrap.min.css">
|
||||||
|
<link rel="stylesheet" href="<%- urlPrefix %>assets/css/bs5.wallview.css">
|
||||||
|
<link rel="stylesheet" href="<%- urlPrefix %>assets/vendor/jquery-ui.min.css">
|
||||||
|
<div id="wallview-container">
|
||||||
|
<div id="wallview-canvas">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div id="wallview-controls">
|
||||||
|
<div class="dropdown">
|
||||||
|
<a class="btn btn-secondary dropdown-toggle" href="#" role="button" id="monitorListButton" data-bs-toggle="dropdown" aria-expanded="false">
|
||||||
|
<%- lang.Monitors %>
|
||||||
|
</a>
|
||||||
|
<ul id="wallview-monitorList" class="dropdown-menu" aria-labelledby="monitorListButton"></ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- <script src="<%- urlPrefix %>assets/js/bs5.embed.utils.js"></script> -->
|
||||||
|
<script src="<%- urlPrefix %>assets/vendor/bootstrap5/js/bootstrap.bundle.min.js"></script>
|
||||||
|
<script src="<%- urlPrefix %>assets/vendor/js/jquery-ui.min.js"></script>
|
||||||
|
<script src="<%- urlPrefix %>assets/js/bs5.wallview.js"></script>
|
Loading…
Reference in New Issue