Skip to content

Commit

Permalink
feat: added alt greetings to character editor. refactor: changed char…
Browse files Browse the repository at this point in the history
…acter card states to use typing inferred from db select
  • Loading branch information
Vali-98 committed Oct 19, 2024
1 parent a790509 commit cc26f41
Show file tree
Hide file tree
Showing 11 changed files with 299 additions and 124 deletions.
195 changes: 173 additions & 22 deletions app/CharacterEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import PopupMenu from '@components/PopupMenu'
import { useViewerState } from '@constants/AvatarViewer'
import { AntDesign } from '@expo/vector-icons'
import { Characters, Chats, Logger, Style } from '@globals'
import { CharacterCardV2 } from 'app/constants/Characters'
import { CharacterCardData } from 'app/constants/Characters'
import { Tokenizer } from 'app/constants/Tokenizer'
import * as DocumentPicker from 'expo-document-picker'
import { Stack, useNavigation, useRouter } from 'expo-router'
Expand All @@ -23,13 +23,13 @@ const ChracterEditor = () => {
charId: state.id,
currentCard: state.card,
setCurrentCard: state.setCard,
charName: state.card?.data.name,
charName: state.card?.name,
unloadCharacter: state.unloadCard,
}))
)

const getTokenCount = Tokenizer.useTokenizer((state) => state.getTokenCount)
const [characterCard, setCharacterCard] = useState<CharacterCardV2 | undefined>(currentCard)
const [characterCard, setCharacterCard] = useState<CharacterCardData | undefined>(currentCard)

