瀏覽代碼

feat(update): allow opting into the dev channel from a stable build

The panel version button opened the GitHub releases page on a stable, up-to-date build, and the dev-channel toggle only rendered on dev builds, so there was no in-panel path from stable to dev. Drop the IsDevBuild() guard in devChannelActive (the toggle alone drives the channel now), always open the update modal instead of releases, and always render the Dev channel switch.
MHSanaei 9 小時之前
父節點
當前提交
8e4c368200

+ 2 - 9
frontend/src/pages/index/IndexPage.tsx

@@ -66,7 +66,6 @@ export default function IndexPage() {
   useEffect(() => { setMessageInstance(messageApi); }, [messageApi]);
 
   const [accessLogEnable, setAccessLogEnable] = useState(false);
-  const [isDevBuild, setIsDevBuild] = useState(false);
   const [devChannelEnable, setDevChannelEnable] = useState(false);
   const [panelUpdateInfo, setPanelUpdateInfo] = useState<PanelUpdateInfo>({
     currentVersion: '',
@@ -90,12 +89,11 @@ export default function IndexPage() {
   const [loadingTip, setLoadingTip] = useState(t('loading'));
 
   useEffect(() => {
-    HttpUtil.post<{ accessLogEnable?: boolean; isDevBuild?: boolean; devChannelEnable?: boolean }>(
+    HttpUtil.post<{ accessLogEnable?: boolean; devChannelEnable?: boolean }>(
       '/panel/api/setting/defaultSettings',
     ).then((msg) => {
       if (msg?.success && msg.obj) {
         setAccessLogEnable(!!msg.obj.accessLogEnable);
-        setIsDevBuild(!!msg.obj.isDevBuild);
         setDevChannelEnable(!!msg.obj.devChannelEnable);
       }
     });
@@ -128,11 +126,7 @@ export default function IndexPage() {
   }, [refresh]);
 
   function openPanelVersion() {
-    if (panelUpdateInfo.updateAvailable || isDevBuild) {
-      setPanelUpdateOpen(true);
-    } else {
-      window.open('https://github.com/MHSanaei/3x-ui/releases', '_blank', 'noopener,noreferrer');
-    }
+    setPanelUpdateOpen(true);
   }
 
   async function handleChannelChange(dev: boolean) {
@@ -463,7 +457,6 @@ export default function IndexPage() {
           <PanelUpdateModal
             open={panelUpdateOpen}
             info={panelUpdateInfo}
-            isDevBuild={isDevBuild}
             devChannelEnable={devChannelEnable}
             onChannelChange={handleChannelChange}
             onClose={() => setPanelUpdateOpen(false)}

+ 9 - 13
frontend/src/pages/index/PanelUpdateModal.tsx

@@ -25,7 +25,6 @@ interface BusyEvent {
 interface PanelUpdateModalProps {
   open: boolean;
   info: PanelUpdateInfo;
-  isDevBuild?: boolean;
   devChannelEnable?: boolean;
   onChannelChange?: (dev: boolean) => void | Promise<void>;
   onClose: () => void;
@@ -35,7 +34,6 @@ interface PanelUpdateModalProps {
 export default function PanelUpdateModal({
   open,
   info,
-  isDevBuild,
   devChannelEnable,
   onChannelChange,
   onClose,
@@ -113,18 +111,16 @@ export default function PanelUpdateModal({
           />
         )}
 
-        {isDevBuild && (
-          <div className="version-list">
-            <div className="version-list-item">
-              <span>{t('pages.index.devChannel')}</span>
-              <Switch
-                checked={!!devChannelEnable}
-                loading={channelBusy}
-                onChange={handleChannel}
-              />
-            </div>
+        <div className="version-list">
+          <div className="version-list-item">
+            <span>{t('pages.index.devChannel')}</span>
+            <Switch
+              checked={!!devChannelEnable}
+              loading={channelBusy}
+              onChange={handleChannel}
+            />
           </div>
-        )}
+        </div>
 
         {devChannelEnable && (
           <Alert

+ 4 - 5
internal/web/service/panel/panel.go

@@ -90,12 +90,11 @@ func (s *PanelService) GetUpdateInfo() (*PanelUpdateInfo, error) {
 }
 
 // devChannelActive reports whether self-update should track the rolling dev
-// release. It requires both the opt-in setting and a dev build, so a stable
-// binary with the toggle left on never cross-grades to the dev channel.
+// release. It is driven solely by the opt-in setting so the panel can
+// cross-grade a stable build onto the dev channel once the user enables it;
+// nothing updates without an explicit user action, so an unattended stable
+// binary with the toggle off stays on the stable channel.
 func devChannelActive() bool {
-	if !config.IsDevBuild() {
-		return false
-	}
 	enabled, err := (&service.SettingService{}).GetDevChannelEnable()
 	return err == nil && enabled
 }