deselect a channel on "all <channel-group>"

This commit is contained in:
Simon
2026-06-23 06:46:06 +00:00
parent 3d4b90b0e1
commit bec981a262
2 changed files with 43 additions and 7 deletions

View File

@@ -50,6 +50,11 @@ App.session = App.session || {};
});
};
// Synthetic filter id used to let a channel group expose its member
// channels as a toggleable multi-select, so the user can browse "All <group>"
// while disabling individual channels.
App.session.GROUP_CHANNELS_OPTION_ID = '__groupChannels';
// Options/session helpers that power channel selection and filters.
App.session.serializeOptions = function(options) {
const serialized = {};
@@ -71,9 +76,13 @@ App.session = App.session || {};
const allOptions = optionGroup.options || [];
const savedValue = saved[optionGroup.id];
if (optionGroup.multiSelect) {
const selectedIds = Array.isArray(savedValue) ? savedValue : [];
const selected = allOptions.filter((opt) => selectedIds.includes(opt.id));
hydrated[optionGroup.id] = selected.length > 0 ? selected : allOptions.slice(0, 1);
const fallback = optionGroup.selectAllDefault ? allOptions.slice() : allOptions.slice(0, 1);
if (Array.isArray(savedValue)) {
const selected = allOptions.filter((opt) => savedValue.includes(opt.id));
hydrated[optionGroup.id] = selected.length > 0 ? selected : fallback;
} else {
hydrated[optionGroup.id] = fallback;
}
} else {
const selected = allOptions.find((opt) => opt.id === savedValue) || allOptions[0];
if (selected) hydrated[optionGroup.id] = selected;
@@ -91,12 +100,26 @@ App.session = App.session || {};
const channelIds = Array.isArray(group.channelIds) ?
group.channelIds.filter((id) => knownIds.has(id)) :
[];
const channelOptions = channelIds.map((id) => {
const channel = (channels || []).find((ch) => ch.id === id);
return { id: id, title: (channel && (channel.name || channel.id)) || id };
});
return {
id: `group:${group.id}`,
name: group.title || group.id,
isGroup: true,
groupId: group.id,
channelIds: channelIds
channelIds: channelIds,
// Expose member channels as a multi-select filter (all on by
// default) so the user can disable individual channels while
// browsing the whole group.
options: channelOptions.length > 0 ? [{
id: App.session.GROUP_CHANNELS_OPTION_ID,
title: 'Channels',
multiSelect: true,
selectAllDefault: true,
options: channelOptions
}] : []
};
};
@@ -131,7 +154,9 @@ App.session = App.session || {};
channel.options.forEach((optionGroup) => {
if (!optionGroup.options || optionGroup.options.length === 0) return;
if (optionGroup.multiSelect) {
selected[optionGroup.id] = [optionGroup.options[0]];
selected[optionGroup.id] = optionGroup.selectAllDefault ?
optionGroup.options.slice() :
[optionGroup.options[0]];
} else {
selected[optionGroup.id] = optionGroup.options[0];
}

View File

@@ -150,11 +150,22 @@ App.videos = App.videos || {};
const searchInput = document.getElementById('search-input');
const query = searchInput ? searchInput.value : "";
if (!state.groupCursors || state.groupCursors.groupId !== group.id || state.groupCursors.query !== query) {
// Honor the per-group "Channels" multi-select filter so disabled
// channels are skipped. Falls back to the full group when nothing is
// selected (e.g. older sessions without the filter).
const selectedChannels = session.options ? session.options[App.session.GROUP_CHANNELS_OPTION_ID] : null;
const enabledIds = (Array.isArray(selectedChannels) && selectedChannels.length > 0 ?
selectedChannels.map((opt) => opt.id) :
group.channelIds).filter((id) => group.channelIds.includes(id));
const signature = enabledIds.join(',');
if (!state.groupCursors || state.groupCursors.groupId !== group.id ||
state.groupCursors.query !== query || state.groupCursors.signature !== signature) {
state.groupCursors = {
groupId: group.id,
query: query,
channels: group.channelIds.map((id) => ({ id, page: 1, hasNextPage: true }))
signature: signature,
channels: enabledIds.map((id) => ({ id, page: 1, hasNextPage: true }))
};
}