fix[desktop]: deeplink ui repeat on refresh (#6469)

Signed-off-by: Yelsin Sepulveda <yelsinsepulveda@gmail.com>
Co-authored-by: Zane Staggs <zane@squareup.com>
This commit is contained in:
Yelsin Sepulveda
2026-01-15 10:39:02 -05:00
committed by GitHub
parent 7c3f41e977
commit 5e815e2a3e
2 changed files with 39 additions and 2 deletions
@@ -19,6 +19,13 @@ const mockElectron = {
(window as any).electron = mockElectron;
vi.mock('./ConfigContext', () => ({
useConfig: () => ({
extensionsList: [],
getExtensions: vi.fn().mockResolvedValue([]),
}),
}));
describe('ExtensionInstallModal', () => {
const mockAddExtension = vi.fn();
const mockSetView = vi.fn();
@@ -1,4 +1,4 @@
import { useState, useCallback, useEffect } from 'react';
import { useState, useCallback, useEffect, useRef } from 'react';
import { IpcRendererEvent } from 'electron';
import {
Dialog,
@@ -13,6 +13,8 @@ import { extractExtensionName } from './settings/extensions/utils';
import { addExtensionFromDeepLink } from './settings/extensions/deeplink';
import type { ExtensionConfig } from '../api/types.gen';
import { View, ViewOptions } from '../utils/navigationUtils';
import { useConfig } from './ConfigContext';
import { toastService } from '../toasts';
type ModalType = 'blocked' | 'untrusted' | 'trusted';
@@ -66,6 +68,14 @@ function extractRemoteUrl(link: string): string | null {
}
export function ExtensionInstallModal({ addExtension, setView }: ExtensionInstallModalProps) {
const { getExtensions } = useConfig();
const getExtensionsRef = useRef(getExtensions);
const processingLinkRef = useRef<string | null>(null);
useEffect(() => {
getExtensionsRef.current = getExtensions;
}, [getExtensions]);
const [modalState, setModalState] = useState<ExtensionModalState>({
isOpen: false,
modalType: 'trusted',
@@ -149,12 +159,30 @@ export function ExtensionInstallModal({ addExtension, setView }: ExtensionInstal
};
const handleExtensionRequest = useCallback(async (link: string): Promise<void> => {
if (processingLinkRef.current === link) {
console.log(`Skipping duplicate extension request (already processing): ${link}`);
return;
}
processingLinkRef.current = link;
try {
console.log(`Processing extension request: ${link}`);
const command = extractCommand(link);
const remoteUrl = extractRemoteUrl(link);
const extName = extractExtensionName(link);
const extensionsList = await getExtensionsRef.current(true);
if (extensionsList?.find((ext) => ext.name === extName)) {
console.log(`Extension Already Installed: ${extName}`);
toastService.success({
title: `Extension '${extName}' Already Installed`,
msg: `'${extName}' extension has already been installed successfully. Start a new chat session to use it.`,
});
return;
}
console.log('Extension not found, continuing to show modal');
const extensionInfo: ExtensionInfo = {
name: extName,
@@ -182,6 +210,8 @@ export function ExtensionInstallModal({ addExtension, setView }: ExtensionInstal
...prev,
error: error instanceof Error ? error.message : 'Unknown error',
}));
} finally {
processingLinkRef.current = null;
}
}, []);
@@ -285,7 +315,7 @@ export function ExtensionInstallModal({ addExtension, setView }: ExtensionInstal
<DialogContent className="sm:max-w-[500px]">
<DialogHeader>
<DialogTitle className={getTitleClassName()}>{config.title}</DialogTitle>
<DialogDescription className="whitespace-pre-wrap text-left">
<DialogDescription className="text-left whitespace-pre-wrap">
{config.message}
</DialogDescription>
</DialogHeader>