appclean 1.9.0 → 2.0.2

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 (212) hide show
  1. package/.github/workflows/npm-publish.yml +61 -0
  2. package/DEVELOPMENT.md +84 -0
  3. package/GUI_IMPLEMENTATION_STATUS.md +143 -0
  4. package/MD_Files/INDEX.md +51 -0
  5. package/PHASE2_COMPLETION.md +281 -0
  6. package/PHASE3_COMPLETION.md +364 -0
  7. package/README.md +411 -91
  8. package/RELEASE_GUIDE.md +236 -0
  9. package/assets/logo.svg +34 -0
  10. package/dist/core/appUpdateChecker.js +12 -16
  11. package/dist/core/appUpdateChecker.js.map +1 -1
  12. package/dist/core/detector.js +14 -18
  13. package/dist/core/detector.js.map +1 -1
  14. package/dist/core/duplicateFileFinder.js +12 -19
  15. package/dist/core/duplicateFileFinder.js.map +1 -1
  16. package/dist/core/orphanedDependencyDetector.js +19 -26
  17. package/dist/core/orphanedDependencyDetector.js.map +1 -1
  18. package/dist/core/performanceOptimizer.js +6 -10
  19. package/dist/core/performanceOptimizer.js.map +1 -1
  20. package/dist/core/permissionHandler.js +21 -25
  21. package/dist/core/permissionHandler.js.map +1 -1
  22. package/dist/core/pluginSystem.js +9 -13
  23. package/dist/core/pluginSystem.js.map +1 -1
  24. package/dist/core/removalRecorder.js +12 -19
  25. package/dist/core/removalRecorder.js.map +1 -1
  26. package/dist/core/remover.js +59 -66
  27. package/dist/core/remover.js.map +1 -1
  28. package/dist/core/reportGenerator.d.ts +1 -1
  29. package/dist/core/reportGenerator.d.ts.map +1 -1
  30. package/dist/core/reportGenerator.js +27 -34
  31. package/dist/core/reportGenerator.js.map +1 -1
  32. package/dist/core/scheduledCleanup.js +23 -30
  33. package/dist/core/scheduledCleanup.js.map +1 -1
  34. package/dist/core/serviceFileDetector.js +24 -31
  35. package/dist/core/serviceFileDetector.js.map +1 -1
  36. package/dist/core/verificationModule.js +10 -14
  37. package/dist/core/verificationModule.js.map +1 -1
  38. package/dist/index.js +118 -156
  39. package/dist/index.js.map +1 -1
  40. package/dist/managers/brewManager.js +30 -37
  41. package/dist/managers/brewManager.js.map +1 -1
  42. package/dist/managers/customManager.js +23 -30
  43. package/dist/managers/customManager.js.map +1 -1
  44. package/dist/managers/linuxManager.js +29 -36
  45. package/dist/managers/linuxManager.js.map +1 -1
  46. package/dist/managers/npmManager.js +27 -34
  47. package/dist/managers/npmManager.js.map +1 -1
  48. package/dist/types/index.js +1 -2
  49. package/dist/ui/client/api/client.d.ts +24 -0
  50. package/dist/ui/client/api/client.d.ts.map +1 -0
  51. package/dist/ui/client/api/client.js +100 -0
  52. package/dist/ui/client/api/client.js.map +1 -0
  53. package/dist/ui/client/app.d.ts +7 -0
  54. package/dist/ui/client/app.d.ts.map +1 -0
  55. package/dist/ui/client/app.js +75 -0
  56. package/dist/ui/client/app.js.map +1 -0
  57. package/dist/ui/client/index.html +107 -0
  58. package/dist/ui/client/pages/appDetails.d.ts +8 -0
  59. package/dist/ui/client/pages/appDetails.d.ts.map +1 -0
  60. package/dist/ui/client/pages/appDetails.js +287 -0
  61. package/dist/ui/client/pages/appDetails.js.map +1 -0
  62. package/dist/ui/client/pages/appSearch.d.ts +2 -0
  63. package/dist/ui/client/pages/appSearch.d.ts.map +1 -0
  64. package/dist/ui/client/pages/appSearch.js +221 -0
  65. package/dist/ui/client/pages/appSearch.js.map +1 -0
  66. package/dist/ui/client/pages/dashboard.d.ts +2 -0
  67. package/dist/ui/client/pages/dashboard.d.ts.map +1 -0
  68. package/dist/ui/client/pages/dashboard.js +175 -0
  69. package/dist/ui/client/pages/dashboard.js.map +1 -0
  70. package/dist/ui/client/pages/settings.d.ts +7 -0
  71. package/dist/ui/client/pages/settings.d.ts.map +1 -0
  72. package/dist/ui/client/pages/settings.js +279 -0
  73. package/dist/ui/client/pages/settings.js.map +1 -0
  74. package/dist/ui/client/state/appStore.d.ts +38 -0
  75. package/dist/ui/client/state/appStore.d.ts.map +1 -0
  76. package/dist/ui/client/state/appStore.js +130 -0
  77. package/dist/ui/client/state/appStore.js.map +1 -0
  78. package/dist/ui/client/state/dashboardStore.d.ts +31 -0
  79. package/dist/ui/client/state/dashboardStore.d.ts.map +1 -0
  80. package/dist/ui/client/state/dashboardStore.js +76 -0
  81. package/dist/ui/client/state/dashboardStore.js.map +1 -0
  82. package/dist/ui/client/state/uiStore.d.ts +43 -0
  83. package/dist/ui/client/state/uiStore.d.ts.map +1 -0
  84. package/dist/ui/client/state/uiStore.js +109 -0
  85. package/dist/ui/client/state/uiStore.js.map +1 -0
  86. package/dist/ui/client/styles/animations.css +349 -0
  87. package/dist/ui/client/styles/base.css +214 -0
  88. package/dist/ui/client/styles/components.css +400 -0
  89. package/dist/ui/client/styles/layout.css +224 -0
  90. package/dist/ui/client/styles/variables.css +140 -0
  91. package/dist/ui/client/utils/events.d.ts +19 -0
  92. package/dist/ui/client/utils/events.d.ts.map +1 -0
  93. package/dist/ui/client/utils/events.js +54 -0
  94. package/dist/ui/client/utils/events.js.map +1 -0
  95. package/dist/ui/client/utils/formatting.d.ts +11 -0
  96. package/dist/ui/client/utils/formatting.d.ts.map +1 -0
  97. package/dist/ui/client/utils/formatting.js +104 -0
  98. package/dist/ui/client/utils/formatting.js.map +1 -0
  99. package/dist/ui/client/utils/router.d.ts +25 -0
  100. package/dist/ui/client/utils/router.d.ts.map +1 -0
  101. package/dist/ui/client/utils/router.js +90 -0
  102. package/dist/ui/client/utils/router.js.map +1 -0
  103. package/dist/ui/guiServer.d.ts +11 -5
  104. package/dist/ui/guiServer.d.ts.map +1 -1
  105. package/dist/ui/guiServer.js +180 -501
  106. package/dist/ui/guiServer.js.map +1 -1
  107. package/dist/ui/menu.js +18 -27
  108. package/dist/ui/menu.js.map +1 -1
  109. package/dist/ui/prompts.js +34 -47
  110. package/dist/ui/prompts.js.map +1 -1
  111. package/dist/ui/server/middleware/errorHandler.d.ts +19 -0
  112. package/dist/ui/server/middleware/errorHandler.d.ts.map +1 -0
  113. package/dist/ui/server/middleware/errorHandler.js +100 -0
  114. package/dist/ui/server/middleware/errorHandler.js.map +1 -0
  115. package/dist/ui/server/routes/apps.d.ts +8 -0
  116. package/dist/ui/server/routes/apps.d.ts.map +1 -0
  117. package/dist/ui/server/routes/apps.js +74 -0
  118. package/dist/ui/server/routes/apps.js.map +1 -0
  119. package/dist/ui/server/routes/dashboard.d.ts +4 -0
  120. package/dist/ui/server/routes/dashboard.d.ts.map +1 -0
  121. package/dist/ui/server/routes/dashboard.js +57 -0
  122. package/dist/ui/server/routes/dashboard.js.map +1 -0
  123. package/dist/ui/server/routes/settings.d.ts +6 -0
  124. package/dist/ui/server/routes/settings.d.ts.map +1 -0
  125. package/dist/ui/server/routes/settings.js +31 -0
  126. package/dist/ui/server/routes/settings.js.map +1 -0
  127. package/dist/ui/server/services/appService.d.ts +45 -0
  128. package/dist/ui/server/services/appService.d.ts.map +1 -0
  129. package/dist/ui/server/services/appService.js +114 -0
  130. package/dist/ui/server/services/appService.js.map +1 -0
  131. package/dist/ui/server/services/removalService.d.ts +24 -0
  132. package/dist/ui/server/services/removalService.d.ts.map +1 -0
  133. package/dist/ui/server/services/removalService.js +83 -0
  134. package/dist/ui/server/services/removalService.js.map +1 -0
  135. package/dist/utils/filesystem.js +32 -49
  136. package/dist/utils/filesystem.js.map +1 -1
  137. package/dist/utils/logger.js +9 -18
  138. package/dist/utils/logger.js.map +1 -1
  139. package/dist/utils/platform.js +10 -22
  140. package/dist/utils/platform.js.map +1 -1
  141. package/dist/utils/upgrade.d.ts +2 -1
  142. package/dist/utils/upgrade.d.ts.map +1 -1
  143. package/dist/utils/upgrade.js +24 -15
  144. package/dist/utils/upgrade.js.map +1 -1
  145. package/package.json +4 -2
  146. package/scripts/publish-npm.sh +64 -0
  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 +8 -8
  161. package/src/managers/brewManager.ts +3 -3
  162. package/src/managers/customManager.ts +2 -2
  163. package/src/managers/linuxManager.ts +3 -3
  164. package/src/managers/npmManager.ts +3 -3
  165. package/src/ui/client/api/client.ts +168 -0
  166. package/src/ui/client/app.ts +125 -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 +283 -0
  170. package/src/ui/client/pages/dashboard.ts +211 -0
  171. package/src/ui/client/pages/settings.ts +342 -0
  172. package/src/ui/client/state/appStore.ts +181 -0
  173. package/src/ui/client/state/dashboardStore.ts +123 -0
  174. package/src/ui/client/state/uiStore.ts +166 -0
  175. package/src/ui/client/styles/animations.css +349 -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 +245 -498
  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 +19 -2
  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/{PUBLICATION_SUCCESS_REPORT.md → MD_Files/PUBLICATION_SUCCESS_REPORT.md} +0 -0
  209. /package/{QUICKSTART.md → MD_Files/QUICKSTART.md} +0 -0
  210. /package/{SETUP_GITHUB.md → MD_Files/SETUP_GITHUB.md} +0 -0
  211. /package/{TESTING_SUMMARY.md → MD_Files/TESTING_SUMMARY.md} +0 -0
  212. /package/{setup-github.sh → MD_Files/setup-github.sh} +0 -0
