Skip to content

Fix/510 pages not syncing#512

Merged
felix-schultz merged 2 commits intodevfrom
fix/510-pages-not-syncing
Feb 15, 2026
Merged

Fix/510 pages not syncing#512
felix-schultz merged 2 commits intodevfrom
fix/510-pages-not-syncing

Conversation

@felix-schultz
Copy link
Copy Markdown
Member

This pull request primarily removes several unused React components related to the store feature in the desktop app, and introduces a new error boundary component for improved error handling and reporting. The changes help to clean up the codebase and enhance user experience when errors occur.

Error handling improvements:

  • Added a new error boundary component error.tsx that captures exceptions with Sentry and provides users with options to reload or go back, improving error reporting and user experience.
  • Updated the global error page in global-error.tsx to use a custom-styled error message instead of the default Next.js error component, offering a more consistent and user-friendly appearance.

Codebase cleanup:

  • Removed unused store-related components: AboutSection, StoreHero, StoreInfo (including InfoGrid, MediaGallery, DetailsCard, LinkRow, ExternalLinkRow), StoreRecommendations, and StoreSkeletons. This reduces code bloat and maintenance overhead. [1] [2] [3] [4] [5]

… for better structure

- Updated LoadingScreen component to include dynamic tips and hints during loading.
- Refactored FlowLogo and TipCard components for improved readability and maintainability.
- Introduced useThemeGradient hook for theme management and gradient generation.
- Added size prop to ShareButton for better customization.
- Cleaned up unused code and optimized existing functionality.
@felix-schultz felix-schultz linked an issue Feb 15, 2026 that may be closed by this pull request
@felix-schultz felix-schultz merged commit 0ff1607 into dev Feb 15, 2026
6 of 13 checks passed
@felix-schultz felix-schultz deleted the fix/510-pages-not-syncing branch February 15, 2026 15:06
@gemini-code-assist
Copy link
Copy Markdown

Summary of Changes

Hello @felix-schultz, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request focuses on improving the application's stability, maintainability, and user experience through a significant refactor of core UI components and the introduction of robust error handling. By centralizing store and library functionalities into a shared UI library, the codebase is cleaner and more modular. Additionally, new page synchronization capabilities enhance data consistency, and a redesigned loading screen provides a more engaging user experience.

Highlights

  • Enhanced Error Handling: Introduced a new error boundary component (error.tsx) for both desktop and web applications, integrating Sentry for exception tracking and providing user-friendly reload/go-back options. The global error page (global-error.tsx) was also updated with custom styling for a consistent user experience.
  • Store Feature Refactor & Cleanup: Extensively refactored the store-related components by moving them into the shared @tm9657/flow-like-ui package. This involved removing numerous unused components (AboutSection, StoreHero, StoreInfo, StoreRecommendations, StoreSkeletons, Visibility, useStoreData) from the desktop and web apps, significantly reducing code bloat and improving maintainability.
  • Library Page Modernization: The LibraryPage component for both desktop and web applications was completely rewritten to leverage a new, more modular LibraryPage component from the shared UI library. This update introduces new features like sorting, visibility toggling, and improved search capabilities, along with better mobile responsiveness and drag-and-drop reordering for favorites.
  • Page Synchronization Logic: Implemented new logic within page-state.ts to synchronize page data between local storage and the server, ensuring consistency and data integrity for pages across different environments.
  • UI Component Enhancements: Updated AppCard components to dynamically generate background gradients based on app IDs and theme, and improved the LoadingScreen with a new visual design and dynamic tips.
