Explorar o código

feat(logs): add auto-update toggle to Access Logs and Logs viewers

A checkbox in both the Xray Access Logs and panel Logs modals polls the
existing refresh every 5s while enabled, respecting the current row count,
level/filter, and Direct/Blocked/Proxy selections. The poller tears down on
close or untoggle. Adds a localized pages.index.autoUpdate key to all 13 locales.
MHSanaei hai 1 día
pai
achega
9381fa284b

+ 17 - 0
frontend/src/pages/index/LogModal.tsx

@@ -13,12 +13,15 @@ interface LogModalProps {
   onClose: () => void;
 }
 
+const AUTO_UPDATE_INTERVAL = 5000;
+
 export default function LogModal({ open, onClose }: LogModalProps) {
   const { t } = useTranslation();
   const { isMobile } = useMediaQuery();
   const [rows, setRows] = useState('20');
   const [level, setLevel] = useState('info');
   const [syslog, setSyslog] = useState(false);
+  const [autoUpdate, setAutoUpdate] = useState(false);
   const [loading, setLoading] = useState(false);
   const [logs, setLogs] = useState<string[]>([]);
   const openRef = useRef(open);
@@ -39,6 +42,11 @@ export default function LogModal({ open, onClose }: LogModalProps) {
     }
   }, [rows, level, syslog]);
 
