-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathApp.tsx
103 lines (85 loc) · 3.24 KB
/
App.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
import { FlatList, SafeAreaView, View } from 'react-native';
import { Button, TextInput } from 'react-native-paper';
import { TailwindProvider, useTailwind } from 'tailwind-rn';
import utilities from './tailwind.json';
import Card from './src/card';
import { useEffect, useRef, useState } from 'react';
import { DataClient, FakeDataClient } from './src/clients/data-client';
import { CARD_BATCH_SIZE, CARD_GAP } from './src/shared/utils';
import type { CardData, Theme } from './src/shared/types';
import { LocalServerThemeClient, ThemeClient } from './src/clients/theme-client';
const cardClient: DataClient = new FakeDataClient();
const themeClient: ThemeClient = new LocalServerThemeClient();
export default function App() {
return (
<TailwindProvider utilities={utilities}>
<AppImpl />
</TailwindProvider>
)
}
function AppImpl() {
const [cardData, setCardData] = useState<CardData[]>([]);
const [themeQuery, setThemeQuery] = useState('');
const [isLoadingTheme, setIsLoadingTheme] = useState(false);
const theme = useRef<Theme>({colors: ['200,200,200', '150,150,150'], iconUris: []});
const cancelCardLoads = useRef(false);
const isLoadingCards = useRef(false);
const tailwind = useTailwind();
useEffect(() => {
loadCards(CARD_BATCH_SIZE * 2);
return () => { cancelCardLoads.current = true };
}, []);
async function loadCards(batchSize: number = CARD_BATCH_SIZE) {
if (isLoadingCards.current) {
return;
}
isLoadingCards.current = true;
const newCardBodies = await cardClient.getCardContent('any cursor', batchSize);
isLoadingCards.current = false;
const nextId = cardData.length;
const newCardData: CardData[] = [];
for (let i = 0; i < newCardBodies.length; i++) {
const body = newCardBodies[i];
const newCard = {
id: nextId + i,
theme: theme.current,
content: {body},
}
newCardData.push(newCard);
}
if (cancelCardLoads.current) {
return;
}
setCardData([...cardData, ...newCardData]);
}
async function requestTheme() {
setIsLoadingTheme(true);
try {
theme.current = await themeClient.getThemeForPrompt(themeQuery);
setThemeQuery('');
} catch (e) {
console.error(`Failed to reach AI backend or parse response. Error:\n${e}`);
} finally {
setIsLoadingTheme(false);
}
}
function handleEndReached() {
loadCards();
}
return (
<SafeAreaView style={{...tailwind("flex-col flex-1 items-stretch justify-start"), paddingTop: 12, gap: 16}}>
<View style={{...tailwind("flex-col items-center"), gap: 8}}>
<TextInput label="Theme prompt" value={themeQuery} onChangeText={setThemeQuery} placeholder="Space" />
<Button onPress={requestTheme} mode='contained' disabled={isLoadingTheme}>Update Visual Theme</Button>
</View>
<FlatList
data={cardData}
renderItem={({item}) => <Card key={item.id} theme={item.theme} content={item.content} />}
keyExtractor={item => String(item.id)}
contentContainerStyle={{ ...tailwind("flex-col flex-1 items-stretch justify-start" ), gap: CARD_GAP }}
scrollEventThrottle={20}
onEndReached={handleEndReached}
onEndReachedThreshold={1} />
</SafeAreaView>
);
}