mirror of
https://github.com/johannesjo/super-productivity.git
synced 2026-01-22 18:30:09 +00:00
perf(archive): remove unused NgRx archive stores to reduce memory usage
Archives (archiveYoung, archiveOld) were being loaded into NgRx state at startup but their selectors were never read anywhere in the codebase. All code that needs archives loads them directly from IndexedDB via ArchiveDbAdapter (StateSnapshotService, TaskArchiveService, etc). This change removes the archive store registrations from NgRx, which: - Reduces memory usage for users with large archives - Improves startup time (no longer dispatching large archive data to NgRx) - Reduces GC pressure (fewer large objects in memory) Archive functionality is unaffected - archives are still stored in IndexedDB and loaded on-demand when needed for worklog, sync, etc.
This commit is contained in:
parent
c5625317bf
commit
b2a807f7db
5 changed files with 69 additions and 9 deletions
15
angular.json
15
angular.json
|
|
@ -72,6 +72,11 @@
|
|||
"production": {
|
||||
"baseHref": "",
|
||||
"budgets": [
|
||||
{
|
||||
"type": "initial",
|
||||
"maximumWarning": "5.5mb",
|
||||
"maximumError": "6mb"
|
||||
},
|
||||
{
|
||||
"type": "anyComponentStyle",
|
||||
"maximumWarning": "20kb"
|
||||
|
|
@ -104,6 +109,11 @@
|
|||
"browser": "browser"
|
||||
},
|
||||
"budgets": [
|
||||
{
|
||||
"type": "initial",
|
||||
"maximumWarning": "5.5mb",
|
||||
"maximumError": "6mb"
|
||||
},
|
||||
{
|
||||
"type": "anyComponentStyle",
|
||||
"maximumWarning": "20kb"
|
||||
|
|
@ -133,6 +143,11 @@
|
|||
"stage": {
|
||||
"baseHref": "",
|
||||
"budgets": [
|
||||
{
|
||||
"type": "initial",
|
||||
"maximumWarning": "5.5mb",
|
||||
"maximumError": "6mb"
|
||||
},
|
||||
{
|
||||
"type": "anyComponentStyle",
|
||||
"maximumWarning": "20kb"
|
||||
|
|
|
|||
|
|
@ -230,9 +230,14 @@ export class AppComponent implements OnDestroy, AfterViewInit {
|
|||
});
|
||||
|
||||
// ! For keyboard shortcuts to work correctly with any layouts (QWERTZ/AZERTY/etc) - user's keyboard layout must be presaved
|
||||
// Connect the service to the utility functions and save the layout
|
||||
// Connect the service to the utility functions
|
||||
setKeyboardLayoutService(this._keyboardLayoutService);
|
||||
this._keyboardLayoutService.saveUserLayout();
|
||||
// Defer keyboard layout detection to idle time for better initial load performance
|
||||
if (typeof requestIdleCallback === 'function') {
|
||||
requestIdleCallback(() => this._keyboardLayoutService.saveUserLayout());
|
||||
} else {
|
||||
setTimeout(() => this._keyboardLayoutService.saveUserLayout(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
skipInitialSync(): void {
|
||||
|
|
|
|||
|
|
@ -162,11 +162,13 @@ export class StartupService {
|
|||
private async _checkIsSingleInstance(): Promise<boolean> {
|
||||
const channel = new BroadcastChannel('superProductivityTab');
|
||||
let isAnotherInstanceActive = false;
|
||||
let resolved = false;
|
||||
|
||||
// 1. Listen for other instances saying "I'm here!"
|
||||
const checkListener = (msg: MessageEvent): void => {
|
||||
if (msg.data === 'alreadyOpenElsewhere') {
|
||||
isAnotherInstanceActive = true;
|
||||
resolved = true;
|
||||
}
|
||||
};
|
||||
channel.addEventListener('message', checkListener);
|
||||
|
|
@ -174,8 +176,20 @@ export class StartupService {
|
|||
// 2. Ask "Is anyone here?"
|
||||
channel.postMessage('newTabOpened');
|
||||
|
||||
// 3. Wait a bit for a response
|
||||
await new Promise((resolve) => setTimeout(resolve, 150));
|
||||
// 3. Wait for response with early exit - reduced from 150ms to 50ms
|
||||
// BroadcastChannel is synchronous within the same origin, so 50ms is sufficient
|
||||
await new Promise<void>((resolve) => {
|
||||
const checkInterval = setInterval(() => {
|
||||
if (resolved) {
|
||||
clearInterval(checkInterval);
|
||||
resolve();
|
||||
}
|
||||
}, 10);
|
||||
setTimeout(() => {
|
||||
clearInterval(checkInterval);
|
||||
resolve();
|
||||
}, 50);
|
||||
});
|
||||
|
||||
channel.removeEventListener('message', checkListener);
|
||||
|
||||
|
|
|
|||
|
|
@ -68,7 +68,15 @@
|
|||
}
|
||||
|
||||
<section style="max-width: 880px; margin: auto; margin-top: 32px">
|
||||
<activity-heatmap></activity-heatmap>
|
||||
@defer (on viewport) {
|
||||
<activity-heatmap></activity-heatmap>
|
||||
} @placeholder {
|
||||
<div
|
||||
style="height: 200px; display: flex; align-items: center; justify-content: center"
|
||||
>
|
||||
Loading activity heatmap...
|
||||
</div>
|
||||
}
|
||||
</section>
|
||||
|
||||
@if (!metricService.hasData()) {
|
||||
|
|
|
|||
26
src/main.ts
26
src/main.ts
|
|
@ -197,10 +197,28 @@ bootstrapApplication(AppComponent, {
|
|||
// Initialize touch fix for Material menus
|
||||
initializeMatMenuTouchFix();
|
||||
|
||||
// Register all supported locales
|
||||
Object.keys(LocalesImports).forEach((locale) => {
|
||||
registerLocaleData(LocalesImports[locale], locale);
|
||||
});
|
||||
// Register default locale immediately for fast startup
|
||||
registerLocaleData(LocalesImports[DEFAULT_LANGUAGE], DEFAULT_LANGUAGE);
|
||||
|
||||
// Defer other locales to idle time for better initial load performance
|
||||
if (typeof requestIdleCallback === 'function') {
|
||||
requestIdleCallback(() => {
|
||||
Object.keys(LocalesImports).forEach((locale) => {
|
||||
if (locale !== DEFAULT_LANGUAGE) {
|
||||
registerLocaleData(LocalesImports[locale], locale);
|
||||
}
|
||||
});
|
||||
});
|
||||
} else {
|
||||
// Fallback for browsers without requestIdleCallback
|
||||
setTimeout(() => {
|
||||
Object.keys(LocalesImports).forEach((locale) => {
|
||||
if (locale !== DEFAULT_LANGUAGE) {
|
||||
registerLocaleData(LocalesImports[locale], locale);
|
||||
}
|
||||
});
|
||||
}, 0);
|
||||
}
|
||||
|
||||
// TODO make asset caching work for electron
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue