Skip to content

Commit a3ca6e1

Browse files
committed
fix(mobile): cache management, editor spacing, and UX improvements
1 parent a5a6fb9 commit a3ca6e1

File tree

4 files changed

+135
-2
lines changed

4 files changed

+135
-2
lines changed

apps/mobile/v1/editor/src/components/Editor.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,11 +127,17 @@ const createEditorHTML = (content: string, placeholder: string, isDark: boolean,
127127
128128
/* Paragraphs */
129129
p {
130-
margin: 0 0 8px 0;
130+
margin: 0;
131+
line-height: 1.6;
131132
}
132133
133-
/* Empty paragraphs should show as spacing */
134+
/* Empty paragraphs should show as single line */
134135
p:empty {
136+
min-height: 1em;
137+
}
138+
139+
/* First empty paragraph in editor gets slightly more height for better UX */
140+
#editor > p:first-child:empty {
135141
min-height: 1.6em;
136142
}
137143

apps/mobile/v1/src/screens/SettingsScreen.tsx

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ import { APP_VERSION } from '../constants/version';
1414
import { forceGlobalMasterPasswordRefresh } from '../hooks/useMasterPassword';
1515
import { clearUserEncryptionData } from '../lib/encryption';
1616
import { clearDecryptedCache,getCacheDecryptedContentPreference, setCacheDecryptedContentPreference } from '../lib/preferences';
17+
import { apiCache } from '../services/api/cache';
18+
import { clearAllCacheMetadata, clearCachedFolders, clearCachedNotes } from '../services/api/databaseCache';
1719
import { useTheme } from '../theme';
1820
import { DARK_THEME_PRESETS,LIGHT_THEME_PRESETS } from '../theme/presets';
1921

@@ -121,6 +123,43 @@ export default function SettingsScreen({ onLogout }: Props) {
121123
}
122124
};
123125

