-
-
Notifications
You must be signed in to change notification settings - Fork 611
fix(frontend): add Tauri environment detection and safe API wrappers #432
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
3655c26
3ca94cb
1eddf14
9844f7f
bc1201b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,106 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * Utility functions for Tauri environment detection and fallbacks | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Check if we're running in a Tauri environment | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export const isTauriEnvironment = (): boolean => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return typeof window !== 'undefined' && '__TAURI__' in window; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Safe invoke wrapper that only calls Tauri APIs when available | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export const safeTauriInvoke = async (command: string, args?: any): Promise<any> => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!isTauriEnvironment()) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.warn(`Tauri command "${command}" is not available in browser mode`); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return null; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const { invoke } = await import('@tauri-apps/api/core'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return await invoke(command, args); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } catch (error) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.error(`Error invoking Tauri command "${command}":`, error); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| throw error; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Safe updater check that only works in Tauri environment | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export const safeTauriUpdaterCheck = async (): Promise<any> => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!isTauriEnvironment()) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.warn('Updater is not available in browser mode'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return null; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const { check } = await import('@tauri-apps/plugin-updater'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return await check(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } catch (error) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.error('Error checking for updates:', error); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return null; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Safe dialog open that only works in Tauri environment | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export const safeTauriDialogOpen = async (options: any): Promise<string[] | string | null> => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!isTauriEnvironment()) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.warn('File dialog is not available in browser mode'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // In browser mode, we could potentially use the HTML5 file input as a fallback | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return null; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const { open } = await import('@tauri-apps/plugin-dialog'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return await open(options); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } catch (error) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.error('Error opening dialog:', error); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return null; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Safe convertFileSrc that returns a fallback URL in browser mode | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export const safeTauriConvertFileSrc = (src: string): string => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!isTauriEnvironment()) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // In browser mode, return the src as-is or provide a fallback | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return src; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Dynamic import to avoid errors in browser mode | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const { convertFileSrc } = require('@tauri-apps/api/core'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return convertFileSrc(src); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } catch (error) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.error('Error converting file src:', error); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return src; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Replace require() with dynamic import for consistency The Apply this diff to use dynamic import consistently: - try {
- // Dynamic import to avoid errors in browser mode
- const { convertFileSrc } = require('@tauri-apps/api/core');
- return convertFileSrc(src);
- } catch (error) {
- console.error('Error converting file src:', error);
- return src;
- }
+ try {
+ const { convertFileSrc } = await import('@tauri-apps/api/core');
+ return convertFileSrc(src);
+ } catch (error) {
+ console.error('Error converting file src:', error);
+ return src;
+ }Note: This change requires making the function -export const safeTauriConvertFileSrc = (src: string): string => {
+export const safeTauriConvertFileSrc = async (src: string): Promise<string> => {📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Safe dialog save that only works in Tauri environment | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export const safeTauriDialogSave = async (options: any): Promise<string | null> => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!isTauriEnvironment()) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.warn('Save dialog is not available in browser mode'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return null; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const { save } = await import('@tauri-apps/plugin-dialog'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return await save(options); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } catch (error) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.error('Error opening save dialog:', error); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return null; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Safe file read that only works in Tauri environment | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export const safeTauriReadFile = async (path: string): Promise<Uint8Array | null> => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!isTauriEnvironment()) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.warn('File reading is not available in browser mode'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return null; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const { readFile } = await import('@tauri-apps/plugin-fs'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return await readFile(path); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } catch (error) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.error('Error reading file:', error); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return null; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Inconsistent error handling pattern across safe wrapper functions
The
safeTauriInvokefunction throws errors while other safe wrapper functions (likesafeTauriUpdaterCheck) returnnullon errors. This inconsistency could lead to confusion and different error handling requirements across the codebase.Consider standardizing the error handling approach. For safe wrapper functions, returning
nullon errors (as done in other functions) is more appropriate:📝 Committable suggestion
🤖 Prompt for AI Agents