Skip to content

Commit

Permalink
refactor: merged Recents and CharacterList into a single menu
Browse files Browse the repository at this point in the history
  • Loading branch information
Vali-98 committed Sep 19, 2024
1 parent 669c047 commit 118f8fa
Show file tree
Hide file tree
Showing 9 changed files with 357 additions and 155 deletions.
33 changes: 23 additions & 10 deletions app/CharInfo.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import AnimatedView from '@components/AnimatedView'
import { FontAwesome } from '@expo/vector-icons'
import { Characters, Logger, Style } from '@globals'
import { Characters, Chats, Logger, Style } from '@globals'
import { CharacterCardV2 } from 'app/constants/Characters'
import { RecentMessages } from 'app/constants/RecentMessages'
import { Tokenizer } from 'app/constants/Tokenizer'
import * as DocumentPicker from 'expo-document-picker'
import { Stack, useRouter } from 'expo-router'
import { useState } from 'react'
import { useEffect, useState } from 'react'
import { useAutosave } from 'react-autosave'
import {
View,
Expand All @@ -18,28 +18,41 @@ import {
Alert,
ScrollView,
TextInput,
BackHandler,
} from 'react-native'
import { useShallow } from 'zustand/react/shallow'

const CharInfo = () => {
const router = useRouter()
const { currentCard, setCurrentCard, charId, charName } = Characters.useCharacterCard(
useShallow((state) => ({
charId: state.id,
currentCard: state.card,
setCurrentCard: state.setCard,
charName: state.card?.data.name,
}))
)
const { currentCard, setCurrentCard, charId, charName, unloadCharacter } =
Characters.useCharacterCard(
useShallow((state) => ({
charId: state.id,
currentCard: state.card,
setCurrentCard: state.setCard,
charName: state.card?.data.name,
unloadCharacter: state.unloadCard,
}))
)
const getTokenCount = Tokenizer.useTokenizer((state) => state.getTokenCount)
const [characterCard, setCharacterCard] = useState<CharacterCardV2 | undefined>(currentCard)

const imageDir = Characters.getImageDir(currentCard?.data.image_id ?? -1)
const chat = Chats.useChat((state) => state.data)

const [imageSource, setImageSource] = useState({
uri: imageDir,
})

useEffect(() => {
const backAction = () => {
if (!chat) unloadCharacter()
return false
}
const handler = BackHandler.addEventListener('hardwareBackPress', backAction)
return () => handler.remove()
}, [])

const handleImageError = () => {
setImageSource(require('@assets/user.png'))
}
Expand Down
9 changes: 0 additions & 9 deletions app/_layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,6 @@ const Layout = () => {
}}>
<Stack.Screen name="index" options={{ animation: 'fade' }} />

<Stack.Screen
name="CharMenu"
options={{
animation: 'slide_from_right',
title: 'Characters',
animationDuration: 200,
}}
/>

<Stack.Screen
name="CharInfo"
options={{
Expand Down
213 changes: 167 additions & 46 deletions app/components/CharacterMenu/CharacterList.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { Characters, Logger } from '@globals'
import { useRouter, Stack, usePathname } from 'expo-router'
import { FontAwesome } from '@expo/vector-icons'
import { Characters, Logger, Style } from '@globals'
import { Stack, usePathname } from 'expo-router'
import { useEffect, useState } from 'react'
import { SafeAreaView, ScrollView } from 'react-native'
import { Gesture, GestureDetector } from 'react-native-gesture-handler'
import { runOnJS } from 'react-native-reanimated'
import { SafeAreaView, View, Text, StyleSheet, FlatList } from 'react-native'
import { TouchableOpacity } from 'react-native-gesture-handler'
import Animated, { SequencedTransition } from 'react-native-reanimated'

import CharacterListing from './CharacterListing'
import CharacterNewMenu from './CharacterNewMenu'
Expand All @@ -13,26 +14,64 @@ type CharInfo = {
name: string
id: number
image_id: number
last_modified: number
tags: string[]
latestSwipe?: string
latestName?: string
latestChat?: number
}

const CharacterList = () => {
const router = useRouter()
enum SortType {
RECENT,
ALPHABETICAL,
}

const sortModified = (item1: CharInfo, item2: CharInfo) => {
return item2.last_modified - item1.last_modified
}

const sortAlphabetical = (item1: CharInfo, item2: CharInfo) => {
return -item2.name.localeCompare(item1.name)
}

type SortButtonProps = {
sortType: SortType
currentSortType: SortType
label: string
onPress: () => void | Promise<void>
}

const SortButton: React.FC<SortButtonProps> = ({ sortType, currentSortType, label, onPress }) => {
return (
<TouchableOpacity
onPress={onPress}
style={sortType === currentSortType ? styles.sortButtonActive : styles.sortButton}>
<Text
style={
sortType === currentSortType
? styles.sortButtonTextActive
: styles.sortButtonText
}>
{label}
</Text>
</TouchableOpacity>
)
}

type CharacterListProps = {
showHeader: boolean
}

const CharacterList: React.FC<CharacterListProps> = ({ showHeader }) => {
'use no memo'
const [characterList, setCharacterList] = useState<CharInfo[]>([])
const [nowLoading, setNowLoading] = useState(false)

const goBack = () => router.back()

const gesture = Gesture.Fling()
.direction(1)
.onEnd(() => {
runOnJS(goBack)()
})
const [sortType, setSortType] = useState<SortType>(SortType.RECENT)

const getCharacterList = async () => {
try {
const list = await Characters.db.query.cardList('character')
const list = await Characters.db.query.cardList('character', 'modified')
setCharacterList(list)
} catch (error) {
Logger.log(`Could not retrieve characters.\n${error}`, true)
Expand All @@ -44,39 +83,121 @@ const CharacterList = () => {
}, [usePathname()])

return (
<GestureDetector gesture={gesture}>
<SafeAreaView style={{ paddingVertical: 16, paddingHorizontal: 8, flex: 1 }}>
<Stack.Screen
options={{
title: 'Characters',
headerRight: () => (
<CharacterNewMenu
nowLoading={nowLoading}
setNowLoading={setNowLoading}
getCharacterList={getCharacterList}
/>
),
}}
/>
<SafeAreaView style={{ paddingVertical: 16, paddingHorizontal: 8, flex: 1 }}>
<Stack.Screen
options={{
title: '',
...(showHeader
? {
headerRight: () => (
<CharacterNewMenu
nowLoading={nowLoading}
setNowLoading={setNowLoading}
getCharacterList={getCharacterList}
/>
),
}
: {}),
}}
/>
<View
style={{
flexDirection: 'row',
justifyContent: 'space-between',
paddingHorizontal: 16,
paddingBottom: 12,
}}>
<View
style={{
columnGap: 12,
flexDirection: 'row',
alignItems: 'center',
}}>
<Text style={{ color: Style.getColor('primary-text2'), fontSize: 16 }}>
Sort By
</Text>
<SortButton
sortType={SortType.RECENT}
currentSortType={sortType}
label="Recent"
onPress={() => {
setSortType(SortType.RECENT)
setCharacterList(characterList.sort(sortModified))
}}
/>
<SortButton
sortType={SortType.ALPHABETICAL}
currentSortType={sortType}
label="A-z"
onPress={() => {
setSortType(SortType.ALPHABETICAL)
setCharacterList(characterList.sort(sortAlphabetical))
}}
/>
</View>

<TouchableOpacity>
<FontAwesome name="search" color={Style.getColor('primary-text1')} size={28} />
</TouchableOpacity>
</View>

{characterList.length === 0 && <CharactersEmpty />}

{characterList.length === 0 && <CharactersEmpty />}

{characterList.length !== 0 && (
<ScrollView>
{characterList.map((character, index) => (
<CharacterListing
key={character.id}
index={index}
character={character}
nowLoading={nowLoading}
setNowLoading={setNowLoading}
/>
))}
</ScrollView>
)}
</SafeAreaView>
</GestureDetector>
{characterList.length !== 0 && (
/*<ScrollView>
{characterList.map((character, index) => (
<CharacterListing
key={character.id}
index={index}
character={character}
nowLoading={nowLoading}
showTags={false}
setNowLoading={setNowLoading}
/>
))}
</ScrollView>*/
<Animated.FlatList
itemLayoutAnimation={SequencedTransition}
data={characterList}
keyExtractor={(item) => item.id.toString()}
renderItem={({ item, index }) => (
<CharacterListing
key={item.id}
index={index}
character={item}
nowLoading={nowLoading}
showTags={false}
setNowLoading={setNowLoading}
/>
)}
/>
)}
</SafeAreaView>
)
}

export default CharacterList

const styles = StyleSheet.create({
sortButton: {
paddingHorizontal: 16,
paddingVertical: 8,
backgroundColor: Style.getColor('primary-surface2'),
borderRadius: 16,
},

sortButtonText: {
color: Style.getColor('primary-text2'),
},

sortButtonActive: {
paddingHorizontal: 16,
paddingVertical: 8,
backgroundColor: Style.getColor('primary-surface3'),
borderRadius: 16,
},

sortButtonTextActive: {
color: Style.getColor('primary-text1'),
},
})
Loading

0 comments on commit 118f8fa

Please sign in to comment.