126+
const handleClearCache = async () => {
127+
Alert.alert(
128+
'Clear Cache',
129+
'This will clear all cached data. Your notes and folders will be synced from the server on next load.',
130+
[
131+
{ text: 'Cancel', style: 'cancel' },
132+
{
133+
text: 'Clear',
134+
style: 'destructive',
135+
onPress: async () => {
136+
try {
137+
// Clear in-memory API cache
138+
apiCache.clearAll();
139+
140+
// Clear SQLite cached data
141+
await clearCachedFolders();
142+
await clearCachedNotes();
143+
await clearAllCacheMetadata();
144+
145+
// Clear decrypted cache
146+
await clearDecryptedCache();
147+
148+
if (__DEV__) {
149+
console.log('[Settings] All caches cleared successfully');
150+
}
151+
152+
Alert.alert('Success', 'Cache cleared successfully. Pull to refresh to reload your data.');
153+
} catch (error) {
154+
Alert.alert('Error', 'Failed to clear cache. Please try again.');
155+
if (__DEV__) console.error('Clear cache error:', error);
156+
}
157+
}
158+
}
159+
]
160+
);
161+
};
162+
124163
const handleResetMasterPassword = async () => {
125164
Alert.alert(
126165
'Change Master Password',
@@ -224,6 +263,12 @@ export default function SettingsScreen({ onLogout }: Props) {
224263
icon: 'sync-outline',
225264
onPress: undefined,
226265
},
266+
{
267+
title: 'Clear Cache',
268+
subtitle: 'Clear all cached data',
269+
icon: 'trash-bin-outline',
270+
onPress: handleClearCache,
271+
},
227272
],
228273
},
229274
{

apps/mobile/v1/src/services/api/databaseCache.ts

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,3 +417,75 @@ export async function storeCachedFolders(folders: Folder[]): Promise<void> {
417417
console.error('[DatabaseCache] Failed to store cached folders:', error);
418418
}
419419
}
420+
421+
/**
422+
* Clear all cached folders from database
423+
* Called when invalidating folder cache to ensure stale data is removed
424+
*/
425+
export async function clearCachedFolders(): Promise<void> {
426+
try {
427+
const db = getDatabase();
428+
429+
await db.runAsync(`DELETE FROM folders`);
430+
431+
if (__DEV__) {
432+
console.log('[DatabaseCache] Cleared all cached folders');
433+
}
434+
} catch (error) {
435+
if (error instanceof Error && error.message.includes('Database not initialized')) {
436+
if (__DEV__) {
437+
console.log('[DatabaseCache] Database not ready yet, skipping folders clear');
438+
}
439+
return;
440+
}
441+
console.error('[DatabaseCache] Failed to clear cached folders:', error);
442+
}
443+
}
444+
445+
/**
446+
* Clear all cached notes from database
447+
* Called when clearing all caches
448+
*/
449+
export async function clearCachedNotes(): Promise<void> {
450+
try {
451+
const db = getDatabase();
452+
453+
await db.runAsync(`DELETE FROM notes`);
454+
455+
if (__DEV__) {
456+
console.log('[DatabaseCache] Cleared all cached notes');
457+
}
458+
} catch (error) {
459+
if (error instanceof Error && error.message.includes('Database not initialized')) {
460+
if (__DEV__) {
461+
console.log('[DatabaseCache] Database not ready yet, skipping notes clear');
462+
}
463+
return;
464+
}
465+
console.error('[DatabaseCache] Failed to clear cached notes:', error);
466+
}
467+
}
468+
469+
/**
470+
* Clear all cache metadata
471+
* Called when clearing all caches
472+
*/
473+
export async function clearAllCacheMetadata(): Promise<void> {
474+
try {
475+
const db = getDatabase();
476+
477+
await db.runAsync(`DELETE FROM cache_metadata`);
478+
479+
if (__DEV__) {
480+
console.log('[DatabaseCache] Cleared all cache metadata');
481+
}
482+
} catch (error) {
483+
if (error instanceof Error && error.message.includes('Database not initialized')) {
484+
if (__DEV__) {
485+
console.log('[DatabaseCache] Database not ready yet, skipping metadata clear');
486+
}
487+
return;
488+
}
489+
console.error('[DatabaseCache] Failed to clear cache metadata:', error);
490+
}
491+
}

apps/mobile/v1/src/services/api/folders.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { isOnline } from '../network/networkManager';
77
import { apiCache, CACHE_KEYS, CACHE_TTL } from './cache';
88
import { AuthTokenGetter, createHttpClient, NotModifiedError } from './client';
99
import {
10+
clearCachedFolders,
1011
getCachedFolders,
1112
getCacheMetadata,
1213
invalidateCache,
@@ -189,6 +190,9 @@ export function createFoldersApi(getToken: AuthTokenGetter) {
189190
body: JSON.stringify({ name, color, parentId }),
190191
});
191192

193+
// Clear cached folder data from SQLite database
194+
await clearCachedFolders();
195+
192196
// Invalidate both memory and database caches
193197
apiCache.clear(CACHE_KEYS.FOLDERS);
194198
await invalidateCache('folders');
@@ -213,6 +217,9 @@ export function createFoldersApi(getToken: AuthTokenGetter) {
213217
body: JSON.stringify(updates),
214218
});
215219

220+
// Clear cached folder data from SQLite database
221+
await clearCachedFolders();
222+
216223
// Invalidate both memory and database caches
217224
apiCache.clear(CACHE_KEYS.FOLDERS);
218225
await invalidateCache('folders');
@@ -236,6 +243,9 @@ export function createFoldersApi(getToken: AuthTokenGetter) {
236243
method: 'DELETE',
237244
});
238245

246+
// Clear cached folder data from SQLite database
247+
await clearCachedFolders();
248+
239249
// Invalidate both memory and database caches
240250
apiCache.clear(CACHE_KEYS.FOLDERS);
241251
await invalidateCache('folders');

0 commit comments

Comments
 (0)