feat(opds): allow editing of registered catalogs (#3814)

* feat(opds): allow editing of registered catalogs

* chore(i18n): add translations for catalog edit feature

Translate "Remove", "Edit OPDS Catalog", and "Save Changes" across all
31 locales.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Huang Xin <chrox.huang@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Zeedif 2026-04-09 22:09:30 -06:00 committed by GitHub
parent bd866cb049
commit c6daf72da9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
32 changed files with 171 additions and 43 deletions

View file

@ -1239,5 +1239,8 @@
"Split Hyphens": "تقسيم الواصلات",
"Apply Theme Colors to PDF": "تطبيق ألوان السمة على PDF",
"Name": "الاسم",
"Unavailable": "غير متاح"
"Unavailable": "غير متاح",
"Remove": "إزالة",
"Edit OPDS Catalog": "تعديل كتالوج OPDS",
"Save Changes": "حفظ التغييرات"
}

View file

@ -1187,5 +1187,8 @@
"Split Hyphens": "হাইফেন বিভক্ত করুন",
"Apply Theme Colors to PDF": "PDF-এ থিম রং প্রয়োগ করুন",
"Name": "নাম",
"Unavailable": "অনুপলব্ধ"
"Unavailable": "অনুপলব্ধ",
"Remove": "সরান",
"Edit OPDS Catalog": "OPDS ক্যাটালগ সম্পাদনা",
"Save Changes": "পরিবর্তন সংরক্ষণ"
}

View file

@ -1174,5 +1174,8 @@
"Split Hyphens": "སྦྲེལ་རྟགས་གཅད་པ",
"Apply Theme Colors to PDF": "PDF ལ་བརྗོད་དོན་ཚོས་གཞི་སྤྱོད་པ",
"Name": "མིང",
"Unavailable": "རག་མི་ཐུབ"
"Unavailable": "རག་མི་ཐུབ",
"Remove": "བསུབ།",
"Edit OPDS Catalog": "OPDS དཀར་ཆག་རྩོམ་སྒྲིག",
"Save Changes": "བསྒྱུར་བཅོས་ཉར་ཚགས།"
}

View file

@ -1187,5 +1187,8 @@
"Split Hyphens": "Bindestriche trennen",
"Apply Theme Colors to PDF": "Designfarben auf PDF anwenden",
"Name": "Name",
"Unavailable": "Nicht verfügbar"
"Unavailable": "Nicht verfügbar",
"Remove": "Entfernen",
"Edit OPDS Catalog": "OPDS-Katalog bearbeiten",
"Save Changes": "Änderungen speichern"
}

View file

@ -1187,5 +1187,8 @@
"Split Hyphens": "Διαχωρισμός παύλων",
"Apply Theme Colors to PDF": "Εφαρμογή χρωμάτων θέματος σε PDF",
"Name": "Όνομα",
"Unavailable": "Μη διαθέσιμο"
"Unavailable": "Μη διαθέσιμο",
"Remove": "Αφαίρεση",
"Edit OPDS Catalog": "Επεξεργασία καταλόγου OPDS",
"Save Changes": "Αποθήκευση αλλαγών"
}

View file

@ -1200,5 +1200,8 @@
"Split Hyphens": "Dividir guiones",
"Apply Theme Colors to PDF": "Aplicar colores del tema al PDF",
"Name": "Nombre",
"Unavailable": "No disponible"
"Unavailable": "No disponible",
"Remove": "Eliminar",
"Edit OPDS Catalog": "Editar catálogo OPDS",
"Save Changes": "Guardar cambios"
}

View file

@ -1187,5 +1187,8 @@
"Split Hyphens": "تقسیم خط‌تیره‌ها",
"Apply Theme Colors to PDF": "اعمال رنگ‌های پوسته روی PDF",
"Name": "نام",
"Unavailable": "ناموجود"
"Unavailable": "ناموجود",
"Remove": "حذف",
"Edit OPDS Catalog": "ویرایش کاتالوگ OPDS",
"Save Changes": "ذخیره تغییرات"
}

