After running a stress test a couple times i found some nasty edge cases and tried to patch them up as best i could

This commit is contained in:
Speng Reb 2026-06-01 21:36:54 +02:00
parent 03711e4726
commit 6b40b9c500
5 changed files with 82 additions and 19 deletions

View file

@ -24,6 +24,7 @@ function OptionsModule(_channel) {
cooldown: 4 // Number of seconds with no messages before burst is reset cooldown: 4 // Number of seconds with no messages before burst is reset
}, },
show_public: false, // List the channel on the index page show_public: false, // List the channel on the index page
show_schedule: true, // Show the schedule UI and nav toggle
enable_link_regex: true, // Use the built-in link filter enable_link_regex: true, // Use the built-in link filter
password: false, // Channel password (false -> no password required for entry) password: false, // Channel password (false -> no password required for entry)
allow_dupes: false, // Allow duplicate videos on the playlist allow_dupes: false, // Allow duplicate videos on the playlist
@ -322,6 +323,11 @@ OptionsModule.prototype.handleSetOptions = function (user, data) {
sendUpdate = true; sendUpdate = true;
} }
if ("show_schedule" in data && user.account.effectiveRank >= 3) {
this.opts.show_schedule = Boolean(data.show_schedule);
sendUpdate = true;
}
if ("enable_link_regex" in data) { if ("enable_link_regex" in data) {
this.opts.enable_link_regex = Boolean(data.enable_link_regex); this.opts.enable_link_regex = Boolean(data.enable_link_regex);
sendUpdate = true; sendUpdate = true;

View file

@ -92,6 +92,7 @@ mixin adminoptions
+textbox-auto("cs-externalcss", "External CSS", "Stylesheet URL") +textbox-auto("cs-externalcss", "External CSS", "Stylesheet URL")
+textbox-auto("cs-externaljs", "External Javascript", "Script URL") +textbox-auto("cs-externaljs", "External Javascript", "Script URL")
+rcheckbox-auto("cs-show_public", "List channel publicly") +rcheckbox-auto("cs-show_public", "List channel publicly")
+rcheckbox-auto("cs-show_schedule", "Show channel schedule")
+rcheckbox-auto("cs-torbanned", "Block connections from Tor") +rcheckbox-auto("cs-torbanned", "Block connections from Tor")
+rcheckbox-auto("cs-block_anonymous_users", "Block anonymous users") +rcheckbox-auto("cs-block_anonymous_users", "Block anonymous users")
+rcheckbox-auto("cs-allow_ascii_control", "Allow ASCII control characters (e.g. newlines)") +rcheckbox-auto("cs-allow_ascii_control", "Allow ASCII control characters (e.g. newlines)")

View file

@ -270,7 +270,6 @@ li.ui-sortable-helper, li.ui-sortable-placeholder + li.queue_entry {
.showschedule-notes { .showschedule-notes {
margin-top: 2px; margin-top: 2px;
max-height: 72px;
overflow: hidden; overflow: hidden;
line-height: 1.2; line-height: 1.2;
color: rgba(255, 255, 255, 0.95); color: rgba(255, 255, 255, 0.95);

View file

@ -34,6 +34,20 @@ function updateScheduleToggleLabel() {
$("#toggleschedule").text(row.is(":visible") ? "Hide Schedule" : "Show Schedule"); $("#toggleschedule").text(row.is(":visible") ? "Hide Schedule" : "Show Schedule");
} }
function applyScheduleVisibility() {
var enabled = true;
if (window.CHANNEL && CHANNEL.opts && CHANNEL.opts.show_schedule === false) {
enabled = false;
}
if (!enabled) {
$("#showschedule-row").hide();
}
$("#toggleschedule").css("display", enabled ? "" : "none");
updateScheduleToggleLabel();
}
$("#toggleschedule").on('click', function () { $("#toggleschedule").on('click', function () {
var row = $("#showschedule-row"); var row = $("#showschedule-row");
if (!row.length) return; if (!row.length) return;
@ -44,7 +58,8 @@ $("#toggleschedule").on('click', function () {
} }
updateScheduleToggleLabel(); updateScheduleToggleLabel();
}); });
updateScheduleToggleLabel(); window.applyScheduleVisibility = applyScheduleVisibility;
applyScheduleVisibility();
/* chatbox */ /* chatbox */
@ -1437,6 +1452,8 @@ var CSTShows = (function () {
var weekOffset = 0; var weekOffset = 0;
var cachedShows = []; var cachedShows = [];
var notesEditorMode = 'edit'; var notesEditorMode = 'edit';
var REFRESH_MS = 15000;
var scheduleRefreshTimer = null;
function apiBase() { function apiBase() {
return '/api/v1/channels/' + CHANNEL.name + '/shows'; return '/api/v1/channels/' + CHANNEL.name + '/shows';
@ -1919,17 +1936,7 @@ var CSTShows = (function () {
} }
var blocksByStart = {}; var blocksByStart = {};
var covered = {};
var firstSegmentPlaced = {}; var firstSegmentPlaced = {};
function ensureDayMap(dayIdx) {
if (!covered[dayIdx]) covered[dayIdx] = {};
}
function markCovered(dayIdx, startHour, span) {
ensureDayMap(dayIdx);
for (var h = startHour + 1; h < startHour + span; h++) {
covered[dayIdx][h] = true;
}
}
function dayIndexFor(date) { function dayIndexFor(date) {
var midnight = new Date(date.getFullYear(), date.getMonth(), date.getDate()); var midnight = new Date(date.getFullYear(), date.getMonth(), date.getDate());
var weekMidnight = new Date(weekStart.getFullYear(), weekStart.getMonth(), weekStart.getDate()); var weekMidnight = new Date(weekStart.getFullYear(), weekStart.getMonth(), weekStart.getDate());
@ -1969,15 +1976,13 @@ var CSTShows = (function () {
isStart: isFirstVisibleSegment isStart: isFirstVisibleSegment
}); });
if (isFirstVisibleSegment) firstSegmentPlaced[show.id] = true; if (isFirstVisibleSegment) firstSegmentPlaced[show.id] = true;
if (span > 1) {
markCovered(dayIdx, startHour, span);
}
} }
cursor = dayEnd; cursor = dayEnd;
} }
}); });
var isAdmin = CLIENT.rank >= 2; var isAdmin = CLIENT.rank >= 2;
var rowspanRemaining = [0, 0, 0, 0, 0, 0, 0];
var table = $('<table class="table table-bordered table-condensed">'); var table = $('<table class="table table-bordered table-condensed">');
var thead = $('<thead><tr><th class="showschedule-time-col">Time</th></tr></thead>').appendTo(table); var thead = $('<thead><tr><th class="showschedule-time-col">Time</th></tr></thead>').appendTo(table);
var hrow = thead.find('tr'); var hrow = thead.find('tr');
@ -1995,7 +2000,8 @@ var CSTShows = (function () {
var cellDate = new Date(weekStart.getTime()); var cellDate = new Date(weekStart.getTime());
cellDate.setDate(weekStart.getDate() + col); cellDate.setDate(weekStart.getDate() + col);
cellDate.setHours(hour, 0, 0, 0); cellDate.setHours(hour, 0, 0, 0);
if (covered[col] && covered[col][hour]) { if (rowspanRemaining[col] > 0) {
rowspanRemaining[col] -= 1;
continue; continue;
} }
var cell = $('<td class="showschedule-cell">').appendTo(tr); var cell = $('<td class="showschedule-cell">').appendTo(tr);
@ -2015,6 +2021,7 @@ var CSTShows = (function () {
items.sort(function (a, b) { return a.date - b.date; }); items.sort(function (a, b) { return a.date - b.date; });
if (items.length === 1 && items[0].span > 1) { if (items.length === 1 && items[0].span > 1) {
cell.attr('rowspan', String(items[0].span)); cell.attr('rowspan', String(items[0].span));
rowspanRemaining[col] = items[0].span - 1;
cell cell
.addClass('showschedule-block-cell') .addClass('showschedule-block-cell')
.css('background-color', getShowBlockColor(items[0].show)); .css('background-color', getShowBlockColor(items[0].show));
@ -2034,7 +2041,7 @@ var CSTShows = (function () {
$('<a href="javascript:void(0)" class="showschedule-show">') $('<a href="javascript:void(0)" class="showschedule-show">')
.addClass('status-' + (item.show.status || 'scheduled')) .addClass('status-' + (item.show.status || 'scheduled'))
.text(label) .text(label)
.css('background', items.length === 1 ? 'transparent' : (item.show.color || '')) .css('background-color', item.show.color || getShowBlockColor(item.show))
.css('opacity', item.isStart ? '1' : '0.85') .css('opacity', item.isStart ? '1' : '0.85')
.attr('title', notesPreview || label) .attr('title', notesPreview || label)
.on('click', function () { .on('click', function () {
@ -2047,15 +2054,34 @@ var CSTShows = (function () {
}) })
.appendTo(cell); .appendTo(cell);
if (item.isStart) { if (item.isStart) {
var notesEl = null;
if (item.show.notes_html) { if (item.show.notes_html) {
$('<div class="showschedule-notes small">') notesEl = $('<div class="showschedule-notes small">')
.html(item.show.notes_html) .html(item.show.notes_html)
.appendTo(cell); .appendTo(cell);
} else if (notesPreview) { } else if (notesPreview) {
$('<div class="showschedule-notes small">') notesEl = $('<div class="showschedule-notes small">')
.text(notesPreview) .text(notesPreview)
.appendTo(cell); .appendTo(cell);
} }
if (notesEl && items.length > 1) {
notesEl
.css('background-color', item.show.color || getShowBlockColor(item.show))
.css('color', '#ffffff')
.css('border-radius', '3px')
.css('padding', '4px 6px')
.css('margin-top', '0')
.css('margin-bottom', '2px');
}
if (items.length > 1) {
cell.find('.showschedule-show:last').css({
'margin-bottom': '0',
'border-bottom-left-radius': '0',
'border-bottom-right-radius': '0'
});
}
} }
}); });
} }
@ -2172,6 +2198,31 @@ var CSTShows = (function () {
}); });
} }
function shouldAutoRefreshSchedule() {
if (document.hidden) return false;
if (window.CHANNEL && CHANNEL.opts && CHANNEL.opts.show_schedule === false) return false;
var row = $('#showschedule-row');
return row.length > 0 && row.is(':visible');
}
function setupScheduleAutoRefresh() {
if (scheduleRefreshTimer) {
clearInterval(scheduleRefreshTimer);
}
scheduleRefreshTimer = setInterval(function () {
if (shouldAutoRefreshSchedule()) {
load();
}
}, REFRESH_MS);
document.addEventListener('visibilitychange', function () {
if (shouldAutoRefreshSchedule()) {
load();
}
});
}
$('#cs-shows-create').on('click', function () { $('#cs-shows-create').on('click', function () {
var payload = readFormPayload(); var payload = readFormPayload();
@ -2259,6 +2310,7 @@ var CSTShows = (function () {
renderDraftPlaylist(); renderDraftPlaylist();
clearForm(); clearForm();
setNotesEditorMode('edit'); setNotesEditorMode('edit');
setupScheduleAutoRefresh();
load(); load();
return { load: load, selectShow: selectShow, prefillScheduledDate: prefillScheduledDate }; return { load: load, selectShow: selectShow, prefillScheduledDate: prefillScheduledDate };

View file

@ -985,6 +985,8 @@ function handleModPermissions() {
} }
$("#cs-show_public").prop("checked", CHANNEL.opts.show_public); $("#cs-show_public").prop("checked", CHANNEL.opts.show_public);
$("#cs-show_public").attr("disabled", CLIENT.rank < 3); $("#cs-show_public").attr("disabled", CLIENT.rank < 3);
$("#cs-show_schedule").prop("checked", CHANNEL.opts.show_schedule !== false);
$("#cs-show_schedule").attr("disabled", CLIENT.rank < 3);
$("#cs-password").val(CHANNEL.opts.password || ""); $("#cs-password").val(CHANNEL.opts.password || "");
$("#cs-password").attr("disabled", CLIENT.rank < 3); $("#cs-password").attr("disabled", CLIENT.rank < 3);
$("#cs-enable_link_regex").prop("checked", CHANNEL.opts.enable_link_regex); $("#cs-enable_link_regex").prop("checked", CHANNEL.opts.enable_link_regex);
@ -1026,6 +1028,9 @@ function handlePermissionChange() {
$("#qlockbtn").attr("disabled", !hasPermission("playlistlock")); $("#qlockbtn").attr("disabled", !hasPermission("playlistlock"));
setVisible("#showchansettings", CLIENT.rank >= 2); setVisible("#showchansettings", CLIENT.rank >= 2);
if (typeof window.applyScheduleVisibility === "function") {
window.applyScheduleVisibility();
}
setVisible("#playlistmanagerwrap", CLIENT.rank >= 1); setVisible("#playlistmanagerwrap", CLIENT.rank >= 1);
setVisible("#modflair", CLIENT.rank >= 2); setVisible("#modflair", CLIENT.rank >= 2);
setVisible("#guestlogin", CLIENT.rank < 0); setVisible("#guestlogin", CLIENT.rank < 0);