@@ -5,65 +5,116 @@ import { useEffect } from "react";
55import { useAppStorage } from "../contexts/AppStorageContext" ;
66import PaginatedResults from "../components/PaginatedResults" ;
77import AccordionGroup from "../components/AccordionGroup" ;
8- import Icon from "react-native-vector-icons/Ionicons" ;
98import { useSearch } from "../contexts/SearchContext" ;
10- import { Skeleton } from "../components/Skeleton" ;
11- import { HEXA } from "../lib/colors" ;
129import LoadingSkeleton from "../components/LoadingSkeleton" ;
10+ import Toast from "react-native-toast-message" ;
1311
1412export default function Home ( ) {
1513 const { setRightSidebarKey } = useRightSidebar ( ) ;
16- const { viewMode } = useAppStorage ( ) ;
17- const { normalized, isLoading, error, setIsLoading } = useSearch ( ) ;
14+ const { viewMode, lastSearch, setLastSearch } = useAppStorage ( ) ;
15+ const { normalized, isLoading, error } = useSearch ( ) ;
16+ const { theme, themeMode, accentKey, accentColors } = useTheme ( ) ;
1817
18+ // Save the *normalized* result to storage when it becomes available.
19+ // (We intentionally DO NOT write lastSearch when it's null/undefined)
20+ useEffect ( ( ) => {
21+ if ( ! normalized ) return ;
22+ // do a cheap equality check — stringify is simple and enough here
23+ try {
24+ const normStr = JSON . stringify ( normalized ) ;
25+ const lastStr = JSON . stringify ( lastSearch ) ;
26+ if ( normStr === lastStr ) return ; // no change -> don't write
27+ } catch ( e ) {
28+ // fallback: if stringify fails, still write once
29+ }
30+ setLastSearch ( normalized ) ;
31+ } , [ normalized , lastSearch , setLastSearch ] ) ;
32+
33+ // set right sidebar key for this page
1934 useEffect ( ( ) => {
2035 setRightSidebarKey ( "home" ) ;
2136 return ( ) => setRightSidebarKey ( null ) ;
22- } , [ ] ) ;
37+ } , [ setRightSidebarKey ] ) ;
38+
39+ // show toast when there's an error (still allow fallback rendering)
40+ useEffect ( ( ) => {
41+ if ( error ) {
42+ Toast . show ( {
43+ type : "error" ,
44+ position : "top" ,
45+ text1 : "Error" ,
46+ text2 : String ( error ) ,
47+ text2Style : { fontSize : 16 } ,
48+ visibilityTime : 4000 ,
49+ autoHide : true ,
50+ } ) ;
51+ }
52+ } , [ error ] ) ;
2353
24- // setIsLoading(true);
54+ // Determine source to render: prefer live normalized results, otherwise use lastSearch
55+ const source = normalized ?? lastSearch ?? null ;
56+ const displayType = normalized ?. type ?? lastSearch ?. type ?? null ;
2557
26- if ( ! isLoading && ! error && ! normalized ) {
58+ // Loading state (use displayType to let skeleton adjust)
59+ if ( isLoading ) {
60+ return (
61+ < ScrollView
62+ showsVerticalScrollIndicator = { false }
63+ style = { [ styles . container ] }
64+ >
65+ < LoadingSkeleton viewMode = { viewMode } displayType = { displayType } />
66+ </ ScrollView >
67+ ) ;
68+ }
69+
70+ // No results at all (initial empty state)
71+ if ( ! source ) {
2772 return (
2873 < View style = { [ styles . container , { alignItems : "center" , marginTop : 40 } ] } >
29- < Icon name = "search-off" size = { 48 } color = "#999" />
30- < Text > Begin Search</ Text >
74+ < Text
75+ style = { [
76+ {
77+ color : theme . textSecondary ,
78+ fontWeight : "bold" ,
79+ fontSize : 40 ,
80+ letterSpacing : 3 ,
81+ } ,
82+ ] }
83+ >
84+ Your Search Results Appear Here.
85+ </ Text >
3186 </ View >
3287 ) ;
3388 }
89+
90+ // If we have a source (normalized or lastSearch) — render it.
91+ // It should match the shape you expect (bulk vs single)
3492 return (
3593 < ScrollView showsVerticalScrollIndicator = { false } style = { [ styles . container ] } >
36- { }
37- { }
38- { isLoading ? (
39- < LoadingSkeleton viewMode = { viewMode } displayType = { normalized ?. type } />
40- ) : error ? (
41- < Text style = { { color : "red" } } > { error } </ Text >
42- ) : ! isLoading && ! normalized ? (
43- < Text > Enter a query and press Enter</ Text >
44- ) : (
45- < View >
46- { /* <ScrollView style={{ padding: 16 }}> */ }
47-
48- { normalized ?. type === "bulk" ? (
49- normalized ?. blocks . map ( ( block ) => (
50- < AccordionGroup
51- key = { block . search_term . query }
52- block = { block }
53- pageSize = { 9 }
54- viewMode = { viewMode }
55- />
56- ) )
57- ) : (
58- < PaginatedResults
59- style = { styles . searchResults }
60- songs = { normalized ?. items }
61- pageSize = { 12 }
94+ < View >
95+ { source . type === "bulk" ? (
96+ // bulk blocks: if lastSearch was saved it should have the same `blocks` structure
97+ source . blocks ?. map ( ( block ) => (
98+ < AccordionGroup
99+ key = {
100+ block . search_term ?. query ??
101+ Math . random ( ) . toString ( 36 ) . slice ( 2 , 9 )
102+ }
103+ block = { block }
104+ pageSize = { 9 }
62105 viewMode = { viewMode }
63106 />
64- ) }
65- </ View >
66- ) }
107+ ) )
108+ ) : (
109+ // single search: normalized.items or lastSearch.items
110+ < PaginatedResults
111+ style = { styles . searchResults }
112+ songs = { source . items ?? [ ] }
113+ pageSize = { 12 }
114+ viewMode = { viewMode }
115+ />
116+ ) }
117+ </ View >
67118 </ ScrollView >
68119 ) ;
69120}
0 commit comments