+  const refreshRef = useRef(refresh);
+  useEffect(() => {
+    refreshRef.current = refresh;
+  }, [refresh]);
+
   useEffect(() => {
     openRef.current = open;
     if (open) refresh();
@@ -48,6 +56,12 @@ export default function LogModal({ open, onClose }: LogModalProps) {
     if (openRef.current) refresh();
   }, [rows, level, syslog, refresh]);
 
+  useEffect(() => {
+    if (!open || !autoUpdate) return;
+    const id = setInterval(() => refreshRef.current(), AUTO_UPDATE_INTERVAL);
+    return () => clearInterval(id);
+  }, [open, autoUpdate]);
+
   const parsedLogs = useMemo(() => logs.map(parseLogLine), [logs]);
 
   function download() {
@@ -106,6 +120,9 @@ export default function LogModal({ open, onClose }: LogModalProps) {
           <Checkbox checked={syslog} onChange={(e) => setSyslog(e.target.checked)}>
             SysLog
           </Checkbox>
+          <Checkbox checked={autoUpdate} onChange={(e) => setAutoUpdate(e.target.checked)}>
+            {t('pages.index.autoUpdate')}
+          </Checkbox>
         </Form.Item>
         <Form.Item className="download-item">
           <Button type="primary" onClick={download} icon={<DownloadOutlined />} />

+ 17 - 0
frontend/src/pages/index/XrayLogModal.tsx

@@ -44,6 +44,8 @@ function shortTime(value?: string | number): string {
   return `${hh}:${mm}:${ss}`;
 }
 
+const AUTO_UPDATE_INTERVAL = 5000;
+
 export default function XrayLogModal({ open, onClose }: XrayLogModalProps) {
   const { t } = useTranslation();
   const { datepicker } = useDatepicker();
@@ -53,6 +55,7 @@ export default function XrayLogModal({ open, onClose }: XrayLogModalProps) {
   const [showDirect, setShowDirect] = useState(true);
   const [showBlocked, setShowBlocked] = useState(true);
   const [showProxy, setShowProxy] = useState(true);
+  const [autoUpdate, setAutoUpdate] = useState(false);
   const [loading, setLoading] = useState(false);
   const [logs, setLogs] = useState<XrayLogEntry[]>([]);
   const openRef = useRef(open);
@@ -75,6 +78,11 @@ export default function XrayLogModal({ open, onClose }: XrayLogModalProps) {
     }
   }, [rows, filter, showDirect, showBlocked, showProxy]);
 
+  const refreshRef = useRef(refresh);
+  useEffect(() => {
+    refreshRef.current = refresh;
+  }, [refresh]);
+
   useEffect(() => {
     openRef.current = open;
     if (open) refresh();
@@ -84,6 +92,12 @@ export default function XrayLogModal({ open, onClose }: XrayLogModalProps) {
     if (openRef.current) refresh();
   }, [rows, showDirect, showBlocked, showProxy, refresh]);
 
+  useEffect(() => {
+    if (!open || !autoUpdate) return;
+    const id = setInterval(() => refreshRef.current(), AUTO_UPDATE_INTERVAL);
+    return () => clearInterval(id);
+  }, [open, autoUpdate]);
+
   function fullDate(value?: string | number): string {
     return IntlUtil.formatDate(value, datepicker);
   }
@@ -158,6 +172,9 @@ export default function XrayLogModal({ open, onClose }: XrayLogModalProps) {
           <Checkbox checked={showProxy} onChange={(e) => setShowProxy(e.target.checked)}>
             Proxy
           </Checkbox>
+          <Checkbox checked={autoUpdate} onChange={(e) => setAutoUpdate(e.target.checked)}>
+            {t('pages.index.autoUpdate')}
+          </Checkbox>
         </Form.Item>
         <Form.Item className="download-item">
           <Button type="primary" onClick={download} icon={<DownloadOutlined />} />

+ 1 - 0
internal/web/translation/ar-EG.json

@@ -246,6 +246,7 @@
       "dontRefresh": "التثبيت شغال، متعملش Refresh للصفحة",
       "logs": "السجلات",
       "accessLogs": "سجلات الوصول",
+      "autoUpdate": "تحديث تلقائي",
       "config": "الإعدادات",
       "backup": "نسخ احتياطي",
       "backupTitle": "نسخ احتياطي واستعادة",

+ 1 - 0
internal/web/translation/en-US.json

@@ -246,6 +246,7 @@
       "dontRefresh": "Installation is in progress, please do not refresh this page",
       "logs": "Logs",
       "accessLogs": "Access Logs",
+      "autoUpdate": "Auto Update",
       "config": "Config",
       "backup": "Backup",
       "backupTitle": "Backup & Restore",

+ 1 - 0
internal/web/translation/es-ES.json

@@ -246,6 +246,7 @@
       "dontRefresh": "La instalación está en progreso, por favor no actualices esta página.",
       "logs": "Registros",
       "accessLogs": "Registros de acceso",
+      "autoUpdate": "Actualización automática",
       "config": "Configuración",
       "backup": "Copia de seguridad",
       "backupTitle": "Copia & Restauración",

+ 1 - 0
internal/web/translation/fa-IR.json

@@ -246,6 +246,7 @@
       "dontRefresh": "در حال نصب، لطفا صفحه را رفرش نکنید",
       "logs": "لاگ‌ها",
       "accessLogs": "لاگ‌های دسترسی",
+      "autoUpdate": "به‌روزرسانی خودکار",
       "config": "پیکربندی",
       "backup": "پشتیبان‌گیری",
       "backupTitle": "پشتیبان‌گیری و بازیابی",

+ 1 - 0
internal/web/translation/id-ID.json

@@ -246,6 +246,7 @@
       "dontRefresh": "Instalasi sedang berlangsung, harap jangan menyegarkan halaman ini",
       "logs": "Log",
       "accessLogs": "Log Akses",
+      "autoUpdate": "Pembaruan Otomatis",
       "config": "Konfigurasi",
       "backup": "Cadangan",
       "backupTitle": "Cadangan & Pulihkan",

+ 1 - 0
internal/web/translation/ja-JP.json

@@ -246,6 +246,7 @@
       "dontRefresh": "インストール中、このページをリロードしないでください",
       "logs": "ログ",
       "accessLogs": "アクセスログ",
+      "autoUpdate": "自動更新",
       "config": "設定",
       "backup": "バックアップ",
       "backupTitle": "バックアップと復元",

+ 1 - 0
internal/web/translation/pt-BR.json

@@ -246,6 +246,7 @@
       "dontRefresh": "Instalação em andamento, por favor não atualize a página",
       "logs": "Logs",
       "accessLogs": "Logs de acesso",
+      "autoUpdate": "Atualização automática",
       "config": "Configuração",
       "backup": "Backup",
       "backupTitle": "Backup & Restauração",

+ 1 - 0
internal/web/translation/ru-RU.json

@@ -246,6 +246,7 @@
       "dontRefresh": "Установка в процессе. Не обновляйте страницу",
       "logs": "Логи",
       "accessLogs": "Логи доступа",
+      "autoUpdate": "Автообновление",
       "config": "Конфигурация",
       "backup": "Резервная копия",
       "backupTitle": "Бэкап и восстановление",

+ 1 - 0
internal/web/translation/tr-TR.json

@@ -246,6 +246,7 @@
       "dontRefresh": "Kurulum devam ediyor, lütfen bu sayfayı yenilemeyin",
       "logs": "Günlükler",
       "accessLogs": "Erişim Günlükleri",
+      "autoUpdate": "Otomatik Güncelleme",
       "config": "Yapılandırma",
       "backup": "Yedek",
       "backupTitle": "Yedekleme ve Geri Yükleme",

+ 1 - 0
internal/web/translation/uk-UA.json

@@ -246,6 +246,7 @@
       "dontRefresh": "Інсталяція триває, будь ласка, не оновлюйте цю сторінку",
       "logs": "Логи",
       "accessLogs": "Логи доступу",
+      "autoUpdate": "Автооновлення",
       "config": "Конфігурація",
       "backup": "Резервна копія",
       "backupTitle": "Резервне копіювання та відновлення",

+ 1 - 0
internal/web/translation/vi-VN.json

@@ -246,6 +246,7 @@
       "dontRefresh": "Đang tiến hành cài đặt, vui lòng không làm mới trang này.",
       "logs": "Nhật ký",
       "accessLogs": "Nhật ký truy cập",
+      "autoUpdate": "Tự động cập nhật",
       "config": "Cấu hình",
       "backup": "Sao lưu",
       "backupTitle": "Sao lưu & Khôi phục",

+ 1 - 0
internal/web/translation/zh-CN.json

@@ -246,6 +246,7 @@
       "dontRefresh": "安装中,请勿刷新此页面",
       "logs": "日志",
       "accessLogs": "访问日志",
+      "autoUpdate": "自动更新",
       "config": "配置",
       "backup": "备份",
       "backupTitle": "备份和恢复",

+ 1 - 0
internal/web/translation/zh-TW.json

@@ -246,6 +246,7 @@
       "dontRefresh": "安裝中,請勿重新整理此頁面",
       "logs": "記錄",
       "accessLogs": "存取記錄",
+      "autoUpdate": "自動更新",
       "config": "配置",
       "backup": "備份",
       "backupTitle": "備份和恢復",