Skip to content

Commit 18b45e0

Browse files
committed
feat(mobile): add dedicated search screen with liquid glass UI
1 parent 2a7d436 commit 18b45e0

File tree

5 files changed

+575
-71
lines changed

5 files changed

+575
-71
lines changed

apps/mobile/v1/app/_layout.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,10 @@ function NavigationContent() {
145145
name="settings"
146146
options={{ contentStyle: { backgroundColor: theme.colors.background } }}
147147
/>
148+
<Stack.Screen
149+
name="search"
150+
options={{ contentStyle: { backgroundColor: theme.colors.background } }}
151+
/>
148152
</Stack>
149153
</AppWrapper>
150154
</ErrorBoundary>

apps/mobile/v1/app/search.tsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { useLocalSearchParams } from 'expo-router';
2+
3+
import SearchScreen from '@/src/screens/Search';
4+
5+
export default function SearchRoute() {
6+
const params = useLocalSearchParams();
7+
8+
return (
9+
<SearchScreen
10+
initialQuery={params.query as string | undefined}
11+
/>
12+
);
13+
}

apps/mobile/v1/src/screens/FolderNotes/components/NotesList/NoteListItem.tsx

Lines changed: 88 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,9 @@ const NoteListItemComponent: React.FC<NoteListItemProps> = ({
120120
const folderPath = note.folderId ? folderPathsMap.get(note.folderId) || '' : '';
121121
const noteFolder = note.folderId ? foldersMap.get(note.folderId) : undefined;
122122

123+
// Check if swipe actions are needed
124+
const hasSwipeActions = Boolean(onDelete || onArchive);
125+
123126
// Render right swipe action (Delete - red)
124127
const renderRightActions = (prog: Reanimated.SharedValue<number>, drag: Reanimated.SharedValue<number>) => {
125128
// eslint-disable-next-line react-hooks/rules-of-hooks
@@ -216,6 +219,89 @@ const NoteListItemComponent: React.FC<NoteListItemProps> = ({
216219
);
217220
};
218221

222+
// Common note content JSX
223+
const noteContent = (
224+
<Pressable
225+
onPress={() => onPress(note.id)}
226+
onLongPress={() => onLongPress?.(note)}
227+
style={[styles.noteListItem, { backgroundColor, paddingHorizontal: 16 }]}
228+
android_ripple={{ color: mutedColor }}
229+
>
230+
<View style={styles.noteListRow}>
231+
{/* Note type icon on the left */}
232+
<View style={styles.noteTypeIconContainer}>
233+
{isDiagram ? (
234+
<MdiIcon path={mdiVectorSquare} size={20} color="#a855f7" />
235+
) : isCode ? (
236+
<SquareCode size={20} color={mutedForegroundColor} />
237+
) : isSheet ? (
238+
<MdiIcon path={mdiFileTableBoxOutline} size={20} color="#22c55e" />
239+
) : (
240+
<MdiIcon path={mdiTextBoxOutline} size={20} color="#f43f5e" />
241+
)}
242+
</View>
243+
244+
{/* Content on the right */}
245+
<View style={styles.noteListContent}>
246+
<View style={styles.noteListHeader}>
247+
<Text
248+
style={[styles.noteListTitle, { color: foregroundColor }]}
249+
numberOfLines={1}
250+
ellipsizeMode="tail"
251+
>
252+
{String(note.title || 'Untitled')}
253+
</Text>
254+
<View style={styles.noteListMeta}>
255+
{note.isPublished && (
256+
<Globe size={12} color="#f59e0b" style={{ marginRight: 8 }} />
257+
)}
258+
{((note.attachments?.length ?? 0) > 0 || (note.attachmentCount ?? 0) > 0) && (
259+
<View style={styles.attachmentBadge}>
260+
<View style={{ transform: [{ rotate: '45deg' }] }}>
261+
<Ionicons name="attach-outline" size={14} color="#3b82f6" />
262+
</View>
263+
<Text style={[styles.attachmentCount, { color: '#3b82f6' }]}>
264+
{note.attachments?.length || note.attachmentCount || 0}
265+
</Text>
266+
</View>
267+
)}
268+
{note.starred && (
269+
<Ionicons name="star" size={14} color="#f59e0b" style={{ marginRight: 8 }} />
270+
)}
271+
<Text style={[styles.noteListTime, { color: mutedForegroundColor }]}>
272+
{enhancedData?.formattedDate || ''}
273+
</Text>
274+
</View>
275+
</View>
276+
<Text
277+
style={[styles.noteListPreview, { color: mutedForegroundColor }]}
278+
numberOfLines={2}
279+
>
280+
{enhancedData?.preview || ''}
281+
</Text>
282+
{!folderId && folderPath && showFolderPaths && (
283+
<View style={styles.noteListFolderInfo}>
284+
<View style={[styles.noteListFolderDot, { backgroundColor: noteFolder?.color || '#6b7280' }]} />
285+
<Text style={[styles.noteListFolderPath, { color: mutedForegroundColor }]} numberOfLines={1}>
286+
{folderPath}
287+
</Text>
288+
</View>
289+
)}
290+
</View>
291+
</View>
292+
</Pressable>
293+
);
294+
295+
// If no swipe actions, render without Swipeable to avoid hooks issues
296+
if (!hasSwipeActions) {
297+
return (
298+
<View style={styles.noteListItemWrapper}>
299+
{noteContent}
300+
{!isLastItem && <View style={[styles.noteListDivider, { backgroundColor: borderColor, marginLeft: 48 }]} />}
301+
</View>
302+
);
303+
}
304+
219305
return (
220306
<View style={styles.noteListItemWrapper}>
221307
<Swipeable
@@ -225,7 +311,7 @@ const NoteListItemComponent: React.FC<NoteListItemProps> = ({
225311
leftThreshold={100}
226312
overshootRight={true}
227313
overshootLeft={canArchive}
228-
renderRightActions={renderRightActions}
314+
renderRightActions={onDelete ? renderRightActions : undefined}
229315
renderLeftActions={canArchive ? renderLeftActions : undefined}
230316
onSwipeableOpen={(direction) => {
231317
// Auto-execute action when fully swiped through
@@ -240,75 +326,7 @@ const NoteListItemComponent: React.FC<NoteListItemProps> = ({
240326
}
241327
}}
242328
>
243-
<Pressable
244-
onPress={() => onPress(note.id)}
245-
onLongPress={() => onLongPress?.(note)}
246-
style={[styles.noteListItem, { backgroundColor, paddingHorizontal: 16 }]}
247-
android_ripple={{ color: mutedColor }}
248-
>
249-
<View style={styles.noteListRow}>
250-
{/* Note type icon on the left */}
251-
<View style={styles.noteTypeIconContainer}>
252-
{isDiagram ? (
253-
<MdiIcon path={mdiVectorSquare} size={20} color="#a855f7" />
254-
) : isCode ? (
255-
<SquareCode size={20} color={mutedForegroundColor} />
256-
) : isSheet ? (
257-
<MdiIcon path={mdiFileTableBoxOutline} size={20} color="#22c55e" />
258-
) : (
259-
<MdiIcon path={mdiTextBoxOutline} size={20} color="#f43f5e" />
260-
)}
261-
</View>
262-
263-
{/* Content on the right */}
264-
<View style={styles.noteListContent}>
265-
<View style={styles.noteListHeader}>
266-
<Text
267-
style={[styles.noteListTitle, { color: foregroundColor }]}
268-
numberOfLines={1}
269-
ellipsizeMode="tail"
270-
>
271-
{String(note.title || 'Untitled')}
272-
</Text>
273-
<View style={styles.noteListMeta}>
274-
{note.isPublished && (
275-
<Globe size={12} color="#f59e0b" style={{ marginRight: 8 }} />
276-
)}
277-
{((note.attachments?.length ?? 0) > 0 || (note.attachmentCount ?? 0) > 0) && (
278-
<View style={styles.attachmentBadge}>
279-
<View style={{ transform: [{ rotate: '45deg' }] }}>
280-
<Ionicons name="attach-outline" size={14} color="#3b82f6" />
281-
</View>
282-
<Text style={[styles.attachmentCount, { color: '#3b82f6' }]}>
283-
{note.attachments?.length || note.attachmentCount || 0}
284-
</Text>
285-
</View>
286-
)}
287-
{note.starred && (
288-
<Ionicons name="star" size={14} color="#f59e0b" style={{ marginRight: 8 }} />
289-
)}
290-
<Text style={[styles.noteListTime, { color: mutedForegroundColor }]}>
291-
{enhancedData?.formattedDate || ''}
292-
</Text>
293-
</View>
294-
</View>
295-
<Text
296-
style={[styles.noteListPreview, { color: mutedForegroundColor }]}
297-
numberOfLines={2}
298-
>
299-
{enhancedData?.preview || ''}
300-
</Text>
301-
{!folderId && folderPath && showFolderPaths && (
302-
<View style={styles.noteListFolderInfo}>
303-
<View style={[styles.noteListFolderDot, { backgroundColor: noteFolder?.color || '#6b7280' }]} />
304-
<Text style={[styles.noteListFolderPath, { color: mutedForegroundColor }]} numberOfLines={1}>
305-
{folderPath}
306-
</Text>
307-
</View>
308-
)}
309-
</View>
310-
</View>
311-
</Pressable>
329+
{noteContent}
312330
</Swipeable>
313331

314332
{!isLastItem && <View style={[styles.noteListDivider, { backgroundColor: borderColor, marginLeft: 48 }]} />}

apps/mobile/v1/src/screens/Home/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -662,7 +662,7 @@ export default function HomeScreen() {
662662
<GlassView glassEffectStyle="regular" style={[styles.glassAvatar, { marginRight: 12, backgroundColor: theme.isDark ? 'rgba(255, 255, 255, 0.01)' : 'rgba(0, 0, 0, 0.01)' }]}>
663663
<TouchableOpacity
664664
style={styles.avatarButton}
665-
onPress={() => router.push('/folder-notes?viewType=all')}
665+
onPress={() => router.push('/search')}
666666
>
667667
<Ionicons name="search" size={20} color={theme.colors.foreground} />
668668
</TouchableOpacity>

0 commit comments

Comments
 (0)