View file

@ -1200,5 +1200,8 @@
"Split Hyphens": "Séparer les traits d'union",
"Apply Theme Colors to PDF": "Appliquer les couleurs du thème au PDF",
"Name": "Nom",
"Unavailable": "Indisponible"
"Unavailable": "Indisponible",
"Remove": "Supprimer",
"Edit OPDS Catalog": "Modifier le catalogue OPDS",
"Save Changes": "Enregistrer les modifications"
}

View file

@ -1200,5 +1200,8 @@
"Split Hyphens": "פיצול מקפים",
"Apply Theme Colors to PDF": "החל צבעי ערכת נושא על PDF",
"Name": "שם",
"Unavailable": "לא זמין"
"Unavailable": "לא זמין",
"Remove": "הסר",
"Edit OPDS Catalog": "עריכת קטלוג OPDS",
"Save Changes": "שמור שינויים"
}

View file

@ -1187,5 +1187,8 @@
"Split Hyphens": "हाइफ़न विभाजित करें",
"Apply Theme Colors to PDF": "PDF पर थीम रंग लागू करें",
"Name": "नाम",
"Unavailable": "अनुपलब्ध"
"Unavailable": "अनुपलब्ध",
"Remove": "हटाएँ",
"Edit OPDS Catalog": "OPDS कैटलॉग संपादित करें",
"Save Changes": "परिवर्तन सहेजें"
}

View file

@ -1187,5 +1187,8 @@
"Split Hyphens": "Kötőjelek felosztása",
"Apply Theme Colors to PDF": "Téma színeinek alkalmazása PDF-re",
"Name": "Név",
"Unavailable": "Nem elérhető"
"Unavailable": "Nem elérhető",
"Remove": "Eltávolítás",
"Edit OPDS Catalog": "OPDS katalógus szerkesztése",
"Save Changes": "Módosítások mentése"
}

View file

@ -1174,5 +1174,8 @@
"Split Hyphens": "Pisahkan Tanda Hubung",
"Apply Theme Colors to PDF": "Terapkan Warna Tema ke PDF",
"Name": "Nama",
"Unavailable": "Tidak Tersedia"
"Unavailable": "Tidak Tersedia",
"Remove": "Hapus",
"Edit OPDS Catalog": "Edit Katalog OPDS",
"Save Changes": "Simpan Perubahan"
}

View file

@ -1200,5 +1200,8 @@
"Split Hyphens": "Dividi trattini",
"Apply Theme Colors to PDF": "Applica colori tema al PDF",
"Name": "Nome",
"Unavailable": "Non disponibile"
"Unavailable": "Non disponibile",
"Remove": "Rimuovi",
"Edit OPDS Catalog": "Modifica catalogo OPDS",
"Save Changes": "Salva modifiche"
}

View file

@ -1174,5 +1174,8 @@
"Split Hyphens": "ハイフンで分割",
"Apply Theme Colors to PDF": "テーマカラーをPDFに適用",
"Name": "名前",
"Unavailable": "利用不可"
"Unavailable": "利用不可",
"Remove": "削除",
"Edit OPDS Catalog": "OPDSカタログを編集",
"Save Changes": "変更を保存"
}

View file

@ -1174,5 +1174,8 @@
"Split Hyphens": "하이픈 분리",
"Apply Theme Colors to PDF": "PDF에 테마 색상 적용",
"Name": "이름",
"Unavailable": "사용 불가"
"Unavailable": "사용 불가",
"Remove": "삭제",
"Edit OPDS Catalog": "OPDS 카탈로그 편집",
"Save Changes": "변경 사항 저장"
}

View file