const { chat, unloadChat } = Chats.useChat((state) => ({
chat: state.data,
Expand All @@ -40,6 +40,8 @@ const ChracterEditor = () => {

const [edited, setEdited] = useState(false)

const [altSwipeIndex, setAltSwipeIndex] = useState(0)

const editedBackAction = (exitCallback: () => void) => {
Alert.alert({
title: `Unsaved Changes`,
Expand All @@ -66,21 +68,27 @@ const ChracterEditor = () => {
}

const initialRender = useRef(true)

useEffect(() => {
if (edited) return
if (initialRender.current) {
initialRender.current = false
return
const removeListener = navigation.addListener('beforeRemove', (e) => {
if (!chat) unloadCharacter()
navigation.dispatch(e.data.action)
})
return () => removeListener()
}
setEdited(true)

navigation.addListener('beforeRemove', (e) => {
const removeListener = navigation.addListener('beforeRemove', (e) => {
e.preventDefault()
editedBackAction(() => {
if (!chat) unloadCharacter()
navigation.dispatch(e.data.action)
})
})
return () => removeListener()
}, [characterCard])

const savecard = async () => {
Expand Down Expand Up @@ -121,7 +129,7 @@ const ChracterEditor = () => {
{
label: 'Delete Image',
onPress: () => {
if (characterCard) Characters.deleteImage(characterCard.data.image_id)
if (characterCard) Characters.deleteImage(characterCard.image_id)
},
type: 'warning',
},
Expand All @@ -139,6 +147,55 @@ const ChracterEditor = () => {
})
}

const handleAddAltMessage = async () => {
if (!charId || !characterCard) return
const id = await Characters.db.mutate.addAltGreeting(charId)
await setCurrentCard(charId)

// optimistically update editor state

const greetings = [
...(characterCard?.alternate_greetings ?? []),
{ id: id, greeting: '', character_id: charId },
]
setCharacterCard({ ...characterCard, alternate_greetings: greetings })
if (characterCard.alternate_greetings.length !== 0) {
setAltSwipeIndex(altSwipeIndex + 1)
}
}

const deleteAltMessageRoutine = async () => {
const id = characterCard?.alternate_greetings[altSwipeIndex].id
if (!id || !charId) {
Logger.log('Error deleting swipe', true)
return
}
await Characters.db.mutate.deleteAltGreeting(id)
await setCurrentCard(charId)
const greetings = [...(characterCard?.alternate_greetings ?? [])].filter(
(item) => item.id !== id
)
setAltSwipeIndex(0)
setCharacterCard({ ...characterCard, alternate_greetings: greetings })
}

const handleDeleteAltMessage = async () => {
Alert.alert({
title: `Delete Alternate Message`,
description: `Are you sure you want to delete this alternate message? This cannot be undone.`,
buttons: [
{ label: 'Cancel' },
{
label: 'Delete',
onPress: async () => {
await deleteAltMessageRoutine()
},
type: 'warning',
},
],
})
}

return (
<FadeDownView style={styles.mainContainer}>
<Stack.Screen
Expand Down Expand Up @@ -180,9 +237,7 @@ const ChracterEditor = () => {
},
]}>
<Avatar
targetImage={Characters.getImageDir(
currentCard?.data.image_id ?? -1
)}
targetImage={Characters.getImageDir(currentCard?.image_id ?? -1)}
style={styles.avatar}
/>
<AntDesign
Expand Down Expand Up @@ -222,16 +277,16 @@ const ChracterEditor = () => {
onChangeText={(mes) => {
setCharacterCard({
...characterCard,
data: { ...characterCard.data, name: mes },
name: mes,
})
}}
value={characterCard?.data?.name}
value={characterCard?.name}
/>
</View>
</View>

<Text style={styles.boxText}>
Description Tokens: {getTokenCount(characterCard?.data?.description ?? '')}
Description Tokens: {getTokenCount(characterCard?.description ?? '')}
</Text>

<TextInput
Expand All @@ -242,10 +297,10 @@ const ChracterEditor = () => {
onChangeText={(mes) => {
setCharacterCard({
...characterCard,
data: { ...characterCard.data, description: mes },
description: mes,
})
}}
value={characterCard?.data?.description}
value={characterCard?.description}
/>

<Text style={styles.boxText}>First Message</Text>
Expand All @@ -256,13 +311,109 @@ const ChracterEditor = () => {
onChangeText={(mes) => {
setCharacterCard({
...characterCard,
data: { ...characterCard.data, first_mes: mes },
first_mes: mes,
})
}}
value={characterCard?.data?.first_mes}
value={characterCard?.first_mes}
numberOfLines={8}
/>

<View
style={{
flexDirection: 'row',
justifyContent: 'space-between',
marginTop: 24,
marginBottom: 12,
}}>
<Text style={{ color: Style.getColor('primary-text2') }}>
Alternate Greetings{' '}
{characterCard.alternate_greetings.length !== 0 && (
<Text
style={{
color: Style.getColor('primary-text2'),
}}>
{altSwipeIndex + 1} / {characterCard.alternate_greetings.length}
</Text>
)}
</Text>

<View style={{ flexDirection: 'row', columnGap: 32 }}>
<TouchableOpacity onPress={handleDeleteAltMessage}>
{characterCard.alternate_greetings.length !== 0 && (
<AntDesign
color={Style.getColor('destructive-brand')}
name="delete"
size={20}
/>
)}
</TouchableOpacity>
<TouchableOpacity
onPress={() => setAltSwipeIndex(Math.max(altSwipeIndex - 1, 0))}>
<AntDesign
color={Style.getColor(
altSwipeIndex === 0 ? 'primary-text3' : 'primary-text1'
)}
name="left"
size={20}
/>
</TouchableOpacity>
{altSwipeIndex === characterCard.alternate_greetings.length - 1 ||
characterCard.alternate_greetings.length === 0 ? (
<TouchableOpacity onPress={handleAddAltMessage}>
<AntDesign
color={Style.getColor('primary-text1')}
name="plus"
size={20}
/>
</TouchableOpacity>
) : (
<TouchableOpacity
onPress={() =>
setAltSwipeIndex(
Math.min(
altSwipeIndex + 1,
characterCard.alternate_greetings.length - 1
)
)
}>
<AntDesign
color={Style.getColor('primary-text1')}
name="right"
size={20}
/>
</TouchableOpacity>
)}
</View>
</View>

{characterCard.alternate_greetings.length !== 0 ? (
<TextInput
style={styles.input}
multiline
numberOfLines={2}
onChangeText={(mes) => {
const greetings = [...characterCard.alternate_greetings]
greetings[altSwipeIndex].greeting = mes
setCharacterCard({
...characterCard,
alternate_greetings: greetings,
})
}}
value={
characterCard?.alternate_greetings?.[altSwipeIndex].greeting ?? ''
}
/>
) : (
<Text
style={{
...styles.input,
color: Style.getColor('primary-text2'),
fontStyle: 'italic',
}}>
No Alernate Greetings
</Text>
)}

<Text style={styles.boxText}>Personality</Text>

<TextInput
Expand All @@ -272,10 +423,10 @@ const ChracterEditor = () => {
onChangeText={(mes) => {
setCharacterCard({
...characterCard,
data: { ...characterCard.data, personality: mes },
personality: mes,
})
}}
value={characterCard?.data?.personality}
value={characterCard?.personality}
/>

<Text style={styles.boxText}>Scenario</Text>
Expand All @@ -286,10 +437,10 @@ const ChracterEditor = () => {
onChangeText={(mes) => {
setCharacterCard({
...characterCard,
data: { ...characterCard.data, scenario: mes },
scenario: mes,
})
}}
value={characterCard?.data?.scenario}
value={characterCard?.scenario}
numberOfLines={3}
/>

Expand All @@ -301,10 +452,10 @@ const ChracterEditor = () => {
onChangeText={(mes) => {
setCharacterCard({
...characterCard,
data: { ...characterCard.data, mes_example: mes },
mes_example: mes,
})
}}
value={characterCard?.data?.mes_example}
value={characterCard?.mes_example}
numberOfLines={8}
/>
</ScrollView>
Expand Down
6 changes: 1 addition & 5 deletions app/components/ChatMenu/ChatEditPopup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const ChatEditPopup: React.FC<ChatEditPopupProps> = ({ item, setNowLoading, nowL

const { charName, charId } = Characters.useCharacterCard((state) => ({
charId: state.id,
charName: state.card?.data?.name ?? 'Unknown',
charName: state.card?.name ?? 'Unknown',
}))

const { deleteChat, loadChat, currentChatId, unloadChat } = Chats.useChat((state) => ({
Expand Down Expand Up @@ -107,26 +107,22 @@ const ChatEditPopup: React.FC<ChatEditPopupProps> = ({ item, setNowLoading, nowL
setShowRename(true)
menuRef.current?.close()
},
closeOnExit: true,
},
{
label: 'Export',
icon: 'download',
onPress: (menuRef) => handleExportChat(menuRef),
closeOnExit: true,
},
{
label: 'Clone',
icon: 'copy1',
onPress: handleCloneChat,
closeOnExit: true,
},
{
label: 'Delete',
icon: 'delete',
warning: true,
onPress: handleDeleteChat,
closeOnExit: true,
},
]}
/>
Expand Down
4 changes: 2 additions & 2 deletions app/components/ChatMenu/ChatInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@ const ChatInput = () => {

const { charName } = Characters.useCharacterCard(
useShallow((state) => ({
charName: state?.card?.data.name,
charName: state?.card?.name,
}))
)

const { userName } = Characters.useUserCard(
useShallow((state) => ({ userName: state.card?.data.name }))
useShallow((state) => ({ userName: state.card?.name }))
)

const [newMessage, setNewMessage] = useState<string>('')
Expand Down
8 changes: 4 additions & 4 deletions app/components/ChatMenu/ChatWindow/AvatarViewer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@ const AvatarViewer = ({ editorButton = true }) => {
}))

const { charName, charImageId } = Characters.useCharacterCard((state) => ({
charName: state.card?.data.name,
charImageId: state.card?.data.image_id,
charName: state.card?.name,
charImageId: state.card?.image_id,
}))

const { userName, userImageId } = Characters.useUserCard((state) => ({
userName: state.card?.data.name,
userImageId: state.card?.data.image_id,
userName: state.card?.name,
userImageId: state.card?.image_id,
}))

const [aspectRatio, setAspectRatio] = useState(1)
Expand Down
Loading

0 comments on commit cc26f41

Please sign in to comment.