appclean 1.8.0 โ†’ 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (211) hide show
  1. package/GUI_IMPLEMENTATION_STATUS.md +143 -0
  2. package/MD_Files/INDEX.md +51 -0
  3. package/MD_Files/PUBLICATION_SUCCESS_REPORT.md +227 -0
  4. package/PHASE2_COMPLETION.md +281 -0
  5. package/PHASE3_COMPLETION.md +364 -0
  6. package/README.md +446 -376
  7. package/assets/logo.svg +34 -0
  8. package/dist/core/appUpdateChecker.js +12 -16
  9. package/dist/core/appUpdateChecker.js.map +1 -1
  10. package/dist/core/detector.js +14 -18
  11. package/dist/core/detector.js.map +1 -1
  12. package/dist/core/duplicateFileFinder.js +12 -19
  13. package/dist/core/duplicateFileFinder.js.map +1 -1
  14. package/dist/core/orphanedDependencyDetector.js +19 -26
  15. package/dist/core/orphanedDependencyDetector.js.map +1 -1
  16. package/dist/core/performanceOptimizer.js +6 -10
  17. package/dist/core/performanceOptimizer.js.map +1 -1
  18. package/dist/core/permissionHandler.js +21 -25
  19. package/dist/core/permissionHandler.js.map +1 -1
  20. package/dist/core/pluginSystem.js +9 -13
  21. package/dist/core/pluginSystem.js.map +1 -1
  22. package/dist/core/removalRecorder.js +12 -19
  23. package/dist/core/removalRecorder.js.map +1 -1
  24. package/dist/core/remover.js +59 -66
  25. package/dist/core/remover.js.map +1 -1
  26. package/dist/core/reportGenerator.d.ts +1 -1
  27. package/dist/core/reportGenerator.d.ts.map +1 -1
  28. package/dist/core/reportGenerator.js +27 -34
  29. package/dist/core/reportGenerator.js.map +1 -1
  30. package/dist/core/scheduledCleanup.js +23 -30
  31. package/dist/core/scheduledCleanup.js.map +1 -1
  32. package/dist/core/serviceFileDetector.js +24 -31
  33. package/dist/core/serviceFileDetector.js.map +1 -1
  34. package/dist/core/verificationModule.js +10 -14
  35. package/dist/core/verificationModule.js.map +1 -1
  36. package/dist/index.js +190 -90
  37. package/dist/index.js.map +1 -1
  38. package/dist/managers/brewManager.d.ts.map +1 -1
  39. package/dist/managers/brewManager.js +35 -41
  40. package/dist/managers/brewManager.js.map +1 -1
  41. package/dist/managers/customManager.d.ts +2 -1
  42. package/dist/managers/customManager.d.ts.map +1 -1
  43. package/dist/managers/customManager.js +79 -53
  44. package/dist/managers/customManager.js.map +1 -1
  45. package/dist/managers/linuxManager.js +29 -36
  46. package/dist/managers/linuxManager.js.map +1 -1
  47. package/dist/managers/npmManager.js +27 -34
  48. package/dist/managers/npmManager.js.map +1 -1
  49. package/dist/types/index.js +1 -2
  50. package/dist/ui/client/api/client.d.ts +24 -0
  51. package/dist/ui/client/api/client.d.ts.map +1 -0
  52. package/dist/ui/client/api/client.js +96 -0
  53. package/dist/ui/client/api/client.js.map +1 -0
  54. package/dist/ui/client/app.d.ts +7 -0
  55. package/dist/ui/client/app.d.ts.map +1 -0
  56. package/dist/ui/client/app.js +71 -0
  57. package/dist/ui/client/app.js.map +1 -0
  58. package/dist/ui/client/index.html +107 -0
  59. package/dist/ui/client/pages/appDetails.d.ts +8 -0
  60. package/dist/ui/client/pages/appDetails.d.ts.map +1 -0
  61. package/dist/ui/client/pages/appDetails.js +287 -0
  62. package/dist/ui/client/pages/appDetails.js.map +1 -0
  63. package/dist/ui/client/pages/appSearch.d.ts +2 -0
  64. package/dist/ui/client/pages/appSearch.d.ts.map +1 -0
  65. package/dist/ui/client/pages/appSearch.js +210 -0
  66. package/dist/ui/client/pages/appSearch.js.map +1 -0
  67. package/dist/ui/client/pages/dashboard.d.ts +2 -0
  68. package/dist/ui/client/pages/dashboard.d.ts.map +1 -0
  69. package/dist/ui/client/pages/dashboard.js +154 -0
  70. package/dist/ui/client/pages/dashboard.js.map +1 -0
  71. package/dist/ui/client/pages/settings.d.ts +7 -0
  72. package/dist/ui/client/pages/settings.d.ts.map +1 -0
  73. package/dist/ui/client/pages/settings.js +279 -0
  74. package/dist/ui/client/pages/settings.js.map +1 -0
  75. package/dist/ui/client/state/appStore.d.ts +38 -0
  76. package/dist/ui/client/state/appStore.d.ts.map +1 -0
  77. package/dist/ui/client/state/appStore.js +121 -0
  78. package/dist/ui/client/state/appStore.js.map +1 -0
  79. package/dist/ui/client/state/dashboardStore.d.ts +31 -0
  80. package/dist/ui/client/state/dashboardStore.d.ts.map +1 -0
  81. package/dist/ui/client/state/dashboardStore.js +70 -0
  82. package/dist/ui/client/state/dashboardStore.js.map +1 -0
  83. package/dist/ui/client/state/uiStore.d.ts +43 -0
  84. package/dist/ui/client/state/uiStore.d.ts.map +1 -0
  85. package/dist/ui/client/state/uiStore.js +109 -0
  86. package/dist/ui/client/state/uiStore.js.map +1 -0
  87. package/dist/ui/client/styles/animations.css +327 -0
  88. package/dist/ui/client/styles/base.css +214 -0
  89. package/dist/ui/client/styles/components.css +400 -0
  90. package/dist/ui/client/styles/layout.css +224 -0
  91. package/dist/ui/client/styles/variables.css +140 -0
  92. package/dist/ui/client/utils/events.d.ts +19 -0
  93. package/dist/ui/client/utils/events.d.ts.map +1 -0
  94. package/dist/ui/client/utils/events.js +54 -0
  95. package/dist/ui/client/utils/events.js.map +1 -0
  96. package/dist/ui/client/utils/formatting.d.ts +11 -0
  97. package/dist/ui/client/utils/formatting.d.ts.map +1 -0
  98. package/dist/ui/client/utils/formatting.js +104 -0
  99. package/dist/ui/client/utils/formatting.js.map +1 -0
  100. package/dist/ui/client/utils/router.d.ts +25 -0
  101. package/dist/ui/client/utils/router.d.ts.map +1 -0
  102. package/dist/ui/client/utils/router.js +90 -0
  103. package/dist/ui/client/utils/router.js.map +1 -0
  104. package/dist/ui/guiServer.d.ts +8 -1
  105. package/dist/ui/guiServer.d.ts.map +1 -1
  106. package/dist/ui/guiServer.js +148 -110
  107. package/dist/ui/guiServer.js.map +1 -1
  108. package/dist/ui/menu.js +18 -27
  109. package/dist/ui/menu.js.map +1 -1
  110. package/dist/ui/prompts.js +34 -47
  111. package/dist/ui/prompts.js.map +1 -1
  112. package/dist/ui/server/middleware/errorHandler.d.ts +19 -0
  113. package/dist/ui/server/middleware/errorHandler.d.ts.map +1 -0
  114. package/dist/ui/server/middleware/errorHandler.js +100 -0
  115. package/dist/ui/server/middleware/errorHandler.js.map +1 -0
  116. package/dist/ui/server/routes/apps.d.ts +8 -0
  117. package/dist/ui/server/routes/apps.d.ts.map +1 -0
  118. package/dist/ui/server/routes/apps.js +74 -0
  119. package/dist/ui/server/routes/apps.js.map +1 -0
  120. package/dist/ui/server/routes/dashboard.d.ts +4 -0
  121. package/dist/ui/server/routes/dashboard.d.ts.map +1 -0
  122. package/dist/ui/server/routes/dashboard.js +57 -0
  123. package/dist/ui/server/routes/dashboard.js.map +1 -0
  124. package/dist/ui/server/routes/settings.d.ts +6 -0
  125. package/dist/ui/server/routes/settings.d.ts.map +1 -0
  126. package/dist/ui/server/routes/settings.js +31 -0
  127. package/dist/ui/server/routes/settings.js.map +1 -0
  128. package/dist/ui/server/services/appService.d.ts +45 -0
  129. package/dist/ui/server/services/appService.d.ts.map +1 -0
  130. package/dist/ui/server/services/appService.js +114 -0
  131. package/dist/ui/server/services/appService.js.map +1 -0
  132. package/dist/ui/server/services/removalService.d.ts +24 -0
  133. package/dist/ui/server/services/removalService.d.ts.map +1 -0
  134. package/dist/ui/server/services/removalService.js +83 -0
  135. package/dist/ui/server/services/removalService.js.map +1 -0
  136. package/dist/utils/filesystem.js +32 -49
  137. package/dist/utils/filesystem.js.map +1 -1
  138. package/dist/utils/logger.js +9 -18
  139. package/dist/utils/logger.js.map +1 -1
  140. package/dist/utils/platform.js +10 -22
  141. package/dist/utils/platform.js.map +1 -1
  142. package/dist/utils/upgrade.d.ts +22 -0
  143. package/dist/utils/upgrade.d.ts.map +1 -0
  144. package/dist/utils/upgrade.js +94 -0
  145. package/dist/utils/upgrade.js.map +1 -0
  146. package/package.json +4 -2
  147. package/src/core/appUpdateChecker.ts +1 -1
  148. package/src/core/detector.ts +6 -6
  149. package/src/core/duplicateFileFinder.ts +1 -1
  150. package/src/core/orphanedDependencyDetector.ts +2 -2
  151. package/src/core/performanceOptimizer.ts +1 -1
  152. package/src/core/permissionHandler.ts +2 -2
  153. package/src/core/pluginSystem.ts +1 -1
  154. package/src/core/removalRecorder.ts +2 -2
  155. package/src/core/remover.ts +11 -11
  156. package/src/core/reportGenerator.ts +2 -2
  157. package/src/core/scheduledCleanup.ts +2 -2
  158. package/src/core/serviceFileDetector.ts +2 -2
  159. package/src/core/verificationModule.ts +2 -2
  160. package/src/index.ts +133 -6
  161. package/src/managers/brewManager.ts +11 -9
  162. package/src/managers/customManager.ts +71 -30
  163. package/src/managers/linuxManager.ts +3 -3
  164. package/src/managers/npmManager.ts +3 -3
  165. package/src/ui/client/api/client.ts +163 -0
  166. package/src/ui/client/app.ts +121 -0
  167. package/src/ui/client/index.html +107 -0
  168. package/src/ui/client/pages/appDetails.ts +356 -0
  169. package/src/ui/client/pages/appSearch.ts +270 -0
  170. package/src/ui/client/pages/dashboard.ts +189 -0
  171. package/src/ui/client/pages/settings.ts +342 -0
  172. package/src/ui/client/state/appStore.ts +169 -0
  173. package/src/ui/client/state/dashboardStore.ts +113 -0
  174. package/src/ui/client/state/uiStore.ts +166 -0
  175. package/src/ui/client/styles/animations.css +327 -0
  176. package/src/ui/client/styles/base.css +214 -0
  177. package/src/ui/client/styles/components.css +400 -0
  178. package/src/ui/client/styles/layout.css +224 -0
  179. package/src/ui/client/styles/variables.css +140 -0
  180. package/src/ui/client/utils/events.ts +74 -0
  181. package/src/ui/client/utils/formatting.ts +157 -0
  182. package/src/ui/client/utils/router.ts +161 -0
  183. package/src/ui/guiServer.ts +206 -105
  184. package/src/ui/prompts.ts +1 -1
  185. package/src/ui/server/middleware/errorHandler.ts +174 -0
  186. package/src/ui/server/routes/apps.ts +132 -0
  187. package/src/ui/server/routes/dashboard.ts +93 -0
  188. package/src/ui/server/routes/settings.ts +63 -0
  189. package/src/ui/server/services/appService.ts +184 -0
  190. package/src/ui/server/services/removalService.ts +138 -0
  191. package/src/utils/upgrade.ts +143 -0
  192. package/tsconfig.json +3 -2
  193. package/INDEX.md +0 -165
  194. /package/{ACTION_CHECKLIST.md โ†’ MD_Files/ACTION_CHECKLIST.md} +0 -0
  195. /package/{APPCLEAN_SUMMARY.md โ†’ MD_Files/APPCLEAN_SUMMARY.md} +0 -0
  196. /package/{CHANGELOG.md โ†’ MD_Files/CHANGELOG.md} +0 -0
  197. /package/{CODE_OF_CONDUCT.md โ†’ MD_Files/CODE_OF_CONDUCT.md} +0 -0
  198. /package/{CODE_REVIEW_REPORT.md โ†’ MD_Files/CODE_REVIEW_REPORT.md} +0 -0
  199. /package/{COMMUNITY_POSTS.md โ†’ MD_Files/COMMUNITY_POSTS.md} +0 -0
  200. /package/{DEPLOYMENT_GUIDE.md โ†’ MD_Files/DEPLOYMENT_GUIDE.md} +0 -0
  201. /package/{DEPLOYMENT_STATUS.md โ†’ MD_Files/DEPLOYMENT_STATUS.md} +0 -0
  202. /package/{EXECUTIVE_REPORT.md โ†’ MD_Files/EXECUTIVE_REPORT.md} +0 -0
  203. /package/{GITHUB_OPTIMIZATION.md โ†’ MD_Files/GITHUB_OPTIMIZATION.md} +0 -0
  204. /package/{MARKETING_SUMMARY.md โ†’ MD_Files/MARKETING_SUMMARY.md} +0 -0
  205. /package/{NPM_PACKAGE_OPTIMIZATION.md โ†’ MD_Files/NPM_PACKAGE_OPTIMIZATION.md} +0 -0
  206. /package/{NPM_PUBLISH.md โ†’ MD_Files/NPM_PUBLISH.md} +0 -0
  207. /package/{PROJECT_SUMMARY.txt โ†’ MD_Files/PROJECT_SUMMARY.txt} +0 -0
  208. /package/{QUICKSTART.md โ†’ MD_Files/QUICKSTART.md} +0 -0
  209. /package/{SETUP_GITHUB.md โ†’ MD_Files/SETUP_GITHUB.md} +0 -0
  210. /package/{TESTING_SUMMARY.md โ†’ MD_Files/TESTING_SUMMARY.md} +0 -0
  211. /package/{setup-github.sh โ†’ MD_Files/setup-github.sh} +0 -0
