@@ -5,6 +5,7 @@ import { useCallback, useEffect, useState } from "react";
55import { useTranslation } from "react-i18next" ;
66import type { InstalledAppInfo } from "../../store/installedAppsStore" ;
77import { useInstalledAppsStore } from "../../store/installedAppsStore" ;
8+ import { dbCacheManager } from "../../utils/dbCache" ;
89import { DataCube } from "./components/DataCube" ;
910import { SystemTerminal } from "./components/SystemTerminal" ;
1011
@@ -32,11 +33,15 @@ export const Analytics = ({ onBack }: AnalyticsProps) => {
3233 const [ loading , setLoading ] = useState ( true ) ;
3334 const [ selectedApp , setSelectedApp ] = useState < InstalledAppInfo | null > ( null ) ;
3435 const [ permissionFilter , setPermissionFilter ] = useState < string | null > ( null ) ;
36+ const [ loadingPermissions , setLoadingPermissions ] = useState ( false ) ;
3537
36- // Get installed apps from store (permissions are preloaded by useInstalledApps)
38+ // Get installed apps from store
3739 const installedAppsInfo = useInstalledAppsStore (
3840 ( state ) => state . installedAppsInfo ,
3941 ) ;
42+ const setInstalledAppsInfo = useInstalledAppsStore (
43+ ( state ) => state . setInstalledAppsInfo ,
44+ ) ;
4045 const installedRuntimes = useInstalledAppsStore (
4146 ( state ) => state . installedRuntimes ,
4247 ) ;
@@ -54,10 +59,10 @@ export const Analytics = ({ onBack }: AnalyticsProps) => {
5459 const updateCount = Object . keys ( availableUpdates ) . length ;
5560
5661 const data = await invoke < SystemAnalytics > ( "get_system_analytics" , {
57- totalApps : installedAppsInfo . length || undefined ,
58- totalRuntimes : installedRuntimes . size || undefined ,
59- totalExtensions : extensionCount || undefined ,
60- appsWithUpdates : updateCount || undefined ,
62+ totalApps : installedAppsInfo . length ,
63+ totalRuntimes : installedRuntimes . size ,
64+ totalExtensions : extensionCount ,
65+ appsWithUpdates : updateCount ,
6166 } ) ;
6267 setAnalytics ( data ) ;
6368 } catch ( error ) {
@@ -67,9 +72,93 @@ export const Analytics = ({ onBack }: AnalyticsProps) => {
6772 }
6873 } , [ installedAppsInfo . length , installedRuntimes . size , availableUpdates ] ) ;
6974
75+ // Load permissions on-demand when Analytics page opens
76+ const loadPermissions = useCallback ( async ( ) => {
77+ // Check if permissions are already loaded in store
78+ const hasPermissions = installedAppsInfo . some (
79+ ( app ) => app . permissions && app . permissions . length > 0 ,
80+ ) ;
81+
82+ if ( hasPermissions || installedAppsInfo . length === 0 ) {
83+ return ; // Already loaded or no apps
84+ }
85+
86+ try {
87+ setLoadingPermissions ( true ) ;
88+
89+ // Step 1: Try to get cached permissions from SQLite
90+ const cachedPermissions = await dbCacheManager . getCachedPermissionsBatch (
91+ installedAppsInfo . map ( ( app ) => ( {
92+ appId : app . appId ,
93+ version : app . version ,
94+ } ) ) ,
95+ ) ;
96+
97+ // Step 2: Find apps that need permissions fetched
98+ const appsNeedingPermissions = installedAppsInfo . filter (
99+ ( app ) => ! cachedPermissions [ app . appId ] ,
100+ ) ;
101+
102+ let freshPermissions : Record < string , string [ ] > = { } ;
103+
104+ // Step 3: Fetch missing permissions from flatpak
105+ if ( appsNeedingPermissions . length > 0 ) {
106+ const appIds = appsNeedingPermissions . map ( ( app ) => app . appId ) ;
107+ freshPermissions = await invoke < Record < string , string [ ] > > (
108+ "get_app_permissions_batch" ,
109+ { appIds } ,
110+ ) ;
111+
112+ // Step 4: Cache the newly fetched permissions
113+ const permissionsToCache : Record <
114+ string ,
115+ { version : string ; permissions : string [ ] }
116+ > = { } ;
117+ for ( const app of appsNeedingPermissions ) {
118+ if ( freshPermissions [ app . appId ] ) {
119+ permissionsToCache [ app . appId ] = {
120+ version : app . version ,
121+ permissions : freshPermissions [ app . appId ] ,
122+ } ;
123+ }
124+ }
125+ await dbCacheManager . cachePermissionsBatch ( permissionsToCache ) ;
126+ }
127+
128+ // Step 5: Merge cached and fresh permissions
129+ const allPermissions = { ...cachedPermissions , ...freshPermissions } ;
130+
131+ // Step 6: Update apps with permissions
132+ const updatedApps = installedAppsInfo . map ( ( app ) => ( {
133+ ...app ,
134+ permissions : allPermissions [ app . appId ] || [ ] ,
135+ } ) ) ;
136+ setInstalledAppsInfo ( updatedApps ) ;
137+
138+ // Step 7: Clean old versions from cache (keep only current versions)
139+ // This prevents database from growing indefinitely
140+ try {
141+ await dbCacheManager . cleanOldPermissionsBatch (
142+ installedAppsInfo . map ( ( app ) => ( {
143+ appId : app . appId ,
144+ version : app . version ,
145+ } ) ) ,
146+ ) ;
147+ } catch ( error ) {
148+ console . error ( "Error cleaning old permissions:" , error ) ;
149+ }
150+ } catch ( error ) {
151+ console . error ( "Error loading permissions:" , error ) ;
152+ } finally {
153+ setLoadingPermissions ( false ) ;
154+ }
155+ } , [ installedAppsInfo , setInstalledAppsInfo ] ) ;
156+
70157 useEffect ( ( ) => {
71158 loadAnalytics ( ) ;
72- } , [ loadAnalytics ] ) ;
159+ loadPermissions ( ) ;
160+ // eslint-disable-next-line react-hooks/exhaustive-deps
161+ } , [ ] ) ; // Solo ejecutar una vez al montar el componente
73162
74163 return (
75164 < Box
0 commit comments