Changelog
  • apps/desktop/app/error.tsx
    • Added a new error boundary component with Sentry integration and user recovery options.
  • apps/desktop/app/global-error.tsx
    • Removed NextError import.
    • Implemented a custom-styled error message with reload and go-back buttons.
  • apps/desktop/app/library/page.tsx
    • Removed numerous local state variables and UI components related to app display, search, and sorting.
    • Replaced local library logic with the LibraryPage component from @tm9657/flow-like-ui.
    • Updated isMobileDevice detection logic.
    • Simplified normalizePickerPath function.
    • Removed apps.refetch() call from importApp and onImported callbacks, now handled by the new LibraryPage component.
  • apps/desktop/app/store/components/AboutSection.tsx
    • Removed the file.
  • apps/desktop/app/store/components/StoreHero.tsx
    • Removed the file.
  • apps/desktop/app/store/components/StoreInfo.tsx
    • Removed the file.
  • apps/desktop/app/store/components/StoreRecommendations.tsx
    • Removed the file.
  • apps/desktop/app/store/components/StoreSkeletons.tsx
    • Removed the file.
  • apps/desktop/app/store/explore/apps/page.tsx
    • Replaced extensive local UI and logic with the ExploreAppsPage component from @tm9657/flow-like-ui.
  • apps/desktop/app/store/packages/page.tsx
    • Replaced extensive local UI and logic with the PackagesStorePage component from @tm9657/flow-like-ui.
  • apps/desktop/app/store/page.tsx
    • Updated imports to use AboutSection, HeroSkeleton, StoreEmptyState, StoreHero, StoreRecommendations, and useStoreData from @tm9657/flow-like-ui.
    • Passed EVENT_CONFIG to useStoreData.
    • Added hasThumbnail prop to StoreHero.
    • Simplified error handling for id not found.
    • Refactored the main return structure to use the new StoreHero and AboutSection components directly.
  • apps/desktop/components/tauri-provider/page-state.ts
    • Added pushPageToServer and fetchRemotePage private methods for server synchronization.
    • Implemented logic in getPage to fetch remote page data and merge if newer than local.
    • Added server synchronization calls to createPage, updatePage, and deletePage.
  • apps/web/app/error.tsx
    • Added a new error boundary component with Sentry integration and user recovery options.
  • apps/web/app/global-error.tsx
    • Removed NextError import.
    • Implemented a custom-styled error message with reload and go-back buttons.
  • apps/web/app/library/page.tsx
    • Replaced extensive local UI and logic with the LibraryPage component from @tm9657/flow-like-ui.
  • apps/web/app/store/components/AboutSection.tsx
    • Removed the file.
  • apps/web/app/store/components/StoreHero.tsx
    • Removed the file.
  • apps/web/app/store/components/StoreInfo.tsx
    • Removed the file.
  • apps/web/app/store/components/StoreRecommendations.tsx
    • Removed the file.
  • apps/web/app/store/components/StoreSkeletons.tsx
    • Removed the file.
  • apps/web/app/store/components/Visibility.tsx
    • Removed the file.
  • apps/web/app/store/components/useStoreData.ts
    • Removed the file (renamed and moved to packages/ui).
  • apps/web/app/store/explore/apps/page.tsx
    • Replaced extensive local UI and logic with the ExploreAppsPage component from @tm9657/flow-like-ui.
  • apps/web/app/store/packages/page.tsx
    • Replaced extensive local UI and logic with the PackagesStorePage component from @tm9657/flow-like-ui.
  • apps/web/app/store/page.tsx
    • Updated imports to use AboutSection, HeroSkeleton, StoreEmptyState, StoreHero, StoreRecommendations, and useStoreData from @tm9657/flow-like-ui.
    • Passed EVENT_CONFIG to useStoreData.
    • Added hasThumbnail prop to StoreHero.
    • Simplified error handling for id not found.
    • Refactored the main return structure to use the new StoreHero and AboutSection components directly.
  • apps/web/package.json
    • Added @dnd-kit/sortable and @dnd-kit/utilities dependencies.
  • packages/ui/components/index.ts
    • Exported new components from the library and store directories.
  • packages/ui/components/library/index.ts
    • Added new exports for LibraryPage, FavoritesSection, JoinInline, JoinInlineExpanded, LibrarySkeleton, PinnedHero, SearchResults, Section, SortableFavoriteCard, CARD_MIN_W_DESKTOP, CARD_MIN_W_MOBILE, CATEGORY_COLORS, COLLAPSED_ROWS, sortItems, LibraryItem, SortMode, and useGridColumns.
  • packages/ui/components/library/library-page.tsx
    • Added a new LibraryPage component, centralizing library UI and logic.
  • packages/ui/components/library/library-sub-components.tsx
    • Added new components: SortableFavoriteCard, Section, FavoritesSection, PinnedHero, SearchResults, JoinInline, JoinInlineExpanded, and LibrarySkeleton.
  • packages/ui/components/library/library-types.ts
    • Added new types: LibraryItem, SortMode, and constants COLLAPSED_ROWS, CARD_MIN_W_DESKTOP, CARD_MIN_W_MOBILE, CATEGORY_COLORS, and sortItems function.
  • packages/ui/components/library/use-grid-columns.ts
    • Added a new useGridColumns hook for responsive grid layouts.
  • packages/ui/components/pages/store/store-package-detail.tsx
    • Exported GenericFetcher type.
  • packages/ui/components/store/about-section.tsx
    • Added a new AboutSection component for app details.
  • packages/ui/components/store/explore-apps-page.tsx
    • Added a new ExploreAppsPage component, centralizing app exploration UI and logic.
  • packages/ui/components/store/index.ts
    • Exported new store-related components and hooks: StoreHero, AboutSection, StoreRecommendations, StoreEmptyState, HeroSkeleton, visibilityLabel, visibilityIcon, useStoreData, ExploreAppsPage, and PackagesStorePage.
  • packages/ui/components/store/packages-store-page.tsx
    • Added a new PackagesStorePage component, centralizing package store UI and logic.
  • packages/ui/components/store/store-hero.tsx
    • Added a new StoreHero component for displaying app hero sections.
  • packages/ui/components/store/store-recommendations.tsx
    • Added a new StoreRecommendations component for displaying recommended apps.
  • packages/ui/components/store/store-skeletons.tsx
    • Added new skeleton components: StoreEmptyState and HeroSkeleton.
  • packages/ui/components/store/use-store-data.ts
    • Renamed from apps/desktop/app/store/components/useStoreData.ts.
    • Modified openCheckoutUrl to handle both Tauri and web environments.
    • Updated useStoreData to accept eventConfig as a prop.
    • Added hasThumbnail to the returned object.
  • packages/ui/components/store/visibility.tsx
    • Renamed from apps/desktop/app/store/components/Visibility.tsx and apps/web/app/store/components/Visibility.tsx.
    • Updated import path for IAppVisibility.
  • packages/ui/components/ui/app-card.tsx
    • Imported cn and useThemeInfo, hashToGradient.
    • Updated SmallAppCard and ExtendedAppCard to use cn for class names.
    • Implemented dynamic background gradients for AppCard when no thumbnail is available.
  • packages/ui/components/ui/loading-screen.tsx
    • Refactored LoadingScreen to use a new FlowLogo component and TipCard for dynamic tips/hints.
    • Removed previous complex canvas animations and replaced them with simpler CSS animations and static elements.
  • packages/ui/components/ui/share-button.tsx
    • Added size prop to ShareButtonProps and passed it to the Button component.
  • packages/ui/hooks/index.ts
    • Exported useMobile and useThemeGradient hooks.
  • packages/ui/hooks/use-theme-gradient.ts
    • Added a new useThemeInfo hook to read theme properties (primary hue, dark mode) from CSS variables.
    • Added hashToGradient function to generate consistent gradients based on an ID and theme info.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request is a significant and valuable refactoring. It successfully cleans up the codebase by moving shared UI components and logic for the store and library pages into the @tm9657/flow-like-ui package. The introduction of new error boundary components and the redesign of the library and store pages are great improvements for both maintainability and user experience.