@ -1174,5 +1174,8 @@
"Split Hyphens": "Pisahkan Sempang",
"Apply Theme Colors to PDF": "Gunakan Warna Tema pada PDF",
"Name": "Nama",
"Unavailable": "Tidak Tersedia"
"Unavailable": "Tidak Tersedia",
"Remove": "Alih keluar",
"Edit OPDS Catalog": "Edit Katalog OPDS",
"Save Changes": "Simpan Perubahan"
}

View file

@ -1187,5 +1187,8 @@
"Split Hyphens": "Afbreekstreepjes splitsen",
"Apply Theme Colors to PDF": "Themakleuren toepassen op PDF",
"Name": "Naam",
"Unavailable": "Niet beschikbaar"
"Unavailable": "Niet beschikbaar",
"Remove": "Verwijderen",
"Edit OPDS Catalog": "OPDS-catalogus bewerken",
"Save Changes": "Wijzigingen opslaan"
}

View file

@ -1213,5 +1213,8 @@
"Split Hyphens": "Dziel łączniki",
"Apply Theme Colors to PDF": "Zastosuj kolory motywu do PDF",
"Name": "Nazwa",
"Unavailable": "Niedostępne"
"Unavailable": "Niedostępne",
"Remove": "Usuń",
"Edit OPDS Catalog": "Edytuj katalog OPDS",
"Save Changes": "Zapisz zmiany"
}

View file

@ -1200,5 +1200,8 @@
"Split Hyphens": "Dividir hífens",
"Apply Theme Colors to PDF": "Aplicar cores do tema ao PDF",
"Name": "Nome",
"Unavailable": "Indisponível"
"Unavailable": "Indisponível",
"Remove": "Remover",
"Edit OPDS Catalog": "Editar catálogo OPDS",
"Save Changes": "Salvar alterações"
}

View file

@ -1200,5 +1200,8 @@
"Split Hyphens": "Desparte cratimele",
"Apply Theme Colors to PDF": "Aplică culorile temei la PDF",
"Name": "Nume",
"Unavailable": "Indisponibil"
"Unavailable": "Indisponibil",
"Remove": "Elimină",
"Edit OPDS Catalog": "Editare catalog OPDS",
"Save Changes": "Salvare modificări"
}

View file

@ -1213,5 +1213,8 @@
"Split Hyphens": "Разделить дефисы",
"Apply Theme Colors to PDF": "Применить цвета темы к PDF",
"Name": "Имя",
"Unavailable": "Недоступно"
"Unavailable": "Недоступно",
"Remove": "Удалить",
"Edit OPDS Catalog": "Редактировать каталог OPDS",
"Save Changes": "Сохранить изменения"
}

View file

@ -1187,5 +1187,8 @@
"Split Hyphens": "හයිෆන් බෙදන්න",
"Apply Theme Colors to PDF": "PDF වෙත තේමා වර්ණ යොදන්න",
"Name": "නම",
"Unavailable": "ලබාගත නොහැක"
"Unavailable": "ලබාගත නොහැක",
"Remove": "ඉවත් කරන්න",
"Edit OPDS Catalog": "OPDS නාමාවලිය සංස්කරණය",
"Save Changes": "වෙනස්කම් සුරකින්න"
}

View file

@ -1213,5 +1213,8 @@
"Split Hyphens": "Razdeli vezaje",
"Apply Theme Colors to PDF": "Uporabi barve teme za PDF",
"Name": "Ime",
"Unavailable": "Nedosegljivo"
"Unavailable": "Nedosegljivo",
"Remove": "Odstrani",
"Edit OPDS Catalog": "Uredi katalog OPDS",
"Save Changes": "Shrani spremembe"
}

View file

@ -1187,5 +1187,8 @@
"Split Hyphens": "Dela bindestreck",
"Apply Theme Colors to PDF": "Tillämpa temafärger på PDF",
"Name": "Namn",
"Unavailable": "Inte tillgängligt"
"Unavailable": "Inte tillgängligt",
"Remove": "Ta bort",
"Edit OPDS Catalog": "Redigera OPDS-katalog",
"Save Changes": "Spara ändringar"
}

