diff --git a/CHANGELOG.md b/CHANGELOG.md index 1b2b8333..c2279057 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -64,6 +64,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- Redesigned the User settings modal with a tabbed layout: **Account** (username, email, name, password), **Permissions** (user level, stream limit, channel profiles, mature content filter - admin only), **EPG Defaults** (days forward/back), and **API & XC** (XC password, API key management). Fields are now logically grouped rather than split across two ad-hoc columns. - EPG channel scanning now automatically removes stale `EPGData` entries. tvg-ids that were present in a previous scan but are no longer found in the upstream source, provided they are not mapped to any channel. This prevents unbounded database bloat over time. Entries mapped to at least one channel are always preserved. - Rewrote the M3U line parser as an `iter_m3u_entries` generator that owns the full per-entry state machine. Intermediate directive lines between `#EXTINF` and the stream URL are now handled correctly rather than corrupting the pending entry or being silently misassigned. A `#EXTINF` with no following URL is discarded with a warning instead of carrying over a `url`-less entry into batch processing. Attribute keys are normalised to lowercase during parsing (provider attribute names remain case-insensitive end-to-end). The `#EXTINF` attribute regex is pre-compiled at module load, and attribute lookups use O(1) `dict.get()` instead of linear scans — approximately 10% faster parsing on large M3U files. - Added support for the `#EXTGRP` directive in M3U files. When a `group-title` attribute is absent from the `#EXTINF` line, the value from a following `#EXTGRP:` line is used as the group. An explicit `group-title` attribute always takes priority. (Closes #1088) diff --git a/frontend/src/components/forms/User.jsx b/frontend/src/components/forms/User.jsx index dd015511..910664fa 100644 --- a/frontend/src/components/forms/User.jsx +++ b/frontend/src/components/forms/User.jsx @@ -1,11 +1,9 @@ -// Modal.js import React, { useState, useEffect } from 'react'; import API from '../../api'; import { TextInput, Button, Modal, - Flex, Select, PasswordInput, Group, @@ -13,14 +11,12 @@ import { MultiSelect, ActionIcon, Switch, - Box, - Tooltip, - Grid, - SimpleGrid, NumberInput, + Tabs, + Text, useMantineTheme, } from '@mantine/core'; -import { RotateCcwKey, RotateCw, X } from 'lucide-react'; +import { RotateCcwKey, X } from 'lucide-react'; import { Copy, Key } from 'lucide-react'; import { useForm } from '@mantine/form'; import useChannelsStore from '../../store/channels'; @@ -247,198 +243,197 @@ const User = ({ user = null, isOpen, onClose }) => { return (
- - - - - - - - + + + Account {showPermissions && ( - <> - ({ label: USER_LEVEL_LABELS[value], value: `${value}`, - }; + }))} + {...form.getInputProps('user_level')} + key={form.key('user_level')} + /> + + + ({ + label: profile.name, + value: `${profile.id}`, + }))} + /> + + + + )} + + + + These defaults apply when no URL parameters are specified — + useful for XC clients that cannot pass custom query parameters. + + - - )} - + + + + - - - - - - - - - } - /> - - {showPermissions && ( - ({ - label: profile.name, - value: `${profile.id}`, - }))} - /> - )} - - {showPermissions && ( - - - - - - )} - - - - - - {canGenerateKey && ( - - {userAPIKey && ( - - copyToClipboard(userAPIKey, { - successTitle: 'API Key Copied!', - successMessage: - 'The API Key has been copied to your clipboard.', - }) - } - > - - - } - /> - )} - - - - + + + } + /> + {canGenerateKey && ( + {userAPIKey && ( + + copyToClipboard(userAPIKey, { + successTitle: 'API Key Copied!', + successMessage: + 'The API Key has been copied to your clipboard.', + }) + } + > + + + } + /> + )} + - )} - - - )} - - + {userAPIKey && ( + + )} + + + )} + + + - + - +
);