My review includes a few suggestions to enhance data synchronization logic and improve code maintainability in the new error pages. Specifically, I've pointed out a missing data refetch after importing an app and an opportunity to make the page synchronization logic more robust. I've also commented on the use of inline styles in the global error handlers.

Comment on lines +76 to +92
const importApp = useCallback(async (path: string) => {
if (path.toLowerCase().endsWith(".enc.flow-app")) {
setEncryptedImportPath(path);
setImportDialogOpen(true);
return;
}
const toastId = toast.loading("Importing app...", {
description: "Please wait.",
});
try {
await invoke("import_app_from_file", { path });
toast.success("App imported successfully!", { id: toastId });
} catch (err) {
console.error(err);
toast.error("Failed to import app", { id: toastId });
}
}, []);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

After a successful app import, the list of apps in the library is not being updated. The previous implementation called apps.refetch(), but the new version is missing a mechanism to refresh the app list. This will lead to a stale UI until the user manually refreshes or navigates away and back.

You should invalidate the queries to trigger a refetch and update the UI. Since queryClient is already available in the component, you can use it to invalidate all queries.

Suggested change
const importApp = useCallback(async (path: string) => {
if (path.toLowerCase().endsWith(".enc.flow-app")) {
setEncryptedImportPath(path);
setImportDialogOpen(true);
return;
}
const toastId = toast.loading("Importing app...", {
description: "Please wait.",
});
try {
await invoke("import_app_from_file", { path });
toast.success("App imported successfully!", { id: toastId });
} catch (err) {
console.error(err);
toast.error("Failed to import app", { id: toastId });
}
}, []);
const importApp = useCallback(async (path: string) => {
if (path.toLowerCase().endsWith(".enc.flow-app")) {
setEncryptedImportPath(path);
setImportDialogOpen(true);
return;
}
const toastId = toast.loading("Importing app...", {
description: "Please wait.",
});
try {
await invoke("import_app_from_file", { path });
toast.success("App imported successfully!", { id: toastId });
queryClient.invalidateQueries();
} catch (err) {
console.error(err);
toast.error("Failed to import app", { id: toastId });
}
}, [queryClient]);