View file

@ -1187,5 +1187,8 @@
"Split Hyphens": "ஹைபன்களைப் பிரி",
"Apply Theme Colors to PDF": "PDF-க்கு தீம் நிறங்களைப் பயன்படுத்து",
"Name": "பெயர்",
"Unavailable": "கிடைக்கவில்லை"
"Unavailable": "கிடைக்கவில்லை",
"Remove": "நீக்கு",
"Edit OPDS Catalog": "OPDS பட்டியலைத் திருத்து",
"Save Changes": "மாற்றங்களைச் சேமி"
}

View file

@ -1174,5 +1174,8 @@
"Split Hyphens": "แยกยัติภังค์",
"Apply Theme Colors to PDF": "ใช้สีธีมกับ PDF",
"Name": "ชื่อ",
"Unavailable": "ไม่พร้อมใช้งาน"
"Unavailable": "ไม่พร้อมใช้งาน",
"Remove": "ลบ",
"Edit OPDS Catalog": "แก้ไขแคตตาล็อก OPDS",
"Save Changes": "บันทึกการเปลี่ยนแปลง"
}

View file

@ -1187,5 +1187,8 @@
"Split Hyphens": "Tireleri Böl",
"Apply Theme Colors to PDF": "Tema Renklerini PDF'ye Uygula",
"Name": "Ad",
"Unavailable": "Kullanılamaz"
"Unavailable": "Kullanılamaz",
"Remove": "Kaldır",
"Edit OPDS Catalog": "OPDS Kataloğunu Düzenle",
"Save Changes": "Değişiklikleri Kaydet"
}

View file

@ -1213,5 +1213,8 @@
"Split Hyphens": "Розділити дефіси",
"Apply Theme Colors to PDF": "Застосувати кольори теми до PDF",
"Name": "Ім'я",
"Unavailable": "Недоступно"
"Unavailable": "Недоступно",
"Remove": "Видалити",
"Edit OPDS Catalog": "Редагувати каталог OPDS",
"Save Changes": "Зберегти зміни"
}

View file

@ -1174,5 +1174,8 @@
"Split Hyphens": "Tách gạch nối",
"Apply Theme Colors to PDF": "Áp dụng màu chủ đề cho PDF",
"Name": "Tên",
"Unavailable": "Không khả dụng"
"Unavailable": "Không khả dụng",
"Remove": "Xóa",
"Edit OPDS Catalog": "Chỉnh sửa danh mục OPDS",
"Save Changes": "Lưu thay đổi"
}

View file

@ -1174,5 +1174,8 @@
"Split Hyphens": "拆分连字符",
"Apply Theme Colors to PDF": "将主题颜色应用于 PDF",
"Name": "名称",
"Unavailable": "不可用"
"Unavailable": "不可用",
"Remove": "移除",
"Edit OPDS Catalog": "编辑 OPDS 目录",
"Save Changes": "保存更改"
}

View file

@ -1174,5 +1174,8 @@
"Split Hyphens": "拆分連字號",
"Apply Theme Colors to PDF": "將主題顏色套用至 PDF",
"Name": "名稱",
"Unavailable": "無法使用"
"Unavailable": "無法使用",
"Remove": "移除",
"Edit OPDS Catalog": "編輯 OPDS 目錄",
"Save Changes": "儲存變更"
}

View file