@@ -1,9 +1,9 @@
1
1
  import { execSync } from 'child_process';
2
2
  import path from 'path';
3
- import { getHomeDir } from '../utils/platform';
4
- import { pathExists, listDirectory, readFile } from '../utils/filesystem';
3
+ import { getHomeDir } from '../utils/platform.js';
4
+ import { pathExists, listDirectory, readFile } from '../utils/filesystem.js';
5
5
  import { InstalledApp, ArtifactPath } from '../types';
6
- import { Logger } from '../utils/logger';
6
+ import { Logger } from '../utils/logger.js';
7
7
 
8
8
  export class NpmManager {
9
9
  private globalNpmPath: string;
@@ -0,0 +1,163 @@
1
+ /**
2
+ * API Client - Wrapper for HTTP requests to AppClean server
3
+ */
4
+
5
+ export interface ApiResponse<T> {
6
+ success: boolean;
7
+ data?: T;
8
+ error?: string;
9
+ message?: string;
10
+ }
11
+
12
+ export class ApiClient {
13
+ private baseUrl = '';
14
+ private timeout = 30000; // 30 seconds
15
+
16
+ /**
17
+ * Make a GET request
18
+ */
19
+ async get<T = any>(endpoint: string, options?: RequestInit): Promise<T> {
20
+ return this.request<T>(endpoint, { ...options, method: 'GET' });
21
+ }
22
+
23
+ /**
24
+ * Make a POST request
25
+ */
26
+ async post<T = any>(
27
+ endpoint: string,
28
+ body?: any,
29
+ options?: RequestInit
30
+ ): Promise<T> {
31
+ return this.request<T>(endpoint, {
32
+ ...options,
33
+ method: 'POST',
34
+ headers: {
35
+ 'Content-Type': 'application/json',
36
+ ...options?.headers,
37
+ },
38
+ body: body ? JSON.stringify(body) : undefined,
39
+ });
40
+ }
41
+
42
+ /**
43
+ * Make a PUT request
44
+ */
45
+ async put<T = any>(
46
+ endpoint: string,
47
+ body?: any,
48
+ options?: RequestInit
49
+ ): Promise<T> {
50
+ return this.request<T>(endpoint, {
51
+ ...options,
52
+ method: 'PUT',
53
+ headers: {
54
+ 'Content-Type': 'application/json',
55
+ ...options?.headers,
56
+ },
57
+ body: body ? JSON.stringify(body) : undefined,
58
+ });
59
+ }
60
+
61
+ /**
62
+ * Make a DELETE request
63
+ */
64
+ async delete<T = any>(endpoint: string, options?: RequestInit): Promise<T> {
65
+ return this.request<T>(endpoint, { ...options, method: 'DELETE' });
66
+ }
67
+
68
+ /**
69
+ * Generic request method
70
+ */
71
+ private async request<T = any>(
72
+ endpoint: string,
73
+ options: RequestInit = {}
74
+ ): Promise<T> {
75
+ const url = `${this.baseUrl}${endpoint}`;
76
+ const controller = new AbortController();
77
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
78
+
79
+ try {
80
+ const response = await fetch(url, {
81
+ ...options,
82
+ signal: controller.signal,
83
+ });
84
+
85
+ clearTimeout(timeoutId);
86
+
87
+ if (!response.ok) {
88
+ const errorData = await this.parseErrorResponse(response);
89
+ throw new ApiError(
90
+ errorData.message || `HTTP ${response.status}`,
91
+ response.status,
92
+ errorData
93
+ );
94
+ }
95
+
96
+ return await this.parseResponse<T>(response);
97
+ } catch (error) {
98
+ clearTimeout(timeoutId);
99
+
100
+ if (error instanceof ApiError) {
101
+ throw error;
102
+ }
103
+
104
+ if (error instanceof Error) {
105
+ if (error.name === 'AbortError') {
106
+ throw new ApiError('Request timeout', 408);
107
+ }
108
+ throw new ApiError(error.message, 0);
109
+ }
110
+
111
+ throw new ApiError('Unknown error occurred', 0);
112
+ }
113
+ }
114
+
115
+ /**
116
+ * Parse successful response
117
+ */
118
+ private async parseResponse<T>(response: Response): Promise<T> {
119
+ const contentType = response.headers.get('content-type');
120
+
121
+ if (contentType?.includes('application/json')) {
122
+ return response.json();
123
+ }
124
+
125
+ if (contentType?.includes('text/')) {
126
+ return (await response.text()) as any;
127
+ }
128
+
129
+ return undefined as any;
130
+ }
131
+
132
+ /**
133
+ * Parse error response
134
+ */
135
+ private async parseErrorResponse(response: Response): Promise<any> {
136
+ try {
137
+ const contentType = response.headers.get('content-type');
138
+ if (contentType?.includes('application/json')) {
139
+ return await response.json();
140
+ }
141
+ return { message: response.statusText };
142
+ } catch {
143
+ return { message: 'Unknown error' };
144
+ }
145
+ }
146
+ }
147
+
148
+ /**
149
+ * Custom API Error class
150
+ */
151
+ export class ApiError extends Error {
152
+ constructor(
153
+ message: string,
154
+ public status: number,
155
+ public data?: any
156
+ ) {
157
+ super(message);
158
+ this.name = 'ApiError';
159
+ }
160
+ }
161
+
162
+ // Export singleton instance
163
+ export const apiClient = new ApiClient();
@@ -0,0 +1,121 @@
1
+ /**
2
+ * AppClean GUI - Main SPA Controller
3
+ * Initializes router, stores, and pages
4
+ */
5
+
6
+ import { router } from './utils/router.js';
7
+ import { appStore } from './state/appStore.js';
8
+ import { dashboardStore } from './state/dashboardStore.js';
9
+ import { uiStore } from './state/uiStore.js';
10
+
11
+ // Import page modules
12
+ import { renderDashboard } from './pages/dashboard.js';
13
+ import { renderAppSearch } from './pages/appSearch.js';
14
+ import { renderAppDetails } from './pages/appDetails.js';
15
+ import { renderSettings } from './pages/settings.js';
16
+
17
+ /**
18
+ * Initialize the SPA
19
+ */
20
+ export function initApp(): void {
21
+ console.log('๐Ÿงน AppClean GUI v1.0.0 initializing...');
22
+
23
+ // Register routes
24
+ registerRoutes();
25
+
26
+ // Initialize stores
27
+ initializeStores();
28
+
29
+ // Setup UI listeners
30
+ setupUIListeners();
31
+
32
+ // Navigate to initial route
33
+ router.navigate('');
34
+
35
+ console.log('โœ“ AppClean GUI ready');
36
+ }
37
+
38
+ /**
39
+ * Register all routes
40
+ */
41
+ function registerRoutes(): void {
42
+ router.register('', () => {
43
+ uiStore.navigateTo('dashboard');
44
+ renderDashboard();
45
+ }, 'AppClean - Dashboard');
46
+
47
+ router.register('apps', () => {
48
+ uiStore.navigateTo('apps');
49
+ renderAppSearch();
50
+ }, 'AppClean - Apps');
51
+
52
+ router.register('apps/:appName', (params) => {
53
+ uiStore.navigateTo('app-details');
54
+ renderAppDetails(params.appName);
55
+ }, 'AppClean - App Details');
56
+
57
+ router.register('settings', () => {
58
+ uiStore.navigateTo('settings');
59
+ renderSettings();
60
+ }, 'AppClean - Settings');
61
+ }
62
+
63
+ /**
64
+ * Initialize stores with data
65
+ */
66
+ async function initializeStores(): Promise<void> {
67
+ try {
68
+ // Load dashboard stats
69
+ await dashboardStore.loadStats();
70
+
71
+ // Load initial app list
72
+ await appStore.loadApps();
73
+ } catch (error) {
74
+ console.error('Failed to initialize stores:', error);
75
+ uiStore.showError('Failed to load application data');
76
+ }
77
+ }
78
+
79
+ /**
80
+ * Setup UI event listeners
81
+ */
82
+ function setupUIListeners(): void {
83
+ // Subscribe to UI store changes
84
+ uiStore.subscribe((state) => {
85
+ console.log('UI State changed:', state.currentView);
86
+ });
87
+
88
+ // Subscribe to app store changes
89
+ appStore.subscribe((state) => {
90
+ console.log(`Apps loaded: ${state.apps.length}`);
91
+ });
92
+
93
+ // Subscribe to dashboard store changes
94
+ dashboardStore.subscribe((state) => {
95
+ if (state.stats) {
96
+ console.log(`Dashboard stats: ${state.stats.totalApps} apps, ${state.stats.totalSpaceUsed} bytes`);
97
+ }
98
+ });
99
+
100
+ // Handle route changes
101
+ router.onchange((route) => {
102
+ console.log('Navigated to:', route.path);
103
+ });
104
+
105
+ // Theme toggle listener
106
+ document.addEventListener('theme-toggle', () => {
107
+ uiStore.toggleTheme();
108
+ });
109
+ }
110
+
111
+ /**
112
+ * Export for consumption in HTML
113
+ */
114
+ export { appStore, dashboardStore, uiStore, router };
115
+
116
+ // Initialize on DOM ready
117
+ if (document.readyState === 'loading') {
118
+ document.addEventListener('DOMContentLoaded', initApp);
119
+ } else {
120
+ initApp();
121
+ }
@@ -0,0 +1,107 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <meta name="description" content="AppClean - Intelligently remove applications and all their hidden files">
7
+ <meta name="theme-color" content="#3b82f6">
8
+ <title>AppClean - Application Remover</title>
9
+
10
+ <!-- Styles -->
11
+ <link rel="stylesheet" href="/static/styles/variables.css">
12
+ <link rel="stylesheet" href="/static/styles/base.css">
13
+ <link rel="stylesheet" href="/static/styles/layout.css">
14
+ <link rel="stylesheet" href="/static/styles/components.css">
15
+ <link rel="stylesheet" href="/static/styles/animations.css">
16
+ </head>
17
+ <body>
18
+ <!-- Root container for SPA -->
19
+ <div id="app" class="app-root">
20
+ <!-- Navbar -->
21
+ <nav class="navbar" id="navbar">
22
+ <div class="container-xl">
23
+ <div class="flex-between">
24
+ <div class="flex items-center gap-4">
25
+ <h1 class="navbar-brand" id="navbar-brand">๐Ÿงน AppClean</h1>
26
+ <button class="btn btn-ghost navbar-menu-toggle" id="navbar-menu-toggle" aria-label="Toggle navigation">
27
+ <span class="hamburger">โ˜ฐ</span>
28
+ </button>
29
+ </div>
30
+ <div class="flex items-center gap-2">
31
+ <button class="btn btn-ghost btn-sm" id="theme-toggle" aria-label="Toggle dark mode">
32
+ <span class="theme-icon">๐ŸŒ™</span>
33
+ </button>
34
+ </div>
35
+ </div>
36
+ </div>
37
+ </nav>
38
+
39
+ <!-- Main layout -->
40
+ <div class="app-layout flex">
41
+ <!-- Sidebar -->
42
+ <aside class="sidebar" id="sidebar">
43
+ <div class="sidebar-nav">
44
+ <nav class="nav-links">
45
+ <a href="#/" class="nav-link active" data-view="dashboard">
46
+ <span class="nav-icon">๐Ÿ“Š</span>
47
+ <span class="nav-label">Dashboard</span>
48
+ </a>
49
+ <a href="#/apps" class="nav-link" data-view="apps">
50
+ <span class="nav-icon">๐Ÿ“ฆ</span>
51
+ <span class="nav-label">Apps</span>
52
+ </a>
53
+ <a href="#/settings" class="nav-link" data-view="settings">
54
+ <span class="nav-icon">โš™๏ธ</span>
55
+ <span class="nav-label">Settings</span>
56
+ </a>
57
+ </nav>
58
+ </div>
59
+ <div class="sidebar-footer">
60
+ <a href="https://github.com/praveenkay/AppClean" target="_blank" rel="noopener" class="sidebar-link">
61
+ <span class="nav-icon">๐Ÿ’ฌ</span>
62
+ <span class="nav-label">GitHub</span>
63
+ </a>
64
+ </div>
65
+ </aside>
66
+
67
+ <!-- Main content -->
68
+ <main class="main-content" id="main-content">
69
+ <div class="container-xl">
70
+ <!-- Pages will be rendered here -->
71
+ <div id="page-container" class="page-container">
72
+ <!-- Loading skeleton -->
73
+ <div class="loading-state" id="loading-state">
74
+ <div class="spinner-lg spinner"></div>
75
+ <p class="text-center text-muted mt-4">Loading AppClean...</p>
76
+ </div>
77
+ </div>
78
+ </div>
79
+ </main>
80
+ </div>
81
+
82
+ <!-- Modals -->
83
+ <div class="modal-backdrop" id="modal-backdrop">
84
+ <div class="modal" id="modal" role="dialog" aria-labelledby="modal-title">
85
+ <div class="modal-header">
86
+ <h2 class="modal-title" id="modal-title">Dialog</h2>
87
+ <button class="modal-close" id="modal-close" aria-label="Close dialog">&times;</button>
88
+ </div>
89
+ <div class="modal-body" id="modal-body">
90
+ <!-- Content will be rendered here -->
91
+ </div>
92
+ <div class="modal-footer" id="modal-footer">
93
+ <!-- Buttons will be rendered here -->
94
+ </div>
95
+ </div>
96
+ </div>
97
+
98
+ <!-- Notifications -->
99
+ <div class="notifications-container" id="notifications-container" role="region" aria-label="Notifications" aria-live="polite">
100
+ <!-- Notifications will be rendered here -->
101
+ </div>
102
+ </div>
103
+
104
+ <!-- Scripts -->
105
+ <script type="module" src="/static/app.js"></script>
106
+ </body>
107
+ </html>