fix: cross-verify update API claims against npm registry (#1082)
* fix: cross-verify update API claims against npm registry * Update packages/web/server/lib/package-manager.js Signed-off-by: Islam Nofl <islamnofl.official@gmail.com> * fix: show live server version in AboutDialog instead of stale build-time constant * fix: add comment to empty catch block to satisfy lint no-empty rule * fix: preserve live about dialog version in electron * fix: scope update checks by runtime --------- Signed-off-by: Islam Nofl <islamnofl.official@gmail.com> Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
This commit is contained in:
committed by
GitHub
co-authored by
Bohdan Triapitsyn
parent
c924e85a29
commit
a23f5e7545
@@ -24,6 +24,7 @@ import { UsageProgressBar } from '@/components/sections/usage/UsageProgressBar';
|
||||
import { PaceIndicator } from '@/components/sections/usage/PaceIndicator';
|
||||
import { formatPercent, formatWindowLabel, QUOTA_PROVIDERS, calculatePace, calculateExpectedUsagePercent } from '@/lib/quota';
|
||||
import { useQuotaAutoRefresh, useQuotaStore } from '@/stores/useQuotaStore';
|
||||
import { useUpdateStore } from '@/stores/useUpdateStore';
|
||||
import { updateDesktopSettings } from '@/lib/persistence';
|
||||
import { lazyWithChunkRecovery } from '@/lib/chunkLoadRecovery';
|
||||
import type { UsageWindow } from '@/types';
|
||||
@@ -58,6 +59,41 @@ type VSCodeView = 'sessions' | 'chat' | 'settings';
|
||||
export const VSCodeLayout: React.FC = () => {
|
||||
const { t } = useI18n();
|
||||
const runtimeApis = useRuntimeAPIs();
|
||||
const checkForUpdates = useUpdateStore((state) => state.checkForUpdates);
|
||||
|
||||
React.useEffect(() => {
|
||||
const initialDelayMs = 3000;
|
||||
const defaultIntervalMs = 60 * 60 * 1000;
|
||||
const minIntervalMs = 5 * 60 * 1000;
|
||||
const maxIntervalMs = 24 * 60 * 60 * 1000;
|
||||
let disposed = false;
|
||||
let timer: number | null = null;
|
||||
|
||||
const clampIntervalMs = (seconds: number): number => {
|
||||
const ms = Math.round(seconds * 1000);
|
||||
return Math.max(minIntervalMs, Math.min(maxIntervalMs, ms));
|
||||
};
|
||||
|
||||
const scheduleNext = (delayMs: number) => {
|
||||
if (disposed) return;
|
||||
timer = window.setTimeout(async () => {
|
||||
const suggestedSec = await checkForUpdates();
|
||||
const nextDelay = typeof suggestedSec === 'number' && Number.isFinite(suggestedSec)
|
||||
? clampIntervalMs(suggestedSec)
|
||||
: defaultIntervalMs;
|
||||
scheduleNext(nextDelay);
|
||||
}, delayMs);
|
||||
};
|
||||
|
||||
scheduleNext(initialDelayMs);
|
||||
|
||||
return () => {
|
||||
disposed = true;
|
||||
if (timer !== null) {
|
||||
window.clearTimeout(timer);
|
||||
}
|
||||
};
|
||||
}, [checkForUpdates]);
|
||||
|
||||
const viewMode = React.useMemo<'sidebar' | 'editor'>(() => {
|
||||
const configured =
|
||||
|
||||
@@ -9,8 +9,7 @@ import { debugUtils } from '@/lib/debug';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { toast } from '@/components/ui';
|
||||
import { useI18n } from '@/lib/i18n';
|
||||
|
||||
declare const __APP_VERSION__: string | undefined;
|
||||
import { getDesktopAppVersion } from '@/lib/desktopNative';
|
||||
|
||||
interface AboutDialogProps {
|
||||
open: boolean;
|
||||
@@ -60,22 +59,24 @@ export const AboutDialog: React.FC<AboutDialogProps> = ({
|
||||
React.useEffect(() => {
|
||||
if (!open) return;
|
||||
|
||||
const isDesktop = typeof window !== 'undefined' && Boolean((window as unknown as { __TAURI__?: unknown }).__TAURI__);
|
||||
|
||||
if (isDesktop) {
|
||||
const fetchVersion = async () => {
|
||||
try {
|
||||
const { getVersion } = await import('@tauri-apps/api/app');
|
||||
const v = await getVersion();
|
||||
setVersion(v);
|
||||
} catch {
|
||||
setVersion(typeof __APP_VERSION__ !== 'undefined' ? __APP_VERSION__ : null);
|
||||
const fetchVersion = async () => {
|
||||
try {
|
||||
const response = await fetch('/api/system/info');
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
if (typeof data.openchamberVersion === 'string' && data.openchamberVersion.trim()) {
|
||||
setVersion(data.openchamberVersion);
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
fetchVersion();
|
||||
} else {
|
||||
setVersion(typeof __APP_VERSION__ !== 'undefined' ? __APP_VERSION__ : null);
|
||||
}
|
||||
} catch {
|
||||
// Fall back to the native shell version when the web server is unavailable.
|
||||
}
|
||||
|
||||
setVersion(await getDesktopAppVersion());
|
||||
};
|
||||
|
||||
void fetchVersion();
|
||||
}, [open]);
|
||||
|
||||
React.useEffect(() => {
|
||||
|
||||
Reference in New Issue
Block a user