Add Wall View API Endpoint

plugin-touch-ups
Moe 2024-06-13 21:48:37 -07:00
parent 21c44fcc27
commit 5e37b8b3b9
5 changed files with 286 additions and 0 deletions

View File

@ -54,6 +54,8 @@ module.exports = function(s,config,lang,io){
if(config.renderPaths.grid === undefined){config.renderPaths.grid='pages/grid'}
//slick.js (cycle) page
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
if(config.useUWebsocketJs === undefined){config.useUWebsocketJs=true}
if(config.webBlocksPreloaded === undefined){

View File

@ -415,4 +415,34 @@ module.exports = function(s,config,lang,app){
},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);
});
}

View File

@ -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;
}

View File

@ -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()
})
})

65
web/pages/wallview.ejs Normal file
View File

@ -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>