@@ -0,0 +1,175 @@
1
+ import { dashboardStore } from '../state/dashboardStore.js';
2
+ import { formatBytes, formatPercent, formatRelativeTime } from '../utils/formatting.js';
3
+ export function renderDashboard() {
4
+ const container = document.getElementById('page-container');
5
+ if (!container)
6
+ return;
7
+ container.innerHTML = `
8
+ <div class="loading-state" style="text-align: center; padding: 60px 20px;">
9
+ <div class="spinner-lg spinner"></div>
10
+ <p class="text-center text-muted mt-4">Loading dashboard...</p>
11
+ </div>
12
+ `;
13
+ dashboardStore.refreshStats(true).then(() => {
14
+ const state = dashboardStore.getState();
15
+ const stats = state.stats;
16
+ const error = state.error;
17
+ if (error) {
18
+ container.innerHTML = `
19
+ <div class="alert alert-danger" style="margin: 20px;">
20
+ <h3 style="margin-top: 0;">⚠️ Error Loading Dashboard</h3>
21
+ <p>${escapeHtml(error)}</p>
22
+ <button class="btn btn-primary btn-sm" onclick="window.location.reload()">Retry</button>
23
+ </div>
24
+ `;
25
+ return;
26
+ }
27
+ if (!stats) {
28
+ container.innerHTML = `
29
+ <div class="alert alert-warning" style="margin: 20px;">
30
+ <h3 style="margin-top: 0;">⏳ Initializing</h3>
31
+ <p>Dashboard is loading. Please wait...</p>
32
+ </div>
33
+ `;
34
+ return;
35
+ }
36
+ renderDashboardContent(container, stats);
37
+ dashboardStore.subscribe((newState) => {
38
+ if (newState.stats) {
39
+ renderDashboardContent(container, newState.stats);
40
+ }
41
+ });
42
+ }).catch((error) => {
43
+ console.error('Dashboard error:', error);
44
+ container.innerHTML = `
45
+ <div class="alert alert-danger" style="margin: 20px;">
46
+ <h3 style="margin-top: 0;">❌ Failed to Load Dashboard</h3>
47
+ <p>An unexpected error occurred. Please check the console for details.</p>
48
+ <button class="btn btn-primary btn-sm" onclick="window.location.reload()">Reload Page</button>
49
+ </div>
50
+ `;
51
+ });
52
+ }
53
+ function renderDashboardContent(container, stats) {
54
+ container.innerHTML = `
55
+ <div class="dashboard-page fade-in">
56
+ <!-- Header -->
57
+ <div class="page-header mb-8">
58
+ <h1 class="text-3xl font-bold">📊 Dashboard</h1>
59
+ <p class="text-secondary mt-2">System overview and app management</p>
60
+ </div>
61
+
62
+ <!-- Stats Grid -->
63
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-6 mb-8">
64
+ ${renderStatCard('📦 Installed Apps', stats.totalApps.toString(), 'Total applications detected')}
65
+ ${renderStatCard('💾 Total Space Used', formatBytes(stats.totalSpaceUsed), 'Size of all app files')}
66
+ ${renderStatCard('🗑️ Removed (Session)', stats.sessionAppsRemoved.toString(), 'Apps removed this session')}
67
+ ${renderStatCard('📉 Space Freed', formatBytes(stats.sessionSpaceFreed), 'Total space recovered')}
68
+ </div>
69
+
70
+ <!-- System Health -->
71
+ <div class="card mb-8">
72
+ <div class="card-header">
73
+ <h2 class="text-xl font-bold">💻 System Health</h2>
74
+ </div>
75
+ <div class="card-body">
76
+ <div class="health-gauge mb-4">
77
+ <div class="flex-between mb-2">
78
+ <span class="text-sm font-medium">Disk Usage</span>
79
+ <span class="text-sm font-bold">${formatPercent(stats.diskUsagePercent)}</span>
80
+ </div>
81
+ <div class="progress-bar" style="height: 8px; background: #e5e7eb; border-radius: 4px; overflow: hidden;">
82
+ <div style="
83
+ height: 100%;
84
+ width: ${stats.diskUsagePercent}%;
85
+ background: ${getDiskUsageColor(stats.diskUsagePercent)};
86
+ transition: width 0.3s ease;
87
+ "></div>
88
+ </div>
89
+ </div>
90
+ <p class="text-sm text-muted">
91
+ ${stats.diskUsagePercent < 80
92
+ ? '✅ Disk usage is healthy'
93
+ : stats.diskUsagePercent < 90
94
+ ? '⚠️ Disk usage is getting high'
95
+ : '🔴 Disk usage is critical'}
96
+ </p>
97
+ </div>
98
+ </div>
99
+
100
+ <!-- Recent Activity -->
101
+ <div class="card">
102
+ <div class="card-header">
103
+ <h2 class="text-xl font-bold">📜 Recent Activity</h2>
104
+ </div>
105
+ <div class="card-body">
106
+ ${stats.recentlyRemoved.length > 0
107
+ ? `
108
+ <div class="activity-list">
109
+ ${stats.recentlyRemoved
110
+ .slice(0, 10)
111
+ .map((removal) => `
112
+ <div class="activity-item flex-between p-3 border-b border-color last:border-0" style="padding: 12px 0;">
113
+ <div class="activity-info">
114
+ <p class="text-sm font-medium">${escapeHtml(removal.appName)}</p>
115
+ <p class="text-xs text-muted">Removed ${formatRelativeTime(removal.timestamp)}</p>
116
+ </div>
117
+ <div class="activity-stats text-right">
118
+ <p class="text-sm font-bold text-success">${formatBytes(removal.freedSpace)}</p>
119
+ <p class="text-xs text-muted">${removal.filesRemoved} files</p>
120
+ </div>
121
+ </div>
122
+ `)
123
+ .join('')}
124
+ </div>
125
+ `
126
+ : `
127
+ <p class="text-muted text-center py-8">
128
+ No apps removed yet. Start by searching for apps to remove.
129
+ </p>
130
+ `}
131
+ </div>
132
+ </div>
133
+
134
+ <!-- Quick Actions -->
135
+ <div class="mt-8 grid grid-cols-1 md:grid-cols-2 gap-4">
136
+ <button class="btn btn-primary btn-lg w-full" onclick="window.location.hash = '#/apps'">
137
+ <span>🔍 Find & Remove Apps</span>
138
+ </button>
139
+ <button class="btn btn-secondary btn-lg w-full" onclick="window.location.hash = '#/settings'">
140
+ <span>⚙️ Settings</span>
141
+ </button>
142
+ </div>
143
+ </div>
144
+ `;
145
+ window.scrollTo(0, 0);
146
+ }
147
+ function renderStatCard(label, value, description) {
148
+ return `
149
+ <div class="card">
150
+ <div class="card-body">
151
+ <p class="text-muted text-sm mb-2">${escapeHtml(label)}</p>
152
+ <p class="text-2xl font-bold text-primary mb-1">${escapeHtml(value)}</p>
153
+ <p class="text-xs text-muted">${escapeHtml(description)}</p>
154
+ </div>
155
+ </div>
156
+ `;
157
+ }
158
+ function getDiskUsageColor(percent) {
159
+ if (percent < 50)
160
+ return '#10b981';
161
+ if (percent < 80)
162
+ return '#f59e0b';
163
+ return '#ef4444';
164
+ }
165
+ function escapeHtml(text) {
166
+ const map = {
167
+ '&': '&amp;',
168
+ '<': '&lt;',
169
+ '>': '&gt;',
170
+ '"': '&quot;',
171
+ "'": '&#039;',
172
+ };
173
+ return text.replace(/[&<>"']/g, (m) => map[m]);
174
+ }
175
+ //# sourceMappingURL=dashboard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboard.js","sourceRoot":"","sources":["../../../../src/ui/client/pages/dashboard.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export interface VersionInfo {
2
+ current: string;
3
+ latest: string;
4
+ isUpdateAvailable: boolean;
5
+ }
6
+ export declare function renderSettings(): void;
7
+ //# sourceMappingURL=settings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../../../src/ui/client/pages/settings.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,iBAAiB,EAAE,OAAO,CAAC;CAC5B;AAKD,wBAAgB,cAAc,IAAI,IAAI,CAgBrC"}
@@ -0,0 +1,279 @@
1
+ import { apiClient } from '../api/client.js';
2
+ import { uiStore } from '../state/uiStore.js';
3
+ export function renderSettings() {
4
+ const container = document.getElementById('page-container');
5
+ if (!container)
6
+ return;
7
+ container.innerHTML = `
8
+ <div class="loading-state" style="text-align: center; padding: 60px 20px;">
9
+ <div class="spinner-lg spinner"></div>
10
+ <p class="text-center text-muted mt-4">Loading settings...</p>
11
+ </div>
12
+ `;
13
+ loadVersionInfo().then((versionInfo) => {
14
+ renderSettingsContent(container, versionInfo);
15
+ });
16
+ }
17
+ async function loadVersionInfo() {
18
+ try {
19
+ return await apiClient.get('/api/version');
20
+ }
21
+ catch (error) {
22
+ return {
23
+ current: 'unknown',
24
+ latest: 'unknown',
25
+ isUpdateAvailable: false,
26
+ };
27
+ }
28
+ }
29
+ function renderSettingsContent(container, versionInfo) {
30
+ const currentTheme = uiStore.getState().theme;
31
+ container.innerHTML = `
32
+ <div class="settings-page">
33
+ <!-- Header -->
34
+ <div class="page-header mb-8">
35
+ <h1 class="text-3xl font-bold">⚙️ Settings</h1>
36
+ <p class="text-secondary mt-2">Configure AppClean</p>
37
+ </div>
38
+
39
+ <!-- Version & Updates Section -->
40
+ <div class="card mb-6">
41
+ <div class="card-header">
42
+ <h2 class="text-xl font-bold">📦 Version & Updates</h2>
43
+ </div>
44
+ <div class="card-body">
45
+ <div class="version-info p-4 bg-secondary rounded mb-4">
46
+ <div class="flex-between mb-3">
47
+ <span class="text-sm font-medium">Current Version</span>
48
+ <span class="text-lg font-bold text-primary">v${escapeHtml(versionInfo.current)}</span>
49
+ </div>
50
+ <div class="flex-between">
51
+ <span class="text-sm font-medium">Latest Version</span>
52
+ <span class="text-lg font-bold ${versionInfo.isUpdateAvailable ? 'text-warning' : 'text-success'}">
53
+ v${escapeHtml(versionInfo.latest)}
54
+ </span>
55
+ </div>
56
+ </div>
57
+
58
+ ${versionInfo.isUpdateAvailable
59
+ ? `
60
+ <div class="alert alert-warning mb-4">
61
+ <span>A new version of AppClean is available!</span>
62
+ </div>
63
+ <div class="flex gap-2">
64
+ <button class="btn btn-primary flex-1" id="upgrade-btn">
65
+ 🚀 Upgrade Now
66
+ </button>
67
+ <button class="btn btn-secondary flex-1" id="check-update-btn">
68
+ 🔄 Check Again
69
+ </button>
70
+ </div>
71
+ `
72
+ : `
73
+ <div class="alert alert-success mb-4">
74
+ <span>✓ You're running the latest version!</span>
75
+ </div>
76
+ <button class="btn btn-secondary w-full" id="check-update-btn">
77
+ 🔄 Check for Updates
78
+ </button>
79
+ `}
80
+ </div>
81
+ </div>
82
+
83
+ <!-- Theme Section -->
84
+ <div class="card mb-6">
85
+ <div class="card-header">
86
+ <h2 class="text-xl font-bold">🎨 Appearance</h2>
87
+ </div>
88
+ <div class="card-body">
89
+ <div class="flex-between items-center p-3 border border-color rounded mb-4">
90
+ <div>
91
+ <p class="font-medium">Dark Mode</p>
92
+ <p class="text-sm text-muted">Switch between light and dark themes</p>
93
+ </div>
94
+ <button
95
+ class="btn btn-sm ${currentTheme === 'dark' ? 'btn-primary' : 'btn-secondary'}"
96
+ id="theme-toggle-btn"
97
+ >
98
+ ${currentTheme === 'dark' ? '🌙 Dark' : '☀️ Light'}
99
+ </button>
100
+ </div>
101
+ </div>
102
+ </div>
103
+
104
+ <!-- About Section -->
105
+ <div class="card mb-6">
106
+ <div class="card-header">
107
+ <h2 class="text-xl font-bold">ℹ️ About</h2>
108
+ </div>
109
+ <div class="card-body">
110
+ <div class="space-y-4">
111
+ <div>
112
+ <p class="text-sm font-medium mb-2">AppClean</p>
113
+ <p class="text-sm text-muted">
114
+ Intelligently find and safely remove applications with all their artifacts.
115
+ </p>
116
+ </div>
117
+
118
+ <div>
119
+ <p class="text-sm font-medium mb-2">Links</p>
120
+ <div class="flex gap-2">
121
+ <a
122
+ href="https://github.com/praveenkay/AppClean"
123
+ target="_blank"
124
+ rel="noopener"
125
+ class="btn btn-sm btn-ghost"
126
+ >
127
+ 💻 GitHub
128
+ </a>
129
+ <a
130
+ href="https://github.com/praveenkay/AppClean/issues"
131
+ target="_blank"
132
+ rel="noopener"
133
+ class="btn btn-sm btn-ghost"
134
+ >
135
+ 🐛 Report Issue
136
+ </a>
137
+ </div>
138
+ </div>
139
+ </div>
140
+ </div>
141
+ </div>
142
+
143
+ <!-- Danger Zone -->
144
+ <div class="card" style="border-color: var(--color-danger);">
145
+ <div class="card-header" style="background: var(--color-danger-light);">
146
+ <h2 class="text-xl font-bold text-danger">⚠️ Danger Zone</h2>
147
+ </div>
148
+ <div class="card-body">
149
+ <p class="text-sm text-muted mb-4">
150
+ Uninstall AppClean from your system. This action cannot be undone.
151
+ </p>
152
+ <button class="btn btn-danger w-full" id="uninstall-btn">
153
+ 🗑️ Uninstall AppClean
154
+ </button>
155
+ </div>
156
+ </div>
157
+ </div>
158
+ `;
159
+ setupSettingsListeners();
160
+ window.scrollTo(0, 0);
161
+ }
162
+ function setupSettingsListeners() {
163
+ const upgradeBtn = document.getElementById('upgrade-btn');
164
+ const checkUpdateBtn = document.getElementById('check-update-btn');
165
+ const themeToggleBtn = document.getElementById('theme-toggle-btn');
166
+ const uninstallBtn = document.getElementById('uninstall-btn');
167
+ if (upgradeBtn) {
168
+ upgradeBtn.addEventListener('click', async () => {
169
+ upgradeBtn.disabled = true;
170
+ upgradeBtn.textContent = '⏳ Upgrading...';
171
+ try {
172
+ const result = await apiClient.post('/api/upgrade', {});
173
+ if (result.success) {
174
+ uiStore.showSuccess(result.message);
175
+ setTimeout(() => {
176
+ window.location.reload();
177
+ }, 2000);
178
+ }
179
+ else {
180
+ uiStore.showError(result.message);
181
+ upgradeBtn.disabled = false;
182
+ upgradeBtn.textContent = '🚀 Upgrade Now';
183
+ }
184
+ }
185
+ catch (error) {
186
+ uiStore.showError(`Upgrade failed: ${error.message}`);
187
+ upgradeBtn.disabled = false;
188
+ upgradeBtn.textContent = '🚀 Upgrade Now';
189
+ }
190
+ });
191
+ }
192
+ if (checkUpdateBtn) {
193
+ checkUpdateBtn.addEventListener('click', async () => {
194
+ checkUpdateBtn.disabled = true;
195
+ checkUpdateBtn.textContent = '⏳ Checking...';
196
+ try {
197
+ const versionInfo = await apiClient.get('/api/version');
198
+ if (versionInfo.isUpdateAvailable) {
199
+ uiStore.showWarning(`Update available: v${versionInfo.latest} (current: v${versionInfo.current})`);
200
+ }
201
+ else {
202
+ uiStore.showSuccess('You are running the latest version!');
203
+ }
204
+ setTimeout(() => {
205
+ window.location.reload();
206
+ }, 1500);
207
+ }
208
+ catch (error) {
209
+ uiStore.showError(`Failed to check updates: ${error.message}`);
210
+ checkUpdateBtn.disabled = false;
211
+ checkUpdateBtn.textContent = '🔄 Check Again';
212
+ }
213
+ });
214
+ }
215
+ if (themeToggleBtn) {
216
+ themeToggleBtn.addEventListener('click', () => {
217
+ uiStore.toggleTheme();
218
+ const newTheme = uiStore.getState().theme;
219
+ themeToggleBtn.className = `btn btn-sm ${newTheme === 'dark' ? 'btn-primary' : 'btn-secondary'}`;
220
+ themeToggleBtn.textContent = newTheme === 'dark' ? '🌙 Dark' : '☀️ Light';
221
+ });
222
+ }
223
+ if (uninstallBtn) {
224
+ uninstallBtn.addEventListener('click', () => {
225
+ const confirmed = confirm('Are you sure you want to uninstall AppClean?\n\nThis action cannot be undone.');
226
+ if (!confirmed)
227
+ return;
228
+ const doubleConfirmed = confirm('This will permanently remove AppClean from your system.\n\nType "YES" in the next dialog to confirm.');
229
+ if (!doubleConfirmed)
230
+ return;
231
+ uninstall();
232
+ });
233
+ }
234
+ }
235
+ async function uninstall() {
236
+ const uninstallBtn = document.getElementById('uninstall-btn');
237
+ if (uninstallBtn) {
238
+ uninstallBtn.disabled = true;
239
+ uninstallBtn.textContent = '⏳ Uninstalling...';
240
+ }
241
+ uiStore.setProcessing(true);
242
+ try {
243
+ const result = await apiClient.post('/api/uninstall', {});
244
+ if (result.success) {
245
+ uiStore.showSuccess(result.message);
246
+ setTimeout(() => {
247
+ window.close();
248
+ }, 2000);
249
+ }
250
+ else {
251
+ uiStore.showError(result.message);
252
+ if (uninstallBtn) {
253
+ uninstallBtn.disabled = false;
254
+ uninstallBtn.textContent = '🗑️ Uninstall AppClean';
255
+ }
256
+ }
257
+ }
258
+ catch (error) {
259
+ uiStore.showError(`Uninstall failed: ${error.message}`);
260
+ if (uninstallBtn) {
261
+ uninstallBtn.disabled = false;
262
+ uninstallBtn.textContent = '🗑️ Uninstall AppClean';
263
+ }
264
+ }
265
+ finally {
266
+ uiStore.setProcessing(false);
267
+ }
268
+ }
269
+ function escapeHtml(text) {
270
+ const map = {
271
+ '&': '&amp;',
272
+ '<': '&lt;',
273
+ '>': '&gt;',
274
+ '"': '&quot;',
275
+ "'": '&#039;',
276
+ };
277
+ return String(text).replace(/[&<>"']/g, (m) => map[m]);
278
+ }
279
+ //# sourceMappingURL=settings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings.js","sourceRoot":"","sources":["../../../../src/ui/client/pages/settings.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ import { Store } from '../utils/events.js';
2
+ export interface InstalledApp {
3
+ name: string;
4
+ version: string;
5
+ installMethod: string;
6
+ mainPath: string;
7
+ installedDate?: string;
8
+ size?: number;
9
+ }
10
+ export interface SearchOptions {
11
+ query: string;
12
+ installMethod?: string;
13
+ sortBy?: 'name' | 'size' | 'date';
14
+ }
15
+ export interface AppStoreState {
16
+ apps: InstalledApp[];
17
+ searchOptions: SearchOptions;
18
+ selectedApp: InstalledApp | null;
19
+ isLoading: boolean;
20
+ error: string | null;
21
+ total: number;
22
+ page: number;
23
+ pageSize: number;
24
+ }
25
+ export declare class AppStore extends Store<AppStoreState> {
26
+ constructor();
27
+ loadApps(): Promise<void>;
28
+ searchApps(options: Partial<SearchOptions>): Promise<void>;
29
+ setSearchQuery(query: string): void;
30
+ setInstallMethodFilter(method?: string): void;
31
+ setSortBy(sortBy: 'name' | 'size' | 'date'): void;
32
+ selectApp(app: InstalledApp): void;
33
+ clearSelection(): void;
34
+ loadNextPage(): Promise<void>;
35
+ clearError(): void;
36
+ }
37
+ export declare const appStore: AppStore;
38
+ //# sourceMappingURL=appStore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"appStore.d.ts","sourceRoot":"","sources":["../../../../src/ui/client/state/appStore.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE3C,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;CACnC;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,YAAY,EAAE,CAAC;IACrB,aAAa,EAAE,aAAa,CAAC;IAC7B,WAAW,EAAE,YAAY,GAAG,IAAI,CAAC;IACjC,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAiBD,qBAAa,QAAS,SAAQ,KAAK,CAAC,aAAa,CAAC;;IAM1C,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IA0BzB,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAkChE,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAKnC,sBAAsB,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI;IAK7C,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI;IAKjD,SAAS,CAAC,GAAG,EAAE,YAAY,GAAG,IAAI;IAKlC,cAAc,IAAI,IAAI;IAKhB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAoCnC,UAAU,IAAI,IAAI;CAGnB;AAGD,eAAO,MAAM,QAAQ,UAAiB,CAAC"}
@@ -0,0 +1,130 @@
1
+ import { Store } from '../utils/events.js';
2
+ const INITIAL_STATE = {
3
+ apps: [],
4
+ searchOptions: {
5
+ query: '',
6
+ installMethod: undefined,
7
+ sortBy: 'name',
8
+ },
9
+ selectedApp: null,
10
+ isLoading: false,
11
+ error: null,
12
+ total: 0,
13
+ page: 1,
14
+ pageSize: 50,
15
+ };
16
+ export class AppStore extends Store {
17
+ constructor() {
18
+ super(INITIAL_STATE);
19
+ }
20
+ async loadApps() {
21
+ this.setState({ isLoading: true, error: null });
22
+ try {
23
+ const response = await fetch('/api/apps/list');
24
+ if (!response.ok)
25
+ throw new Error('Failed to load apps');
26
+ const json = await response.json();
27
+ const data = json.data || json;
28
+ this.setState({
29
+ apps: data.apps || [],
30
+ total: data.total || 0,
31
+ page: data.page || 1,
32
+ isLoading: false,
33
+ });
34
+ }
35
+ catch (error) {
36
+ const errorMsg = error instanceof Error ? error.message : 'Unknown error';
37
+ console.error('Failed to load apps:', errorMsg);
38
+ this.setState({
39
+ error: errorMsg,
40
+ isLoading: false,
41
+ });
42
+ }
43
+ }
44
+ async searchApps(options) {
45
+ const searchOptions = { ...this.state.searchOptions, ...options };
46
+ this.setState({ searchOptions, isLoading: true, error: null, page: 1 });
47
+ try {
48
+ const params = new URLSearchParams();
49
+ if (searchOptions.query)
50
+ params.append('q', searchOptions.query);
51
+ if (searchOptions.installMethod)
52
+ params.append('method', searchOptions.installMethod);
53
+ if (searchOptions.sortBy)
54
+ params.append('sort', searchOptions.sortBy);
55
+ params.append('limit', String(this.state.pageSize));
56
+ params.append('offset', '0');
57
+ const response = await fetch(`/api/apps/search?${params}`);
58
+ if (!response.ok)
59
+ throw new Error('Failed to search apps');
60
+ const json = await response.json();
61
+ const data = json.data || json;
62
+ this.setState({
63
+ apps: data.apps || [],
64
+ total: data.count || 0,
65
+ isLoading: false,
66
+ });
67
+ }
68
+ catch (error) {
69
+ const errorMsg = error instanceof Error ? error.message : 'Unknown error';
70
+ console.error('Failed to search apps:', errorMsg);
71
+ this.setState({
72
+ error: errorMsg,
73
+ isLoading: false,
74
+ });
75
+ }
76
+ }
77
+ setSearchQuery(query) {
78
+ this.searchApps({ query });
79
+ }
80
+ setInstallMethodFilter(method) {
81
+ this.searchApps({ installMethod: method });
82
+ }
83
+ setSortBy(sortBy) {
84
+ this.searchApps({ sortBy });
85
+ }
86
+ selectApp(app) {
87
+ this.setState({ selectedApp: app });
88
+ }
89
+ clearSelection() {
90
+ this.setState({ selectedApp: null });
91
+ }
92
+ async loadNextPage() {
93
+ const nextPage = this.state.page + 1;
94
+ const offset = (nextPage - 1) * this.state.pageSize;
95
+ this.setState({ isLoading: true });
96
+ try {
97
+ const params = new URLSearchParams();
98
+ if (this.state.searchOptions.query)
99
+ params.append('q', this.state.searchOptions.query);
100
+ if (this.state.searchOptions.installMethod) {
101
+ params.append('method', this.state.searchOptions.installMethod);
102
+ }
103
+ params.append('limit', String(this.state.pageSize));
104
+ params.append('offset', String(offset));
105
+ const response = await fetch(`/api/apps/search?${params}`);
106
+ if (!response.ok)
107
+ throw new Error('Failed to load more apps');
108
+ const json = await response.json();
109
+ const data = json.data || json;
110
+ this.setState({
111
+ apps: [...this.state.apps, ...(data.apps || [])],
112
+ page: nextPage,
113
+ isLoading: false,
114
+ });
115
+ }
116
+ catch (error) {
117
+ const errorMsg = error instanceof Error ? error.message : 'Unknown error';
118
+ console.error('Failed to load next page:', errorMsg);
119
+ this.setState({
120
+ error: errorMsg,
121
+ isLoading: false,
122
+ });
123
+ }
124
+ }
125
+ clearError() {
126
+ this.setState({ error: null });
127
+ }
128
+ }
129
+ export const appStore = new AppStore();
130
+ //# sourceMappingURL=appStore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"appStore.js","sourceRoot":"","sources":["../../../../src/ui/client/state/appStore.ts"],"names":[],"mappings":"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"}