Channel ui changes. Confirmation popup for deleting channels. Adjust program order and start time when reopening a channel to match what's currently on air. 'Cyclic Shuffle'. Button to delete all programs.

This commit is contained in:
vexorian 2020-06-29 15:42:18 -04:00
parent 326797431f
commit 5b8d9c5995
3 changed files with 120 additions and 6 deletions

View File

@ -8,9 +8,11 @@ module.exports = function ($scope, pseudotv) {
$scope.channels = channels
})
$scope.removeChannel = (channel) => {
pseudotv.removeChannel(channel).then((channels) => {
$scope.channels = channels
})
if (confirm("Are you sure to delete channel: " + channel.name + "?")) {
pseudotv.removeChannel(channel).then((channels) => {
$scope.channels = channels
})
}
}
$scope.onChannelConfigDone = (channel) => {
if (typeof channel !== 'undefined') {

View File

@ -9,6 +9,7 @@ module.exports = function ($timeout, $location) {
onDone: "=onDone"
},
link: function (scope, element, attrs) {
scope.millisecondsOffset = 0;
if (typeof scope.channel === 'undefined' || scope.channel == null) {
scope.channel = {}
scope.channel.programs = []
@ -31,9 +32,36 @@ module.exports = function ($timeout, $location) {
scope.channel.number = 1
scope.channel.name = "Channel 1"
}
scope.showRotatedNote = false;
} else {
scope.beforeEditChannelNumber = scope.channel.number
let t = Date.now();
let originalStart = scope.channel.startTime.getTime();
let n = scope.channel.programs.length;
let totalDuration = scope.channel.duration;
let m = (t - originalStart) % totalDuration;
let x = 0;
let runningProgram = -1;
let offset = 0;
for (let i = 0; i < n; i++) {
let d = scope.channel.programs[i].duration;
if (x + d > m) {
runningProgram = i
offset = m - x;
break;
} else {
x += d;
}
}
scope.millisecondsOffset = (t - offset) % 1000;
scope.channel.startTime = new Date(t - offset - scope.millisecondsOffset);
// move runningProgram to index 0
scope.channel.programs = scope.channel.programs.slice(runningProgram, this.length)
.concat(scope.channel.programs.slice(0, runningProgram) );
updateChannelDuration();
setTimeout( () => { scope.showRotatedNote = true }, 1, 'funky');
}
scope.finshedProgramEdit = (program) => {
scope.channel.programs[scope.selectedProgram] = program
scope._selectedProgram = null
@ -151,6 +179,15 @@ module.exports = function ($timeout, $location) {
shuffle(scope.channel.programs)
updateChannelDuration()
}
scope.cyclicShuffle = () => {
cyclicShuffle(scope.channel.programs);
updateChannelDuration();
}
scope.wipeSchedule = () => {
wipeSchedule(scope.channel.programs);
updateChannelDuration();
}
function getRandomInt(min, max) {
min = Math.ceil(min)
max = Math.floor(max)
@ -167,8 +204,75 @@ module.exports = function ($timeout, $location) {
}
return array
}
function wipeSchedule(array) {
array.splice(0, array.length)
return array;
}
function cyclicShuffle(array) {
let shows = {};
let next = {};
let counts = {};
// some precalculation, useful to stop the shuffle from being quadratic...
for (let i = 0; i < array.length; i++) {
var vid = array[i];
if (vid.type != 'movie' && vid.season != 0) {
let countKey = {
title: vid.showTitle,
s: vid.season,
e: vid.episode,
}
let key = JSON.stringify(countKey);
let c = ( (typeof(counts[key]) === 'undefined') ? 0 : counts[key] );
counts[key] = c + 1;
let showEntry = {
c: c,
it: array[i],
}
if ( typeof(shows[vid.showTitle]) === 'undefined') {
shows[vid.showTitle] = [];
}
shows[vid.showTitle].push(showEntry);
}
}
//this is O(|N| log|M|) where |N| is the total number of TV
// episodes and |M| is the maximum number of episodes
// in a single show. I am pretty sure this is a lower bound
// on the time complexity that's possible here.
Object.keys(shows).forEach(function(key,index) {
shows[key].sort( (a,b) => {
if (a.c == b.c) {
if (a.it.season == b.it.season) {
if (a.it.episode == b.it.episode) {
return 0;
} else {
return (a.it.episode < b.it.episode)?-1: 1;
}
} else {
return (a.it.season < b.it.season)?-1: 1;
}
} else {
return (a.c < b.c)? -1: 1;
}
});
next[key] = Math.floor( Math.random() * shows[key].length );
});
shuffle(array);
for (let i = 0; i < array.length; i++) {
if (array[i].type !== 'movie' && array[i].season != 0) {
let title = array[i].showTitle;
var sequence = shows[title];
var j = next[title];
array[i] = sequence[j].it;
next[title] = (j + 1) % sequence.length;
}
}
return array
}
scope.updateChannelDuration = updateChannelDuration
function updateChannelDuration() {
scope.showRotatedNote = false;
scope.channel.duration = 0
for (let i = 0, l = scope.channel.programs.length; i < l; i++) {
scope.channel.programs[i].start = new Date(scope.channel.startTime.valueOf() + scope.channel.duration)
@ -204,8 +308,10 @@ module.exports = function ($timeout, $location) {
scope.error.startTime = "Start time must not be set in the future."
else if (channel.programs.length === 0)
scope.error.programs = "No programs have been selected. Select at least one program."
else
else {
channel.startTime.setMilliseconds( scope.millisecondsOffset);
scope.onDone(JSON.parse(angular.toJson(channel)))
}
$timeout(() => { scope.error = {} }, 3500)
}
}
@ -229,4 +335,4 @@ module.exports = function ($timeout, $location) {
}
function validURL(url) {
return /^(ftp|http|https):\/\/[^ "]+$/.test(url);
}
}

View File

@ -72,10 +72,13 @@
<label id="channelStartTime" class="small">Channel Timeline Start {{maxDate}}</label>
<input for="channelStartTime" class="form-control form-control-sm" type="datetime-local" ng-model="channel.startTime" />
</div>
<p class="text-center text-info small" ng-show='showRotatedNote' >The channel is already live, the program schedule has been rotated so that the currently-playing program is at the top of the list.</p>
<hr />
<div>
<h6>Programs
<span class="small">Total: {{channel.programs.length}}</span>
<span class="btn fa fa-trash" ng-click="wipeSchedule()"></span>
<span class="badge badge-dark" style="margin-left: 15px;"
ng-show="channel.programs.length !== 0">Commercials</span>
<button class="btn btn-sm btn-secondary" style="margin-left: 10px"
@ -108,9 +111,12 @@
<button class="btn btn-sm btn-warning form-control form-control-sm" type="button" ng-click="blockShuffle(blockCount, randomizeBlockShuffle)">Block Shuffle</button>
</div>
</div>
<div class="input-group col-md-6" style="padding: 5px;">
<div class="input-group col-md-3" style="padding: 5px;">
<button class="btn btn-sm btn-warning form-control form-control-sm" type="button" ng-click="randomShuffle()">Random Shuffle</button>
</div>
<div class="input-group col-md-3" style="padding: 5px;">
<button class="btn btn-sm btn-warning form-control form-control-sm" type="button" ng-click="cyclicShuffle()">Cyclic Shuffle</button>
</div>
</div>
<div class="row">
<div class="input-group col-md-6" style="padding: 5px;">