implementing favorite apps feature (#1410)

This PR implements favorite apps feature and addresses issue #827 
    
<!-- This is an auto-generated description by cubic. -->
---

## Summary by cubic
Adds a favorite apps feature with a star toggle in the sidebar.
Favorites are grouped separately and persisted, with optimistic UI
updates and e2e tests.

- **New Features**
- Added isFavorite to the apps schema and an IPC handler
(add-to-favorite) to toggle and persist the state.
  - Updated AppList to show “Favorite apps” and “Other apps” sections.
- Introduced AppItem component with a star button; uses
useAddAppToFavorite for optimistic updates and toasts.
  - Added Playwright tests to verify favoriting and unfavoriting.

- **Migration**
- Run DB migrations to add the apps.is_favorite column (defaults to 0).

<!-- End of auto-generated description by cubic. -->
This commit is contained in:
Mohamed Aziz Mejri
2025-10-06 20:44:18 +01:00
committed by GitHub
parent e8b93e3298
commit 423a95ed81
12 changed files with 1030 additions and 25 deletions

View File

@@ -1075,6 +1075,53 @@ export function registerAppHandlers() {
},
);
ipcMain.handle(
"add-to-favorite",
async (
_,
{ appId }: { appId: number },
): Promise<{ isFavorite: boolean }> => {
return withLock(appId, async () => {
try {
// Fetch the current isFavorite value
const result = await db
.select({ isFavorite: apps.isFavorite })
.from(apps)
.where(eq(apps.id, appId))
.limit(1);
if (result.length === 0) {
throw new Error(`App with ID ${appId} not found.`);
}
const currentIsFavorite = result[0].isFavorite;
// Toggle the isFavorite value
const updated = await db
.update(apps)
.set({ isFavorite: !currentIsFavorite })
.where(eq(apps.id, appId))
.returning({ isFavorite: apps.isFavorite });
if (updated.length === 0) {
throw new Error(
`Failed to update favorite status for app ID ${appId}.`,
);
}
// Return the updated isFavorite value
return { isFavorite: updated[0].isFavorite };
} catch (error: any) {
logger.error(
`Error in add-to-favorite handler for app ID ${appId}:`,
error,
);
throw new Error(`Failed to toggle favorite status: ${error.message}`);
}
});
},
);
ipcMain.handle(
"rename-app",
async (