Comment on lines +71 to +74
if (remoteUpdated > localUpdated) {
const merged = { ...remotePage, boardId: remotePage.boardId || localPage.boardId };
await invoke("update_page", { appId, page: merged });
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The background sync logic in getPage only handles synchronizing from remote to local when the remote page is newer. It doesn't handle the case where the local page is newer than the remote one (e.g., after an offline edit). This can lead to data loss or stale data on the server.

To ensure data consistency, you should also push local changes to the server if the local version is more recent.

			if (remoteUpdated > localUpdated) {
				const merged = { ...remotePage, boardId: remotePage.boardId || localPage.boardId };
				await invoke("update_page", { appId, page: merged });
			} else if (localUpdated > remoteUpdated) {
				await this.pushPageToServer(appId, localPage);
			}

Comment on lines +18 to +70
<div
style={{
display: "flex",
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
minHeight: "100vh",
gap: "24px",
padding: "24px",
fontFamily: "system-ui, sans-serif",
background: "#0a0a0a",
color: "#fafafa",
}}
>
<h2 style={{ fontSize: "1.5rem", fontWeight: 600 }}>
Something went wrong
</h2>
<p style={{ fontSize: "0.875rem", color: "#a1a1aa" }}>
An unexpected error occurred.
</p>
<div style={{ display: "flex", gap: "12px" }}>
<button
type="button"
onClick={() => window.history.back()}
style={{
padding: "8px 16px",
fontSize: "0.875rem",
borderRadius: "6px",
border: "1px solid #27272a",
background: "transparent",
color: "#fafafa",
cursor: "pointer",
}}
>
Go Back
</button>
<button
type="button"
onClick={() => window.location.reload()}
style={{
padding: "8px 16px",
fontSize: "0.875rem",
borderRadius: "6px",
border: "none",
background: "#fafafa",
color: "#0a0a0a",
cursor: "pointer",
}}
>
Reload
</button>
</div>
</div>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The error page uses inline styles with hardcoded color values (e.g., #0a0a0a, #fafafa). This can lead to inconsistencies if the application's theme changes and makes maintenance harder.

While global-error.tsx has limitations and using theme providers might not be safe, it would be better to define these colors as constants at the top of the file, or ideally use CSS variables if they are available at this stage. This would improve maintainability and consistency.

Comment on lines +18 to +70
<div
style={{
display: "flex",
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
minHeight: "100vh",
gap: "24px",
padding: "24px",
fontFamily: "system-ui, sans-serif",
background: "#0a0a0a",
color: "#fafafa",
}}
>
<h2 style={{ fontSize: "1.5rem", fontWeight: 600 }}>
Something went wrong
</h2>
<p style={{ fontSize: "0.875rem", color: "#a1a1aa" }}>
An unexpected error occurred.
</p>
<div style={{ display: "flex", gap: "12px" }}>
<button
type="button"
onClick={() => window.history.back()}
style={{
padding: "8px 16px",
fontSize: "0.875rem",
borderRadius: "6px",
border: "1px solid #27272a",
background: "transparent",
color: "#fafafa",
cursor: "pointer",
}}
>
Go Back
</button>
<button
type="button"
onClick={() => window.location.reload()}
style={{
padding: "8px 16px",
fontSize: "0.875rem",
borderRadius: "6px",
border: "none",
background: "#fafafa",
color: "#0a0a0a",
cursor: "pointer",
}}
>
Reload
</button>
</div>
</div>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The error page uses inline styles with hardcoded color values (e.g., #0a0a0a, #fafafa). This can lead to inconsistencies if the application's theme changes and makes maintenance harder.

While global-error.tsx has limitations and using theme providers might not be safe, it would be better to define these colors as constants at the top of the file, or ideally use CSS variables if they are available at this stage. This would improve maintainability and consistency.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Pages not syncing

1 participant