mirror of
https://github.com/Dispatcharr/Dispatcharr.git
synced 2026-01-22 18:28:00 +00:00
Enhancement: Added "Hide Stale" filter to quickly hide streams marked as stale.
Some checks are pending
CI Pipeline / prepare (push) Waiting to run
CI Pipeline / docker (amd64, ubuntu-24.04) (push) Blocked by required conditions
CI Pipeline / docker (arm64, ubuntu-24.04-arm) (push) Blocked by required conditions
CI Pipeline / create-manifest (push) Blocked by required conditions
Build and Push Multi-Arch Docker Image / build-and-push (push) Waiting to run
Frontend Tests / test (push) Waiting to run
Some checks are pending
CI Pipeline / prepare (push) Waiting to run
CI Pipeline / docker (amd64, ubuntu-24.04) (push) Blocked by required conditions
CI Pipeline / docker (arm64, ubuntu-24.04-arm) (push) Blocked by required conditions
CI Pipeline / create-manifest (push) Blocked by required conditions
Build and Push Multi-Arch Docker Image / build-and-push (push) Waiting to run
Frontend Tests / test (push) Waiting to run
This commit is contained in:
parent
c9b454431c
commit
2fc2486c34
3 changed files with 36 additions and 6 deletions
|
|
@ -25,6 +25,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
- Only polls when active channel list changes, not on stats refresh
|
||||
- Channel preview button: Added preview functionality to active stream cards on stats page
|
||||
- Unassociated streams filter: Added "Only Unassociated" filter option to streams table for quickly finding streams not assigned to any channels - Thanks [@JeffreyBytes](https://github.com/JeffreyBytes) (Closes #667)
|
||||
- Streams table: Added "Hide Stale" filter to quickly hide streams marked as stale.
|
||||
- Client-side logo caching: Added `Cache-Control` and `Last-Modified` headers to logo responses, enabling browsers to cache logos locally for 4 hours (local files) and respecting upstream cache headers (remote logos). This reduces network traffic and nginx load while providing faster page loads through browser-level caching that complements the existing nginx server-side cache - Thanks [@DawtCom](https://github.com/DawtCom)
|
||||
- DVR recording remux fallback strategy: Implemented two-stage TS→MP4→MKV fallback when direct TS→MKV conversion fails due to timestamp issues. On remux failure, system now attempts TS→MP4 conversion (MP4 container handles broken timestamps better) followed by MP4→MKV conversion, automatically recovering from provider timestamp corruption. Failed conversions now properly clean up partial files and preserve source TS for manual recovery.
|
||||
- Mature content filtering support:
|
||||
|
|
|
|||
|
|
@ -149,7 +149,7 @@ class StreamViewSet(viewsets.ModelViewSet):
|
|||
qs = qs.filter(channels__id=assigned)
|
||||
|
||||
unassigned = self.request.query_params.get("unassigned")
|
||||
if unassigned == "1":
|
||||
if unassigned and str(unassigned).lower() in ("1", "true", "yes", "on"):
|
||||
# Use annotation with Count for better performance on large datasets
|
||||
qs = qs.annotate(channel_count=Count('channels')).filter(channel_count=0)
|
||||
|
||||
|
|
@ -158,6 +158,11 @@ class StreamViewSet(viewsets.ModelViewSet):
|
|||
group_names = channel_group.split(",")
|
||||
qs = qs.filter(channel_group__name__in=group_names)
|
||||
|
||||
# Allow client to hide stale streams (streams marked as is_stale=True)
|
||||
hide_stale = self.request.query_params.get("hide_stale")
|
||||
if hide_stale and str(hide_stale).lower() in ("1", "true", "yes", "on"):
|
||||
qs = qs.filter(is_stale=False)
|
||||
|
||||
return qs
|
||||
|
||||
def list(self, request, *args, **kwargs):
|
||||
|
|
|
|||
|
|
@ -232,7 +232,8 @@ const StreamsTable = ({ onReady }) => {
|
|||
name: '',
|
||||
channel_group: '',
|
||||
m3u_account: '',
|
||||
unassigned: '',
|
||||
unassigned: false,
|
||||
hide_stale: false,
|
||||
});
|
||||
const [columnSizing, setColumnSizing] = useLocalStorage(
|
||||
'streams-table-column-sizing',
|
||||
|
|
@ -398,7 +399,14 @@ const StreamsTable = ({ onReady }) => {
|
|||
const toggleUnassignedOnly = () => {
|
||||
setFilters((prev) => ({
|
||||
...prev,
|
||||
unassigned: prev.unassigned === '1' ? '' : '1',
|
||||
unassigned: !prev.unassigned,
|
||||
}));
|
||||
};
|
||||
|
||||
const toggleHideStale = () => {
|
||||
setFilters((prev) => ({
|
||||
...prev,
|
||||
hide_stale: !prev.hide_stale,
|
||||
}));
|
||||
};
|
||||
|
||||
|
|
@ -426,9 +434,13 @@ const StreamsTable = ({ onReady }) => {
|
|||
params.append('ordering', `${sortDirection}${sortField}`);
|
||||
}
|
||||
|
||||
// Apply debounced filters
|
||||
// Apply debounced filters; send boolean filters as 'true' when set
|
||||
Object.entries(debouncedFilters).forEach(([key, value]) => {
|
||||
if (value) params.append(key, value);
|
||||
if (typeof value === 'boolean') {
|
||||
if (value) params.append(key, 'true');
|
||||
} else if (value !== null && value !== undefined && value !== '') {
|
||||
params.append(key, String(value));
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
|
|
@ -1188,7 +1200,7 @@ const StreamsTable = ({ onReady }) => {
|
|||
<Menu.Item
|
||||
onClick={toggleUnassignedOnly}
|
||||
leftSection={
|
||||
filters.unassigned === '1' ? (
|
||||
filters.unassigned === true ? (
|
||||
<SquareCheck size={18} />
|
||||
) : (
|
||||
<Square size={18} />
|
||||
|
|
@ -1197,6 +1209,18 @@ const StreamsTable = ({ onReady }) => {
|
|||
>
|
||||
<Text size="xs">Only Unassociated</Text>
|
||||
</Menu.Item>
|
||||
<Menu.Item
|
||||
onClick={toggleHideStale}
|
||||
leftSection={
|
||||
filters.hide_stale === true ? (
|
||||
<SquareCheck size={18} />
|
||||
) : (
|
||||
<Square size={18} />
|
||||
)
|
||||
}
|
||||
>
|
||||
<Text size="xs">Hide Stale</Text>
|
||||
</Menu.Item>
|
||||
</Menu.Dropdown>
|
||||
</Menu>
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue