desktop: disable updates for portable desktop app (#9855)

* desktop: disable updates for portable desktop app

* web: hide setting group if all settings under it are hidden

* web: hide check for updates button on flatpak/snap/portable apps

* desktop: disable auto updates for flatpak/snap/portable apps
This commit is contained in:
Abdullah Atta
2026-05-15 18:59:01 +05:00
committed by GitHub
parent d9d5cb2168
commit ea0550cb05
7 changed files with 41 additions and 18 deletions

View File

@@ -38,7 +38,7 @@ import { dirname } from "path";
import { resolvePath } from "../utils/resolve-path";
import { observable } from "@trpc/server/observable";
import { AssetManager } from "../utils/asset-manager";
import { isFlatpak, isSnap } from "../utils";
import { isFlatpak, isPortable, isSnap } from "../utils";
import { setupDesktopIntegration } from "../utils/desktop-integration";
import { rm } from "fs/promises";
import { disableCustomDns, enableCustomDns } from "../utils/custom-dns";
@@ -60,6 +60,7 @@ const NotificationOptions = z.object({
export const osIntegrationRouter = t.router({
isFlatpak: t.procedure.query(() => isFlatpak()),
isSnap: t.procedure.query(() => isSnap()),
isPortable: t.procedure.query(() => isPortable()),
zoomFactor: t.procedure.query(() => config.zoomFactor),
setZoomFactor: t.procedure.input(z.number()).mutation(({ input: factor }) => {

View File

@@ -24,6 +24,7 @@ import type { AppUpdaterEvents } from "electron-updater/out/AppUpdater";
import { z } from "zod";
import { config } from "../utils/config";
import { app } from "electron";
import { isFlatpak, isPortable, isSnap } from "../utils";
type UpdateInfo = { version: string };
type Progress = { percent: number };
@@ -31,13 +32,15 @@ type Progress = { percent: number };
const t = initTRPC.create();
let cancellationToken: CancellationToken | undefined = undefined;
let downloadTimeout: NodeJS.Timeout | undefined = undefined;
const updatesSupported = !isFlatpak() && !isSnap() && !isPortable();
export const updaterRouter = t.router({
autoUpdates: t.procedure.query(() => config.automaticUpdates),
autoUpdates: t.procedure.query(
() => updatesSupported && config.automaticUpdates
),
releaseTrack: t.procedure.query(() => config.releaseTrack),
install: t.procedure.query(() => autoUpdater.quitAndInstall()),
download: t.procedure.query(async () => {
if (cancellationToken) return;
if (!updatesSupported || cancellationToken) return;
clearTimeout(downloadTimeout);
await new Promise<string[]>((resolve, reject) => {
downloadTimeout = setTimeout(async () => {
@@ -52,7 +55,7 @@ export const updaterRouter = t.router({
});
}),
check: t.procedure.query(async () => {
if (cancellationToken) return;
if (!updatesSupported || cancellationToken) return;
clearTimeout(downloadTimeout);
await new Promise<void>((resolve) => {
downloadTimeout = setTimeout(async () => {

View File

@@ -33,3 +33,7 @@ export function isFlatpak() {
export function isSnap() {
return process.env.SNAP !== undefined;
}
export function isPortable() {
return process.env.PORTABLE_EXECUTABLE_DIR !== undefined;
}

View File

@@ -240,7 +240,8 @@ export const BehaviourSettings: SettingsGroup[] = [
useSettingStore.subscribe((s) => s.autoUpdates, listener),
isHidden: () =>
useSettingStore.getState().isFlatpak ||
useSettingStore.getState().isSnap,
useSettingStore.getState().isSnap ||
useSettingStore.getState().isPortable,
components: [
{
type: "toggle",

View File

@@ -437,7 +437,9 @@ function SettingsGroupComponent(props: { item: SettingsGroup }) {
};
}, [onStateChange]);
if (item.isHidden?.()) return null;
const allHidden = item.settings.every((s) => s.isHidden?.());
if (item.isHidden?.() || allHidden) return null;
return (
<Flex
sx={{

View File

@@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { SettingsGroup } from "./types";
import { SettingComponent, SettingsGroup } from "./types";
import { appVersion } from "../../utils/version";
import { writeText } from "clipboard-polyfill";
import { showToast } from "../../utils/toast";
@@ -50,6 +50,23 @@ export const AboutSettings: SettingsGroup[] = [
useAutoUpdateStore.subscribe((s) => s.status, listener),
components: () => {
const status = useAutoUpdateStore.getState().status;
const copyVersionButton: SettingComponent = {
type: "button",
action: async () => {
await writeText(appVersion.formatted);
showToast("info", strings.copied());
},
title: strings.copy(),
variant: "secondary"
};
if (
useSettingStore.getState().isFlatpak ||
useSettingStore.getState().isSnap ||
useSettingStore.getState().isPortable
) {
return [copyVersionButton];
}
return [
status?.type === "available"
? {
@@ -64,15 +81,7 @@ export const AboutSettings: SettingsGroup[] = [
title: strings.checkForUpdates(),
variant: "secondary"
},
{
type: "button",
action: async () => {
await writeText(appVersion.formatted);
showToast("info", strings.copied());
},
title: strings.copy(),
variant: "secondary"
}
copyVersionButton
];
}
},
@@ -82,7 +91,8 @@ export const AboutSettings: SettingsGroup[] = [
description: strings.releaseTrackDesc(),
isHidden: () =>
useSettingStore.getState().isFlatpak ||
useSettingStore.getState().isSnap,
useSettingStore.getState().isSnap ||
useSettingStore.getState().isPortable,
components: [
{
type: "dropdown",

View File

@@ -90,6 +90,7 @@ class SettingStore extends BaseStore<SettingStore> {
autoUpdates = false;
isFlatpak = false;
isSnap = false;
isPortable = false;
proxyRules?: string;
isInboxEnabled = false;
@@ -104,6 +105,7 @@ class SettingStore extends BaseStore<SettingStore> {
profile: db.settings.getProfile(),
isFlatpak: await desktop?.integration.isFlatpak.query(),
isSnap: await desktop?.integration.isSnap.query(),
isPortable: await desktop?.integration.isPortable.query(),
desktopIntegrationSettings:
await desktop?.integration.desktopIntegration.query(),
privacyMode: await desktop?.integration.privacyMode.query(),