@ -2,7 +2,7 @@
import clsx from 'clsx';
import { useState } from 'react';
import { IoAdd, IoTrash, IoOpenOutline, IoBook, IoEyeOff, IoEye } from 'react-icons/io5';
import { IoAdd, IoTrash, IoOpenOutline, IoBook, IoEyeOff, IoEye, IoPencil } from 'react-icons/io5';
import { useRouter } from 'next/navigation';
import { useEnv } from '@/context/EnvContext';
import { useTranslation } from '@/hooks/useTranslation';
@ -77,6 +77,7 @@ export function CatalogManager() {
const { settings } = useSettingsStore();
const [catalogs, setCatalogs] = useState<OPDSCatalog[]>(() => settings.opdsCatalogs || []);
const [showAddDialog, setShowAddDialog] = useState(false);
const [editingCatalogId, setEditingCatalogId] = useState<string | null>(null);
const [newCatalog, setNewCatalog] = useState(EMPTY_NEW_CATALOG);
const [showPassword, setShowPassword] = useState(false);
const [urlError, setUrlError] = useState('');
@ -147,7 +148,7 @@ export function CatalogManager() {
}
const catalog: OPDSCatalog = {
id: Date.now().toString(),
id: editingCatalogId || Date.now().toString(),
name: newCatalog.name,
url: newCatalog.url,
description: newCatalog.description,
@ -158,15 +159,35 @@ export function CatalogManager() {
: undefined,
};
saveCatalogs([catalog, ...catalogs]);
if (editingCatalogId) {
saveCatalogs(catalogs.map((c) => (c.id === editingCatalogId ? catalog : c)));
} else {
saveCatalogs([catalog, ...catalogs]);
}
setNewCatalog(EMPTY_NEW_CATALOG);
setUrlError('');
setHeaderError('');
setProxyConsentError('');
setIsValidating(false);
setEditingCatalogId(null);
setShowAddDialog(false);
};
const handleEditCatalog = (catalog: OPDSCatalog) => {
setNewCatalog({
name: catalog.name,
url: catalog.url,
description: catalog.description || '',
username: catalog.username || '',
password: catalog.password || '',
customHeadersInput: formatOPDSCustomHeadersInput(catalog.customHeaders),
proxyConsent: false,
});
setEditingCatalogId(catalog.id);
setShowAddDialog(true);
};
const handleAddPopularCatalog = (popularCatalog: OPDSCatalog) => {
if (catalogs.some((c) => c.url === popularCatalog.url)) {
return;
@ -192,6 +213,7 @@ export function CatalogManager() {
setHeaderError('');
setProxyConsentError('');
setShowPassword(false);
setEditingCatalogId(null);
};
return (
@ -239,13 +261,22 @@ export function CatalogManager() {
{catalog.icon && <span className=''>{catalog.icon}</span>}
{catalog.name}
</h3>
<button
onClick={() => handleRemoveCatalog(catalog.id)}
className='btn btn-ghost btn-xs btn-square'
title='Remove'
>
<IoTrash className='h-4 w-4' />
</button>
<div className='flex gap-1'>
<button
onClick={() => handleEditCatalog(catalog)}
className='btn btn-ghost btn-xs btn-square'
title={_('Edit')}
>
<IoPencil className='h-4 w-4' />
</button>
<button
onClick={() => handleRemoveCatalog(catalog.id)}
className='btn btn-ghost btn-xs btn-square'
title={_('Remove')}
>
<IoTrash className='h-4 w-4' />
</button>
</div>
</div>
{catalog.description && (
<p className='text-base-content/70 mb-2 line-clamp-1 h-6 text-sm sm:line-clamp-2 sm:h-10'>
@ -329,12 +360,14 @@ export function CatalogManager() {
</div>
</section>
{/* Add Catalog Dialog */}
{/* Add/Edit Catalog Dialog */}
{showAddDialog && (
<ModalPortal>
<dialog className='modal modal-open'>
<div className='modal-box'>
<h3 className='mb-4 text-lg font-bold'>{_('Add OPDS Catalog')}</h3>
<h3 className='mb-4 text-lg font-bold'>
{editingCatalogId ? _('Edit OPDS Catalog') : _('Add OPDS Catalog')}
</h3>
<form
onSubmit={(e) => {
e.preventDefault();
@ -518,6 +551,8 @@ export function CatalogManager() {
<span className='loading loading-spinner loading-sm'></span>
{_('Validating...')}
</>
) : editingCatalogId ? (
_('Save Changes')
) : (
_('Add Catalog')
)}