Load recipe deeplinks in single window when app is closed (#4048)
This commit is contained in:
+90
-39
@@ -184,7 +184,23 @@ const PairRouteWrapper = ({
|
||||
|
||||
// Check if we have a resumed session or recipe config from navigation state
|
||||
useEffect(() => {
|
||||
// Only process if we actually have navigation state
|
||||
const appConfig = window.appConfig?.get('recipe');
|
||||
if (appConfig && !chatRef.current.recipeConfig) {
|
||||
const recipe = appConfig as Recipe;
|
||||
|
||||
const updatedChat: ChatType = {
|
||||
...chatRef.current,
|
||||
recipeConfig: recipe,
|
||||
title: recipe.title || chatRef.current.title,
|
||||
messages: [], // Start fresh for recipe from deeplink
|
||||
messageHistoryIndex: 0,
|
||||
};
|
||||
setChat(updatedChat);
|
||||
setPairChat(updatedChat);
|
||||
return;
|
||||
}
|
||||
|
||||
// Only process navigation state if we actually have it
|
||||
if (!location.state) {
|
||||
console.log('No navigation state, preserving existing chat state');
|
||||
return;
|
||||
@@ -232,8 +248,6 @@ const PairRouteWrapper = ({
|
||||
// Clear the navigation state to prevent reloading on navigation
|
||||
window.history.replaceState({}, document.title);
|
||||
} else if (recipeConfig && !chatRef.current.recipeConfig) {
|
||||
// Only set recipe config if we don't already have one (e.g., from deeplinks)
|
||||
|
||||
const updatedChat: ChatType = {
|
||||
...chatRef.current,
|
||||
recipeConfig: recipeConfig,
|
||||
@@ -824,6 +838,59 @@ export default function App() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for recipe config - this also needs provider initialization
|
||||
if (recipeConfig && typeof recipeConfig === 'object') {
|
||||
console.log('Recipe deeplink detected, initializing system for recipe');
|
||||
|
||||
const initializeForRecipe = async () => {
|
||||
try {
|
||||
await initConfig();
|
||||
await readAllConfig({ throwOnError: true });
|
||||
|
||||
const config = window.electron.getConfig();
|
||||
const provider = (await read('GOOSE_PROVIDER', false)) ?? config.GOOSE_DEFAULT_PROVIDER;
|
||||
const model = (await read('GOOSE_MODEL', false)) ?? config.GOOSE_DEFAULT_MODEL;
|
||||
|
||||
if (provider && model) {
|
||||
await initializeSystem(provider as string, model as string, {
|
||||
getExtensions,
|
||||
addExtension,
|
||||
});
|
||||
|
||||
// Set up the recipe in pair chat after system is initialized
|
||||
setPairChat((prevChat) => ({
|
||||
...prevChat,
|
||||
recipeConfig: recipeConfig as Recipe,
|
||||
title: (recipeConfig as Recipe)?.title || 'Recipe Chat',
|
||||
messages: [], // Start fresh for recipe
|
||||
messageHistoryIndex: 0,
|
||||
}));
|
||||
|
||||
// Navigate to pair view
|
||||
window.location.hash = '#/pair';
|
||||
window.history.replaceState(
|
||||
{
|
||||
recipeConfig: recipeConfig,
|
||||
resetChat: true,
|
||||
},
|
||||
'',
|
||||
'#/pair'
|
||||
);
|
||||
} else {
|
||||
throw new Error('No provider/model configured for recipe');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to initialize system for recipe:', error);
|
||||
setFatalError(
|
||||
`Failed to initialize system for recipe: ${error instanceof Error ? error.message : 'Unknown error'}`
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
initializeForRecipe();
|
||||
return;
|
||||
}
|
||||
|
||||
if (viewType) {
|
||||
if (viewType === 'recipeEditor' && recipeConfig) {
|
||||
// Handle recipe editor deep link - use hash routing
|
||||
@@ -925,40 +992,6 @@ export default function App() {
|
||||
}
|
||||
|
||||
await Promise.all(initPromises);
|
||||
|
||||
const recipeConfig = window.appConfig.get('recipe');
|
||||
if (
|
||||
recipeConfig &&
|
||||
typeof recipeConfig === 'object' &&
|
||||
!window.sessionStorage.getItem('ignoreRecipeConfigChanges')
|
||||
) {
|
||||
console.log(
|
||||
'Recipe deeplink detected, navigating to pair view with config:',
|
||||
recipeConfig
|
||||
);
|
||||
// Set the recipe config in the pair chat state
|
||||
setPairChat((prevChat) => ({
|
||||
...prevChat,
|
||||
recipeConfig: recipeConfig as Recipe,
|
||||
title: (recipeConfig as Recipe).title || 'Recipe Chat',
|
||||
messages: [], // Start fresh for recipe
|
||||
messageHistoryIndex: 0,
|
||||
}));
|
||||
// Navigate to pair view with recipe config using hash routing
|
||||
window.location.hash = '#/pair';
|
||||
window.history.replaceState(
|
||||
{
|
||||
recipeConfig: recipeConfig,
|
||||
resetChat: true,
|
||||
},
|
||||
'',
|
||||
'#/pair'
|
||||
);
|
||||
} else if (window.sessionStorage.getItem('ignoreRecipeConfigChanges')) {
|
||||
console.log(
|
||||
'Ignoring recipe config changes to prevent navigation conflicts with new window creation'
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error in system initialization:', error);
|
||||
if (error instanceof MalformedConfigError) {
|
||||
@@ -1051,9 +1084,25 @@ export default function App() {
|
||||
|
||||
// Handle recipe decode events from main process
|
||||
useEffect(() => {
|
||||
const handleLoadRecipeDeeplink = (_event: IpcRendererEvent, ...args: unknown[]) => {
|
||||
const recipeDeeplink = args[0] as string;
|
||||
const scheduledJobId = args[1] as string | undefined;
|
||||
|
||||
// Store the deeplink info in app config for processing
|
||||
const config = window.electron.getConfig();
|
||||
config.recipeDeeplink = recipeDeeplink;
|
||||
if (scheduledJobId) {
|
||||
config.scheduledJobId = scheduledJobId;
|
||||
}
|
||||
|
||||
// Navigate to pair view to handle the recipe loading
|
||||
if (window.location.hash !== '#/pair') {
|
||||
window.location.hash = '#/pair';
|
||||
}
|
||||
};
|
||||
|
||||
const handleRecipeDecoded = (_event: IpcRendererEvent, ...args: unknown[]) => {
|
||||
const decodedRecipe = args[0] as Recipe;
|
||||
console.log('[App] Recipe decoded successfully:', decodedRecipe);
|
||||
|
||||
// Update the pair chat with the decoded recipe
|
||||
setPairChat((prevChat) => ({
|
||||
@@ -1079,14 +1128,16 @@ export default function App() {
|
||||
window.location.hash = '#/recipes';
|
||||
};
|
||||
|
||||
window.electron.on('load-recipe-deeplink', handleLoadRecipeDeeplink);
|
||||
window.electron.on('recipe-decoded', handleRecipeDecoded);
|
||||
window.electron.on('recipe-decode-error', handleRecipeDecodeError);
|
||||
|
||||
return () => {
|
||||
window.electron.off('load-recipe-deeplink', handleLoadRecipeDeeplink);
|
||||
window.electron.off('recipe-decoded', handleRecipeDecoded);
|
||||
window.electron.off('recipe-decode-error', handleRecipeDecodeError);
|
||||
};
|
||||
}, [setPairChat]);
|
||||
}, [setPairChat, pairChat.id]);
|
||||
|
||||
useEffect(() => {
|
||||
console.log('Setting up keyboard shortcuts');
|
||||
|
||||
Reference in New Issue
Block a user