mirror of
https://github.com/KuekHaoYang/KVideo.git
synced 2026-06-01 19:39:47 +08:00
feat: Introduce user-editable source ID field with automatic generation and editing state handling.
This commit is contained in:
@@ -14,7 +14,7 @@ interface AddSourceModalProps {
|
||||
}
|
||||
|
||||
export function AddSourceModal({ isOpen, onClose, onAdd, existingIds, initialValues }: AddSourceModalProps) {
|
||||
const { name, setName, url, setUrl, error, handleSubmit } = useAddSourceForm({
|
||||
const { name, setName, customId, setCustomId, url, setUrl, error, handleSubmit, isEditing } = useAddSourceForm({
|
||||
isOpen,
|
||||
existingIds,
|
||||
onAdd,
|
||||
@@ -53,6 +53,24 @@ export function AddSourceModal({ isOpen, onClose, onAdd, existingIds, initialVal
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label htmlFor="source-id" className="block mb-2 font-medium text-[var(--text-color)]">
|
||||
源 ID
|
||||
</label>
|
||||
<input
|
||||
id="source-id"
|
||||
type="text"
|
||||
value={customId}
|
||||
onChange={(e) => setCustomId(e.target.value.toLowerCase().replace(/[^a-z0-9-]/g, ''))}
|
||||
placeholder="自动生成,可手动修改"
|
||||
disabled={isEditing}
|
||||
className="w-full bg-[var(--glass-bg)] backdrop-blur-md border border-[var(--glass-border)] rounded-[var(--radius-2xl)] px-4 py-3 text-[var(--text-color)] placeholder:text-[var(--text-color-secondary)] focus:outline-none focus:border-[var(--accent-color)] focus:ring-4 focus:ring-[color-mix(in_srgb,var(--accent-color)_30%,transparent)] transition-all duration-[0.4s] disabled:opacity-50"
|
||||
/>
|
||||
<p className="mt-1 text-xs text-[var(--text-color-secondary)]">
|
||||
用于唯一标识此源,仅支持小写字母、数字和连字符
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label htmlFor="source-url" className="block mb-2 font-medium text-[var(--text-color)]">
|
||||
接口地址
|
||||
|
||||
@@ -15,8 +15,15 @@ interface UseAddSourceFormProps {
|
||||
initialValues?: VideoSource | null;
|
||||
}
|
||||
|
||||
function generateIdFromName(name: string): string {
|
||||
const slug = name.toLowerCase().replace(/[^a-z0-9]/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '');
|
||||
return slug || `custom-${Date.now().toString(36)}`;
|
||||
}
|
||||
|
||||
export function useAddSourceForm({ isOpen, existingIds, onAdd, onClose, initialValues }: UseAddSourceFormProps) {
|
||||
const [name, setName] = useState('');
|
||||
const [customId, setCustomId] = useState('');
|
||||
const [idManuallyEdited, setIdManuallyEdited] = useState(false);
|
||||
const [url, setUrl] = useState('');
|
||||
const [error, setError] = useState('');
|
||||
|
||||
@@ -24,15 +31,31 @@ export function useAddSourceForm({ isOpen, existingIds, onAdd, onClose, initialV
|
||||
if (isOpen) {
|
||||
if (initialValues) {
|
||||
setName(initialValues.name);
|
||||
setCustomId(initialValues.id);
|
||||
setUrl(initialValues.baseUrl);
|
||||
setIdManuallyEdited(true);
|
||||
} else {
|
||||
setName('');
|
||||
setCustomId('');
|
||||
setUrl('');
|
||||
setIdManuallyEdited(false);
|
||||
}
|
||||
setError('');
|
||||
}
|
||||
}, [isOpen, initialValues]);
|
||||
|
||||
const handleNameChange = (newName: string) => {
|
||||
setName(newName);
|
||||
if (!idManuallyEdited && !initialValues) {
|
||||
setCustomId(generateIdFromName(newName));
|
||||
}
|
||||
};
|
||||
|
||||
const handleIdChange = (newId: string) => {
|
||||
setIdManuallyEdited(true);
|
||||
setCustomId(newId);
|
||||
};
|
||||
|
||||
const handleSubmit = (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
setError('');
|
||||
@@ -49,18 +72,11 @@ export function useAddSourceForm({ isOpen, existingIds, onAdd, onClose, initialV
|
||||
return;
|
||||
}
|
||||
|
||||
let id = initialValues?.id;
|
||||
const id = customId.trim() || generateIdFromName(name);
|
||||
|
||||
// Only generate new ID if not editing or if name changed (optional, maybe keep ID stable?)
|
||||
// For now, let's keep ID stable if editing, unless we want to allow re-generating ID.
|
||||
// But if we re-generate ID, we lose history/preferences for that ID.
|
||||
// So better to keep ID if editing.
|
||||
if (!id) {
|
||||
id = name.toLowerCase().replace(/[^a-z0-9]/g, '-');
|
||||
if (existingIds.includes(id)) {
|
||||
setError('此源名称已存在');
|
||||
return;
|
||||
}
|
||||
if (!initialValues && existingIds.includes(id)) {
|
||||
setError('此源 ID 已存在,请修改源 ID');
|
||||
return;
|
||||
}
|
||||
|
||||
const newSource: VideoSource = {
|
||||
@@ -79,10 +95,13 @@ export function useAddSourceForm({ isOpen, existingIds, onAdd, onClose, initialV
|
||||
|
||||
return {
|
||||
name,
|
||||
setName,
|
||||
setName: handleNameChange,
|
||||
customId,
|
||||
setCustomId: handleIdChange,
|
||||
url,
|
||||
setUrl,
|
||||
error,
|
||||
handleSubmit,
|
||||
isEditing: !!initialValues,
|
||||
};
|
||||
}
|
||||
|
||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "kvideo",
|
||||
"version": "4.1.6",
|
||||
"version": "4.1.7",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "kvideo",
|
||||
"version": "4.1.6",
|
||||
"version": "4.1.7",
|
||||
"dependencies": {
|
||||
"@dnd-kit/core": "^6.3.1",
|
||||
"@dnd-kit/sortable": "^10.0.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "kvideo",
|
||||
"version": "4.1.6",
|
||||
"version": "4.1.7",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
|
||||
Reference in New Issue
Block a user