documentation-hub 5.7.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.
- package/.eslintrc.json +43 -0
- package/.github/workflows/build.yml +64 -0
- package/.github/workflows/ci.yml +39 -0
- package/.vscode/extensions.json +3 -0
- package/Current.md +97 -0
- package/DocHub_Image.png +0 -0
- package/README.md +666 -0
- package/USER_GUIDE.md +1173 -0
- package/Updater.md +311 -0
- package/build/256x256.png +0 -0
- package/build/512x512.png +0 -0
- package/build/app-update.yml +4 -0
- package/build/create-icon.js +208 -0
- package/build/icon.ico +0 -0
- package/build/icon.png +0 -0
- package/build/icon_1024x1024.png +0 -0
- package/dist/assets/Analytics-BpsG9895.js +1 -0
- package/dist/assets/Card-IAZin8kp.js +1 -0
- package/dist/assets/CurrentSession-B-rFkHvf.js +12 -0
- package/dist/assets/Dashboard-C_5gMb0q.js +1 -0
- package/dist/assets/Documents-CqZ25axS.js +1 -0
- package/dist/assets/Input-l89xwXBi.js +1 -0
- package/dist/assets/Reporting-DqdHJY_a.js +1 -0
- package/dist/assets/Search-XNbu5z_3.js +1 -0
- package/dist/assets/SessionManager-lH9hZfzH.js +1 -0
- package/dist/assets/Sessions-ClZOPYNc.js +1 -0
- package/dist/assets/Settings-DUEHGURa.js +11 -0
- package/dist/assets/index-8xUe8ptc.js +24 -0
- package/dist/assets/index-RYyJqF7O.css +1 -0
- package/dist/assets/path-BkOl0AGO.js +1 -0
- package/dist/assets/promises-ID_B9S-h.js +1 -0
- package/dist/assets/urlHelpers-TvgahX0r.js +1 -0
- package/dist/assets/useToast-yRSO1dkm.js +1 -0
- package/dist/assets/vendor-charts-RkGK5ROP.js +36 -0
- package/dist/assets/vendor-db-l0sNRNKZ.js +1 -0
- package/dist/assets/vendor-react-BVZ_anCF.js +4 -0
- package/dist/assets/vendor-search-Dw8P0qyA.js +1 -0
- package/dist/assets/vendor-ui-BU7NfluV.js +53 -0
- package/dist/electron/PowerAutomateApiService-LfW09ZGr.js +147 -0
- package/dist/electron/main-CXkNtyv-.js +19789 -0
- package/dist/electron/main.js +5 -0
- package/dist/electron/preload.js +1 -0
- package/dist/icon.png +0 -0
- package/dist/index.html +27 -0
- package/docs/CODEBASE_ANALYSIS_REPORT.md +309 -0
- package/docs/DEBUG_LOGGING_GUIDE.md +244 -0
- package/docs/README.md +115 -0
- package/docs/TOC_WIRING_GUIDE.md +344 -0
- package/docs/analysis/Bullet_Symbol_Bug_Analysis.md +136 -0
- package/docs/analysis/DOCXMLATER_ANALYSIS_SUMMARY.txt +169 -0
- package/docs/analysis/Document_Processing_Issues_Analysis.md +704 -0
- package/docs/analysis/FIELD_PRESERVATION_ANALYSIS.md +1200 -0
- package/docs/analysis/INDENTATION_PRESERVE_ANALYSIS.md +181 -0
- package/docs/analysis/INDENTATION_PRESERVE_IMPLEMENTATION.md +207 -0
- package/docs/analysis/List_Implementation.md +206 -0
- package/docs/analysis/List_Implementation_Accuracy_Report.md +366 -0
- package/docs/analysis/PROCESSING_OPTIONS_UI_UPDATES.md +220 -0
- package/docs/analysis/RefactorStyles.md +852 -0
- package/docs/analysis/STYLE_PARAMETER_ENHANCEMENT.md +143 -0
- package/docs/analysis/docxmlater-comparison-todo-2025-11-13.md +636 -0
- package/docs/analysis/docxmlater-implementation-analysis-2025-11-13.md +340 -0
- package/docs/analysis/docxmlater-template_ui-integration-analysis.md +263 -0
- package/docs/analysis/github-issues-to-create.md +237 -0
- package/docs/api/API_README.md +538 -0
- package/docs/api/API_REFERENCE.md +751 -0
- package/docs/api/TYPE_DEFINITIONS.md +869 -0
- package/docs/architecture/FONT_EMBEDDING_GUIDE.md +318 -0
- package/docs/architecture/docxmlater-functions-and-structure.md +726 -0
- package/docs/docxmlater-readme.md +1341 -0
- package/docs/fixes/EXECUTION_LOG_TEST_BASE.md +573 -0
- package/docs/fixes/HYPERLINK_TEXT_SANITIZATION.md +253 -0
- package/docs/fixes/README.md +37 -0
- package/docs/github-issues/issue-1-body.md +125 -0
- package/docs/github-issues/issue-10-body.md +850 -0
- package/docs/github-issues/issue-2-body.md +200 -0
- package/docs/github-issues/issue-3-body.md +270 -0
- package/docs/github-issues/issue-4-body.md +169 -0
- package/docs/github-issues/issue-5-body.md +173 -0
- package/docs/github-issues/issue-6-body.md +158 -0
- package/docs/github-issues/issue-7-body.md +171 -0
- package/docs/github-issues/issue-8-body.md +407 -0
- package/docs/github-issues/issue-9-body.md +515 -0
- package/docs/github-issues/issue-tracker.md +274 -0
- package/docs/github-issues/predictive-analysis-2025-10-18.md +2131 -0
- package/docs/implementation/List_Framework_Refactor_Plan.md +336 -0
- package/docs/implementation/PRIMARY_TEXT_COLOR_FEATURE.md +217 -0
- package/docs/implementation/RELEASE_PLAN_v2.1.0.md +362 -0
- package/docs/implementation/RefactorStyles.md +588 -0
- package/docs/implementation/implement-plan.md +489 -0
- package/docs/implementation/missing-helpers-implementation.md +391 -0
- package/docs/implementation/refactor-plan.md +520 -0
- package/docs/implementation/session-implementation-complete.md +233 -0
- package/docs/implementation/session-management-plan.md +250 -0
- package/docs/setup-checklist.md +77 -0
- package/docs/versions/changelog.md +345 -0
- package/electron/customUpdater.ts +656 -0
- package/electron/main.ts +2441 -0
- package/electron/memoryConfig.ts +187 -0
- package/electron/preload.ts +394 -0
- package/electron/proxyConfig.ts +340 -0
- package/electron/services/BackupService.ts +452 -0
- package/electron/services/DictionaryService.ts +402 -0
- package/electron/services/LocalDictionaryLookupService.ts +147 -0
- package/electron/services/PowerAutomateApiService.ts +231 -0
- package/electron/services/SharePointSyncService.ts +474 -0
- package/electron/windowsCertStore.ts +427 -0
- package/electron/zscalerConfig.ts +381 -0
- package/eslint.config.js +92 -0
- package/jest.config.js +52 -0
- package/package.json +214 -0
- package/postcss.config.mjs +6 -0
- package/public/icon.png +0 -0
- package/publish-release.ps1 +5 -0
- package/renovate.json +30 -0
- package/src/App.tsx +216 -0
- package/src/__mocks__/p-limit.js +12 -0
- package/src/__mocks__/styleMock.js +1 -0
- package/src/components/common/BugReportButton.tsx +44 -0
- package/src/components/common/BugReportDialog.tsx +193 -0
- package/src/components/common/Button.tsx +153 -0
- package/src/components/common/Card.tsx +86 -0
- package/src/components/common/ColorPickerDialog.tsx +177 -0
- package/src/components/common/ConfirmDialog.tsx +96 -0
- package/src/components/common/DebugConsole.tsx +275 -0
- package/src/components/common/EmptyState.tsx +183 -0
- package/src/components/common/ErrorBoundary.tsx +98 -0
- package/src/components/common/ErrorDetailsDialog.tsx +153 -0
- package/src/components/common/ErrorFallback.tsx +218 -0
- package/src/components/common/Input.tsx +109 -0
- package/src/components/common/Skeleton.tsx +184 -0
- package/src/components/common/SplashScreen.tsx +81 -0
- package/src/components/common/Toast.tsx +155 -0
- package/src/components/common/Tooltip.tsx +79 -0
- package/src/components/common/UpdateNotification.tsx +320 -0
- package/src/components/comparison/ComparisonWindow.tsx +374 -0
- package/src/components/comparison/SideBySideDiff.tsx +486 -0
- package/src/components/comparison/index.ts +8 -0
- package/src/components/document/DocumentUploader.tsx +288 -0
- package/src/components/document/HyperlinkPreview.tsx +430 -0
- package/src/components/document/HyperlinkService.md +1484 -0
- package/src/components/document/Hyperlink_Technical_Documentation.md +496 -0
- package/src/components/document/InlineChangesView.tsx +707 -0
- package/src/components/document/ProcessingProgress.tsx +303 -0
- package/src/components/document/ProcessingResults.tsx +256 -0
- package/src/components/document/TrackedChangesDetail.tsx +530 -0
- package/src/components/document/TrackedChangesPanel.tsx +546 -0
- package/src/components/document/VirtualDocumentList.tsx +240 -0
- package/src/components/editor/DocumentEditor.tsx +723 -0
- package/src/components/editor/DocumentEditorModal.tsx +640 -0
- package/src/components/editor/EditorQuickActions.tsx +502 -0
- package/src/components/editor/EditorToolbar.tsx +312 -0
- package/src/components/editor/TableEditor.tsx +926 -0
- package/src/components/editor/index.ts +18 -0
- package/src/components/layout/Header.tsx +190 -0
- package/src/components/layout/Sidebar.tsx +313 -0
- package/src/components/layout/TitleBar.tsx +190 -0
- package/src/components/navigation/CommandPalette.tsx +233 -0
- package/src/components/navigation/KeyboardShortcutsModal.tsx +173 -0
- package/src/components/sessions/ChangeItem.tsx +408 -0
- package/src/components/sessions/ChangeViewer.tsx +1155 -0
- package/src/components/sessions/DocumentComparisonModal.tsx +314 -0
- package/src/components/sessions/ProcessingOptions.tsx +297 -0
- package/src/components/sessions/ReplacementsTab.tsx +438 -0
- package/src/components/sessions/RevisionHandlingOptions.tsx +87 -0
- package/src/components/sessions/SessionManager.tsx +188 -0
- package/src/components/sessions/StylesEditor.tsx +1335 -0
- package/src/components/sessions/TabContainer.tsx +151 -0
- package/src/components/sessions/VirtualSessionList.tsx +157 -0
- package/src/components/sessions/sessionToProcessorManager.tsx +420 -0
- package/src/components/settings/CertificateManager.tsx +410 -0
- package/src/components/settings/SegmentedControl.tsx +88 -0
- package/src/components/settings/SettingRow.tsx +52 -0
- package/src/contexts/GlobalStatsContext.tsx +396 -0
- package/src/contexts/SessionContext.tsx +2129 -0
- package/src/contexts/ThemeContext.tsx +428 -0
- package/src/contexts/UserSettingsContext.tsx +290 -0
- package/src/contexts/__tests__/GlobalStatsContext.test.tsx +390 -0
- package/src/global.d.ts +273 -0
- package/src/hooks/useDocumentQueue.tsx +210 -0
- package/src/hooks/useToast.tsx +55 -0
- package/src/main.tsx +10 -0
- package/src/pages/Analytics.tsx +386 -0
- package/src/pages/CurrentSession.tsx +1174 -0
- package/src/pages/Dashboard.tsx +319 -0
- package/src/pages/Documents.tsx +317 -0
- package/src/pages/Projects.tsx +250 -0
- package/src/pages/Reporting.tsx +386 -0
- package/src/pages/Search.tsx +349 -0
- package/src/pages/Sessions.tsx +285 -0
- package/src/pages/Settings.tsx +2662 -0
- package/src/services/HyperlinkService.ts +1085 -0
- package/src/services/document/DocXMLaterProcessor.ts +617 -0
- package/src/services/document/DocumentProcessingComparison.ts +856 -0
- package/src/services/document/DocumentSnapshotService.ts +575 -0
- package/src/services/document/WordDocumentProcessor.ts +10509 -0
- package/src/services/document/__tests__/DocXMLaterProcessor.hyperlinks.test.md +311 -0
- package/src/services/document/__tests__/WordDocumentProcessor.integration.test.ts +515 -0
- package/src/services/document/__tests__/WordDocumentProcessor.test.ts +812 -0
- package/src/services/document/blanklines/BlankLineManager.ts +658 -0
- package/src/services/document/blanklines/__tests__/paragraphChecks.test.ts +281 -0
- package/src/services/document/blanklines/helpers/blankLineInsertion.ts +87 -0
- package/src/services/document/blanklines/helpers/blankLineSnapshot.ts +251 -0
- package/src/services/document/blanklines/helpers/clearCustom.ts +121 -0
- package/src/services/document/blanklines/helpers/contextChecks.ts +117 -0
- package/src/services/document/blanklines/helpers/imageChecks.ts +51 -0
- package/src/services/document/blanklines/helpers/paragraphChecks.ts +236 -0
- package/src/services/document/blanklines/helpers/removeBlanksBetweenListItems.ts +91 -0
- package/src/services/document/blanklines/helpers/removeTrailingBlanks.ts +35 -0
- package/src/services/document/blanklines/helpers/tableGuards.ts +21 -0
- package/src/services/document/blanklines/index.ts +67 -0
- package/src/services/document/blanklines/rules/additionRules.ts +337 -0
- package/src/services/document/blanklines/rules/indentationRules.ts +317 -0
- package/src/services/document/blanklines/rules/removalRules.ts +362 -0
- package/src/services/document/blanklines/rules/ruleTypes.ts +92 -0
- package/src/services/document/blanklines/types.ts +29 -0
- package/src/services/document/helpers/ImageBorderCropper.ts +377 -0
- package/src/services/document/helpers/__tests__/whitespace.test.ts +272 -0
- package/src/services/document/helpers/whitespace.ts +117 -0
- package/src/services/document/list/ListNormalizer.ts +947 -0
- package/src/services/document/list/index.ts +45 -0
- package/src/services/document/list/list-detection.ts +275 -0
- package/src/services/document/list/list-types.ts +162 -0
- package/src/services/document/processors/HyperlinkProcessor.ts +370 -0
- package/src/services/document/processors/ListProcessor.ts +257 -0
- package/src/services/document/processors/StructureProcessor.ts +176 -0
- package/src/services/document/processors/StyleProcessor.ts +389 -0
- package/src/services/document/processors/TableProcessor.ts +2238 -0
- package/src/services/document/processors/__tests__/HyperlinkProcessor.test.ts +314 -0
- package/src/services/document/processors/__tests__/ListProcessor.test.ts +291 -0
- package/src/services/document/processors/__tests__/StructureProcessor.test.ts +257 -0
- package/src/services/document/processors/__tests__/TableProcessor.hlp-tips-bullets.test.ts +459 -0
- package/src/services/document/processors/__tests__/TableProcessor.test.ts +1604 -0
- package/src/services/document/processors/index.ts +28 -0
- package/src/services/document/types/docx-processing.ts +310 -0
- package/src/services/editor/EditorActionHandlers.ts +901 -0
- package/src/services/editor/index.ts +13 -0
- package/src/setupTests.ts +47 -0
- package/src/styles/global.css +782 -0
- package/src/types/backup.ts +132 -0
- package/src/types/dictionary.ts +125 -0
- package/src/types/document-processing.ts +331 -0
- package/src/types/docxmlater-augments.d.ts +142 -0
- package/src/types/editor.ts +280 -0
- package/src/types/electron.ts +340 -0
- package/src/types/globalStats.ts +155 -0
- package/src/types/hyperlink.ts +471 -0
- package/src/types/operations.ts +354 -0
- package/src/types/session.ts +427 -0
- package/src/types/settings.ts +112 -0
- package/src/utils/MemoryMonitor.ts +248 -0
- package/src/utils/cn.ts +6 -0
- package/src/utils/colorConvert.ts +306 -0
- package/src/utils/diffUtils.ts +347 -0
- package/src/utils/documentUtils.ts +202 -0
- package/src/utils/electronGuard.ts +62 -0
- package/src/utils/indexedDB.ts +915 -0
- package/src/utils/logger.ts +717 -0
- package/src/utils/pathSecurity.ts +232 -0
- package/src/utils/pathValidator.ts +236 -0
- package/src/utils/processingTimeEstimator.ts +153 -0
- package/src/utils/safeJsonParse.ts +62 -0
- package/src/utils/textSanitizer.ts +162 -0
- package/src/utils/urlHelpers.ts +304 -0
- package/src/utils/urlPatterns.ts +198 -0
- package/src/utils/urlSanitizer.ts +152 -0
- package/src/vite-env.d.ts +11 -0
- package/tsconfig.electron.json +19 -0
- package/tsconfig.json +36 -0
- package/tsconfig.node.json +12 -0
- package/typedoc.json +45 -0
- package/vite.config.ts +152 -0
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
## Problem Description
|
|
2
|
+
|
|
3
|
+
**Type:** Bug (Infinite Re-render Loop)
|
|
4
|
+
**Priority:** High
|
|
5
|
+
**Likelihood:** 60%
|
|
6
|
+
**Impact:** App freeze/crash when theme color parsing fails
|
|
7
|
+
**Timeline:** 1-2 weeks (user enters invalid color value)
|
|
8
|
+
|
|
9
|
+
ThemeContext calls `setState` inside a `useEffect` error handler, which can trigger an infinite re-render loop when color parsing fails.
|
|
10
|
+
|
|
11
|
+
### Affected Files
|
|
12
|
+
|
|
13
|
+
- [`src/contexts/ThemeContext.tsx:203-268`](src/contexts/ThemeContext.tsx#L203-L268) - Custom color application with error handler
|
|
14
|
+
|
|
15
|
+
###Current Problematic Code
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
const root = window.document.documentElement;
|
|
20
|
+
|
|
21
|
+
if (useCustomColors) {
|
|
22
|
+
try {
|
|
23
|
+
root.setAttribute('data-custom-colors', 'true');
|
|
24
|
+
|
|
25
|
+
const foregroundColor = getContrastTextColor(customBackgroundColor);
|
|
26
|
+
root.style.setProperty('--custom-primary', hexToHSL(customPrimaryColor));
|
|
27
|
+
// ... more color applications
|
|
28
|
+
} catch (error) {
|
|
29
|
+
log.error('[ThemeContext] Error applying custom colors:', error);
|
|
30
|
+
|
|
31
|
+
// ❌ INFINITE LOOP TRAP!
|
|
32
|
+
setUseCustomColors(false); // Triggers useEffect again!
|
|
33
|
+
root.removeAttribute('data-custom-colors');
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}, [useCustomColors, customPrimaryColor, customBackgroundColor /* deps */]);
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## The Infinite Loop Scenario
|
|
40
|
+
|
|
41
|
+
**Step 1:** User enters invalid color (e.g., "#GGGGGG")
|
|
42
|
+
**Step 2:** useEffect runs, `hexToHSL("#GGGGGG")` throws error
|
|
43
|
+
**Step 3:** Catch block calls `setUseCustomColors(false)` → state change
|
|
44
|
+
**Step 4:** State change triggers useEffect again (dependency changed)
|
|
45
|
+
**Step 5:** If error persists (bad color in localStorage), loop continues
|
|
46
|
+
|
|
47
|
+
**Result:** React error: "Maximum update depth exceeded"
|
|
48
|
+
|
|
49
|
+
## Additional Issues
|
|
50
|
+
|
|
51
|
+
**Problem 2:** Multiple useEffect hooks modify same DOM element
|
|
52
|
+
|
|
53
|
+
7 separate useEffect hooks all modify `window.document.documentElement`:
|
|
54
|
+
|
|
55
|
+
- Theme application (light/dark)
|
|
56
|
+
- Accent color
|
|
57
|
+
- Custom colors
|
|
58
|
+
- Density
|
|
59
|
+
- Animations
|
|
60
|
+
- Blur effects
|
|
61
|
+
- Typography
|
|
62
|
+
|
|
63
|
+
All running simultaneously during initial mount = potential race conditions
|
|
64
|
+
|
|
65
|
+
**Problem 3:** No validation before applying colors
|
|
66
|
+
|
|
67
|
+
Colors applied directly without validation:
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
root.style.setProperty('--custom-primary', hexToHSL(customPrimaryColor));
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
If `hexToHSL()` throws, entire effect fails and triggers recovery via setState.
|
|
74
|
+
|
|
75
|
+
## Root Cause
|
|
76
|
+
|
|
77
|
+
1. **Error Recovery in useEffect:** Calling setState inside effect's error handler creates feedback loop
|
|
78
|
+
2. **No Color Validation:** Invalid colors aren't caught before attempting to apply
|
|
79
|
+
3. **Lack of Error Boundaries:** No fallback mechanism to prevent cascading failures
|
|
80
|
+
4. **Too Many Effects:** 7 separate hooks all modifying the same DOM element
|
|
81
|
+
|
|
82
|
+
## Evidence
|
|
83
|
+
|
|
84
|
+
**From Code Comments:**
|
|
85
|
+
|
|
86
|
+
- Line 232: "Disable custom colors on error to prevent cascading failures"
|
|
87
|
+
- Confirms failures have occurred
|
|
88
|
+
- The "fix" (setUseCustomColors) creates new problem
|
|
89
|
+
|
|
90
|
+
## Proposed Solution
|
|
91
|
+
|
|
92
|
+
**Solution 1: Validate colors before applying**
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
95
|
+
// NEW: Color validation utility
|
|
96
|
+
function isValidHexColor(color: string): boolean {
|
|
97
|
+
return /^#[0-9A-F]{6}$/i.test(color);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// REFACTORED: Validate in state setter, not in effect
|
|
101
|
+
const [customPrimaryColor, setCustomPrimaryColor] = useState<string>(() => {
|
|
102
|
+
const stored = localStorage.getItem('customPrimaryColor') || '#3b82f6';
|
|
103
|
+
return isValidHexColor(stored) ? stored : '#3b82f6'; // Validate on load
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
// Validate in setter
|
|
107
|
+
const updateCustomPrimaryColor = (color: string) => {
|
|
108
|
+
if (isValidHexColor(color)) {
|
|
109
|
+
setCustomPrimaryColor(color);
|
|
110
|
+
} else {
|
|
111
|
+
log.warn(`Invalid hex color: ${color}, using default`);
|
|
112
|
+
setCustomPrimaryColor('#3b82f6');
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
// Effect no longer needs error recovery
|
|
117
|
+
useEffect(() => {
|
|
118
|
+
const root = window.document.documentElement;
|
|
119
|
+
|
|
120
|
+
if (useCustomColors) {
|
|
121
|
+
// Safe to apply - already validated
|
|
122
|
+
const foregroundColor = getContrastTextColor(customBackgroundColor);
|
|
123
|
+
root.style.setProperty('--custom-primary', hexToHSL(customPrimaryColor));
|
|
124
|
+
}
|
|
125
|
+
}, [useCustomColors, customPrimaryColor, customBackgroundColor]);
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
**Solution 2: Consolidate effects**
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
// Instead of 7 separate useEffect hooks, use one coordinated effect
|
|
132
|
+
useEffect(() => {
|
|
133
|
+
const root = window.document.documentElement;
|
|
134
|
+
|
|
135
|
+
try {
|
|
136
|
+
applyTheme(root, theme, resolvedTheme);
|
|
137
|
+
applyAccentColor(root, accentColor, customAccentColor);
|
|
138
|
+
applyCustomColors(root, useCustomColors, { customPrimaryColor /* ... */ });
|
|
139
|
+
applyDensity(root, density);
|
|
140
|
+
applyAnimations(root, animations);
|
|
141
|
+
applyBlur(root, blur);
|
|
142
|
+
applyTypography(root, { fontSize, fontFamily /* ... */ });
|
|
143
|
+
} catch (error) {
|
|
144
|
+
log.error('[ThemeContext] Failed to apply theme:', error);
|
|
145
|
+
// DON'T call setState here - just log and use defaults
|
|
146
|
+
}
|
|
147
|
+
}, [theme, accentColor /* all deps */]);
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## Acceptance Criteria
|
|
151
|
+
|
|
152
|
+
- [ ] No `setState` calls inside useEffect error handlers
|
|
153
|
+
- [ ] All colors validated before applying to DOM
|
|
154
|
+
- [ ] Invalid colors in localStorage don't crash app
|
|
155
|
+
- [ ] No infinite re-render loops on theme errors
|
|
156
|
+
- [ ] Clear error messages when color validation fails
|
|
157
|
+
- [ ] Fallback to default theme on catastrophic failure
|
|
158
|
+
- [ ] All 7 theme aspects apply correctly
|
|
159
|
+
|
|
160
|
+
## Testing Strategy
|
|
161
|
+
|
|
162
|
+
1. **Invalid Color Test:** Enter "#ZZZZZZ", verify app doesn't crash, fallback applied
|
|
163
|
+
2. **Corrupted Storage Test:** Set invalid localStorage color, restart app, verify loads with default
|
|
164
|
+
3. **Rapid Change Test:** Change all settings rapidly (10 changes/second), verify no loop warnings
|
|
165
|
+
4. **Error Boundary Test:** Force hexToHSL() to throw, verify boundary catches, app remains usable
|
|
166
|
+
|
|
167
|
+
## Estimated Effort
|
|
168
|
+
|
|
169
|
+
**2 hours** (1 hour implementation + 1 hour testing)
|
|
170
|
+
|
|
171
|
+
## Research Reference
|
|
172
|
+
|
|
173
|
+
Full analysis: [`GH_Issues/scratchpads/predictive-analysis-2025-10-18.md`](../GH_Issues/scratchpads/predictive-analysis-2025-10-18.md#high-priority-issue-5-theme-context-infinite-loop-on-error)
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
## Problem Description
|
|
2
|
+
|
|
3
|
+
**Type:** Enhancement (UX Polish)
|
|
4
|
+
**Priority:** Medium
|
|
5
|
+
**Likelihood:** 40%
|
|
6
|
+
**Impact:** Unprofessional flicker/flash on startup
|
|
7
|
+
**Timeline:** **ALREADY HAPPENING** - visible on every launch
|
|
8
|
+
|
|
9
|
+
Main window is visible immediately on creation, showing black background before React loads.
|
|
10
|
+
|
|
11
|
+
### Affected Files
|
|
12
|
+
|
|
13
|
+
- [`electron/main.ts:365-395`](electron/main.ts#L365-L395) - Window creation without ready-to-show
|
|
14
|
+
|
|
15
|
+
### Current Implementation
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
async function createWindow() {
|
|
19
|
+
mainWindow = new BrowserWindow({
|
|
20
|
+
width: 1400,
|
|
21
|
+
height: 900,
|
|
22
|
+
minWidth: 800,
|
|
23
|
+
minHeight: 600,
|
|
24
|
+
frame: false,
|
|
25
|
+
titleBarStyle: 'hiddenInset',
|
|
26
|
+
backgroundColor: '#0a0a0a', // Dark gray
|
|
27
|
+
webPreferences: REQUIRED_SECURITY_SETTINGS,
|
|
28
|
+
// ❌ NO show: false option!
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
if (isDev) {
|
|
32
|
+
mainWindow.loadURL('http://localhost:5173'); // Shows immediately!
|
|
33
|
+
} else {
|
|
34
|
+
mainWindow.loadFile(join(__dirname, '../index.html'));
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// ❌ NO ready-to-show event handler!
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Comparison: Comparison Window (Correct Pattern)
|
|
42
|
+
|
|
43
|
+
Located at `electron/main.ts:657-693`:
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
const comparisonWindow = new BrowserWindow({
|
|
47
|
+
// ...
|
|
48
|
+
show: false, // Hidden initially!
|
|
49
|
+
backgroundColor: '#ffffff',
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
comparisonWindow.loadURL(/*...*/);
|
|
53
|
+
|
|
54
|
+
// Show only when ready!
|
|
55
|
+
comparisonWindow.once('ready-to-show', () => {
|
|
56
|
+
comparisonWindow.show();
|
|
57
|
+
});
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## User Experience Impact
|
|
61
|
+
|
|
62
|
+
**Current Behavior:**
|
|
63
|
+
|
|
64
|
+
- 0ms: User clicks app icon
|
|
65
|
+
- 50ms: Electron window appears (black screen)
|
|
66
|
+
- 1500ms: React finally renders UI
|
|
67
|
+
- **User sees:** 1.5 seconds of black screen
|
|
68
|
+
|
|
69
|
+
**Expected with Fix:**
|
|
70
|
+
|
|
71
|
+
- 0ms: User clicks app icon
|
|
72
|
+
- 0ms: Window created but hidden
|
|
73
|
+
- 1500ms: All providers initialized, React ready
|
|
74
|
+
- 1500ms: Window shows (smooth fade-in)
|
|
75
|
+
- **User sees:** Nothing until app is fully loaded
|
|
76
|
+
|
|
77
|
+
## Root Cause
|
|
78
|
+
|
|
79
|
+
1. `show: false` not set in BrowserWindowOptions
|
|
80
|
+
2. No `ready-to-show` event listener
|
|
81
|
+
3. No loading splash screen
|
|
82
|
+
|
|
83
|
+
## Proposed Solution
|
|
84
|
+
|
|
85
|
+
**Option 1: Hide until ready (Recommended)**
|
|
86
|
+
|
|
87
|
+
```typescript
|
|
88
|
+
async function createWindow() {
|
|
89
|
+
mainWindow = new BrowserWindow({
|
|
90
|
+
width: 1400,
|
|
91
|
+
height: 900,
|
|
92
|
+
minWidth: 800,
|
|
93
|
+
minHeight: 600,
|
|
94
|
+
frame: false,
|
|
95
|
+
titleBarStyle: 'hiddenInset',
|
|
96
|
+
backgroundColor: '#0a0a0a',
|
|
97
|
+
show: false, // Hide initially
|
|
98
|
+
webPreferences: REQUIRED_SECURITY_SETTINGS,
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
if (isDev) {
|
|
102
|
+
mainWindow.loadURL('http://localhost:5173');
|
|
103
|
+
} else {
|
|
104
|
+
mainWindow.loadFile(join(__dirname, '../index.html'));
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Show when content is ready
|
|
108
|
+
mainWindow.once('ready-to-show', () => {
|
|
109
|
+
mainWindow?.show();
|
|
110
|
+
|
|
111
|
+
// Optional: Fade in effect
|
|
112
|
+
mainWindow?.setOpacity(0);
|
|
113
|
+
let opacity = 0;
|
|
114
|
+
const fadeIn = setInterval(() => {
|
|
115
|
+
opacity += 0.1;
|
|
116
|
+
mainWindow?.setOpacity(opacity);
|
|
117
|
+
if (opacity >= 1) clearInterval(fadeIn);
|
|
118
|
+
}, 20); // 200ms total fade
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## Acceptance Criteria
|
|
124
|
+
|
|
125
|
+
- [ ] Window hidden until `ready-to-show` event fires
|
|
126
|
+
- [ ] No black screen visible during startup
|
|
127
|
+
- [ ] Smooth appearance of UI (optional: fade-in effect)
|
|
128
|
+
- [ ] Dev tools open correctly in development mode
|
|
129
|
+
- [ ] Window shows at correct size and position
|
|
130
|
+
- [ ] All window event handlers still work correctly
|
|
131
|
+
|
|
132
|
+
## Testing Strategy
|
|
133
|
+
|
|
134
|
+
1. **Cold Start Test:** Restart app 10 times, verify no black screen flicker
|
|
135
|
+
2. **Dev Mode Test:** Run `npm run dev`, verify dev tools open correctly
|
|
136
|
+
3. **Production Test:** Build app, test on fresh install and with existing data
|
|
137
|
+
|
|
138
|
+
## Estimated Effort
|
|
139
|
+
|
|
140
|
+
**30 minutes** (15 min implementation + 15 min testing)
|
|
141
|
+
|
|
142
|
+
## Priority Justification
|
|
143
|
+
|
|
144
|
+
**Why Medium (not High):**
|
|
145
|
+
|
|
146
|
+
- Purely cosmetic issue (doesn't affect functionality)
|
|
147
|
+
- Workaround exists (users can wait)
|
|
148
|
+
- Easy fix, low risk
|
|
149
|
+
|
|
150
|
+
**Why Not Low:**
|
|
151
|
+
|
|
152
|
+
- Affects every single app launch
|
|
153
|
+
- First impression matters (UX quality)
|
|
154
|
+
- Simple fix with big perceived improvement
|
|
155
|
+
|
|
156
|
+
## Research Reference
|
|
157
|
+
|
|
158
|
+
Full analysis: [`GH_Issues/scratchpads/predictive-analysis-2025-10-18.md`](../GH_Issues/scratchpads/predictive-analysis-2025-10-18.md#medium-priority-issue-6-main-window-shows-black-screen-on-startup)
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
## Problem Description
|
|
2
|
+
|
|
3
|
+
**Type:** Bug (Timing/Coordination)
|
|
4
|
+
**Priority:** Medium
|
|
5
|
+
**Likelihood:** 50%
|
|
6
|
+
**Impact:** Auto-update delayed by 5-10 seconds in corporate environments
|
|
7
|
+
**Timeline:** **ALREADY HAPPENING** - affects users behind proxies
|
|
8
|
+
|
|
9
|
+
Background certificate check and auto-updater initialize independently with no coordination, causing TLS failures when updater runs before certificates are validated.
|
|
10
|
+
|
|
11
|
+
### Affected Files
|
|
12
|
+
|
|
13
|
+
- [`electron/main.ts:576-607`](electron/main.ts#L576-L607) - Certificate check (runs at 500ms)
|
|
14
|
+
- [`electron/main.ts:1585-1595`](electron/main.ts#L1585-L1595) - Auto-updater (runs at 1000ms)
|
|
15
|
+
|
|
16
|
+
### Current Implementation
|
|
17
|
+
|
|
18
|
+
**Certificate Check:**
|
|
19
|
+
|
|
20
|
+
```typescript
|
|
21
|
+
app.whenReady().then(async () => {
|
|
22
|
+
await createWindow();
|
|
23
|
+
|
|
24
|
+
setImmediate(async () => {
|
|
25
|
+
await new Promise((resolve) => setTimeout(resolve, 500)); // ❌ Arbitrary delay
|
|
26
|
+
|
|
27
|
+
performPreflightCertificateCheck()
|
|
28
|
+
.then(() => {
|
|
29
|
+
// ... success handling
|
|
30
|
+
})
|
|
31
|
+
.catch((error) => {
|
|
32
|
+
// ... error handling
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
**Auto-Updater:**
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
app.whenReady().then(() => {
|
|
42
|
+
setTimeout(() => {
|
|
43
|
+
updaterHandler = new AutoUpdaterHandler(); // ❌ Might run before certs validated!
|
|
44
|
+
|
|
45
|
+
if (!isDev) {
|
|
46
|
+
updaterHandler.checkOnStartup(); // Immediately tries to connect
|
|
47
|
+
}
|
|
48
|
+
}, 1000); // ❌ Another arbitrary delay
|
|
49
|
+
});
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## The Race Condition
|
|
53
|
+
|
|
54
|
+
**Scenario 1: Certificate check wins (500ms < 1000ms)**
|
|
55
|
+
|
|
56
|
+
- Result: Works correctly
|
|
57
|
+
|
|
58
|
+
**Scenario 2: Certificate check is slow (network latency)**
|
|
59
|
+
|
|
60
|
+
- 500ms: Certificate check starts
|
|
61
|
+
- 1000ms: Auto-updater starts
|
|
62
|
+
- 1001ms: Update check fails with TLS error (certs not ready)
|
|
63
|
+
- 2000ms: Certificate check completes (too late!)
|
|
64
|
+
- Result: Auto-update fails, user doesn't get notified
|
|
65
|
+
|
|
66
|
+
**Scenario 3: Corporate proxy (high latency)**
|
|
67
|
+
|
|
68
|
+
- Both checks hang waiting for proxy auth
|
|
69
|
+
- Both timeout
|
|
70
|
+
- Result: Both fail, no updates available
|
|
71
|
+
|
|
72
|
+
## Impact Analysis
|
|
73
|
+
|
|
74
|
+
**Affected Users:**
|
|
75
|
+
|
|
76
|
+
- Corporate environments with Zscaler/proxy
|
|
77
|
+
- Users with slow network connections
|
|
78
|
+
- Users with SSL-intercepting firewalls
|
|
79
|
+
|
|
80
|
+
Based on extensive proxy configuration code (lines 51-313), this clearly affects a significant portion of users.
|
|
81
|
+
|
|
82
|
+
**User Experience:**
|
|
83
|
+
|
|
84
|
+
- Update notification should appear
|
|
85
|
+
- Instead: silence (update check failed)
|
|
86
|
+
- User never knows update is available
|
|
87
|
+
- Continues using old version with bugs
|
|
88
|
+
|
|
89
|
+
## Root Cause
|
|
90
|
+
|
|
91
|
+
1. **Independent Initialization:** Two `setTimeout` calls with arbitrary delays (500ms, 1000ms)
|
|
92
|
+
2. **No Synchronization:** Auto-updater doesn't wait for certificate validation
|
|
93
|
+
3. **Race Condition:** Which finishes first is unpredictable (network dependent)
|
|
94
|
+
4. **Silent Failure:** Failed update checks don't retry or notify user
|
|
95
|
+
|
|
96
|
+
## Proposed Solution
|
|
97
|
+
|
|
98
|
+
Make certificate validation a prerequisite for updater:
|
|
99
|
+
|
|
100
|
+
```typescript
|
|
101
|
+
app.whenReady().then(async () => {
|
|
102
|
+
// STEP 1: Create window first (user sees app immediately)
|
|
103
|
+
await createWindow();
|
|
104
|
+
|
|
105
|
+
// STEP 2: Background initialization (non-blocking for UI)
|
|
106
|
+
setImmediate(async () => {
|
|
107
|
+
try {
|
|
108
|
+
// STEP 2A: Validate certificates (BLOCKING for updater)
|
|
109
|
+
log.info('[Init] Validating certificates...');
|
|
110
|
+
await performPreflightCertificateCheck();
|
|
111
|
+
log.info('[Init] Certificates validated');
|
|
112
|
+
|
|
113
|
+
// Notify renderer
|
|
114
|
+
if (mainWindow && !mainWindow.isDestroyed()) {
|
|
115
|
+
mainWindow.webContents.send('certificate-check-complete', {
|
|
116
|
+
success: true,
|
|
117
|
+
timestamp: new Date().toISOString(),
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
} catch (error) {
|
|
121
|
+
log.error('[Init] Certificate validation failed:', error);
|
|
122
|
+
|
|
123
|
+
// Notify renderer of failure
|
|
124
|
+
if (mainWindow && !mainWindow.isDestroyed()) {
|
|
125
|
+
mainWindow.webContents.send('certificate-check-complete', {
|
|
126
|
+
success: false,
|
|
127
|
+
error: error.message,
|
|
128
|
+
timestamp: new Date().toISOString(),
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// STEP 2B: Initialize updater (AFTER certificates validated)
|
|
134
|
+
log.info('[Init] Initializing auto-updater...');
|
|
135
|
+
updaterHandler = new AutoUpdaterHandler(mainWindow);
|
|
136
|
+
|
|
137
|
+
if (!isDev) {
|
|
138
|
+
setTimeout(() => {
|
|
139
|
+
log.info('[Init] Checking for updates...');
|
|
140
|
+
updaterHandler.checkOnStartup();
|
|
141
|
+
}, 2000); // 2 second delay AFTER certs validated
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
log.info('[Init] Background initialization complete');
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## Acceptance Criteria
|
|
150
|
+
|
|
151
|
+
- [ ] Auto-updater only initializes AFTER certificate validation completes
|
|
152
|
+
- [ ] No race condition between certificate check and update check
|
|
153
|
+
- [ ] Failed certificate validation delays updater (doesn't crash it)
|
|
154
|
+
- [ ] Update checks succeed in corporate proxy environments
|
|
155
|
+
- [ ] User gets notified of available updates within 5 seconds
|
|
156
|
+
- [ ] Failed update checks retry with exponential backoff
|
|
157
|
+
|
|
158
|
+
## Testing Strategy
|
|
159
|
+
|
|
160
|
+
1. **Normal Network Test:** Verify update notification appears within 5 seconds
|
|
161
|
+
2. **Slow Network Test:** Add 3s latency, verify updater waits for certificates
|
|
162
|
+
3. **Corporate Proxy Test:** Test with Zscaler/proxy configuration
|
|
163
|
+
4. **Certificate Failure Test:** Block GitHub certificates, verify updater doesn't crash
|
|
164
|
+
|
|
165
|
+
## Estimated Effort
|
|
166
|
+
|
|
167
|
+
**1 hour** (30 min implementation + 30 min testing)
|
|
168
|
+
|
|
169
|
+
## Research Reference
|
|
170
|
+
|
|
171
|
+
Full analysis: [`GH_Issues/scratchpads/predictive-analysis-2025-10-18.md`](../GH_Issues/scratchpads/predictive-analysis-2025-10-18.md#medium-priority-issue-7-certificate-check-delays-auto-update)
|