chore: save wip changes

This commit is contained in:
2026-06-20 16:07:12 +01:00
parent 2e6cae4d02
commit 25713ef614
11 changed files with 275 additions and 199 deletions

View File

@@ -1,5 +1,7 @@
import { BlurView } from "expo-blur"
import { GlassView } from "expo-glass-effect"
import { Link } from "expo-router"
import { Pressable } from "react-native"
import { Pressable, View, Text, TextInput } from "react-native"
import { SafeAreaView } from "react-native-safe-area-context"
import tw from "twrnc"
@@ -11,7 +13,9 @@ import { SerifText } from "@/components/ui/serif-text"
export default function HomeScreen() {
return (
<SafeAreaView style={tw`bg-stone-100 dark:bg-stone-900 flex-1 px-5 pt-6 gap-4`}>
<SafeAreaView
style={tw`bg-stone-100 dark:bg-stone-900 flex-1 px-5 pt-6 gap-4 relative dark:text-stone-100`}
>
<FeedCard>
<SerifText style={tw`text-4xl`}>Hello world asdsadsa</SerifText>
<SansSerifText style={tw`text-4xl font-bold`}>Hello world</SansSerifText>
@@ -23,6 +27,17 @@ export default function HomeScreen() {
<SansSerifText style={tw`text-teal-600`}>View component library</SansSerifText>
</Pressable>
</Link>
<View style={tw`absolute bottom-10 left-0 right-0 px-3`}>
<BlurView
style={tw`flex flex-row w-full py-2 pl-4 pr-2 bg-stone-800 border border-stone-700 rounded-full overflow-hidden`}
>
<TextInput
style={tw`text-stone-300 dark:text-stone-200 flex-1`}
placeholder="Message Freya..."
/>
<Button style={tw`size-8 p-0`} leadingIcon={<Button.Icon name="arrow-up" />} />
</BlurView>
</View>
</SafeAreaView>
)
}

View File

@@ -15,7 +15,7 @@ function ButtonIcon({ name }: ButtonIconProps) {
}
type ButtonProps = Omit<PressableProps, "children" | "style"> & {
label: string
label?: string
leadingIcon?: React.ReactNode
style?: StyleProp<ViewStyle>
trailingIcon?: React.ReactNode
@@ -24,14 +24,17 @@ type ButtonProps = Omit<PressableProps, "children" | "style"> & {
export function Button({ style, label, leadingIcon, trailingIcon, ...props }: ButtonProps) {
const hasIcons = leadingIcon != null || trailingIcon != null
const textElement = (
const textElement = label ? (
<SansSerifText style={tw`text-stone-100 dark:text-stone-200 font-medium`}>
{label}
</SansSerifText>
)
) : null
return (
<Pressable style={[tw`rounded-full bg-teal-600 px-4 py-3 w-fit`, style]} {...props}>
<Pressable
style={[tw`rounded-full bg-teal-600 px-4 py-3 w-fit flex items-center justify-center`, style]}
{...props}
>
{hasIcons ? (
<View style={tw`flex-row items-center gap-1.5`}>
{leadingIcon}

View File

@@ -0,0 +1,23 @@
import { FlashList } from "@shopify/flash-list";
import { useQuery } from "@tanstack/react-query";
import {
useListConversationEntriesQuery,
useDefaultConversationQuery,
useListConversationsQuery,
} from "./queries";
export function ConversationView() {
const { data: conversation } = useQuery(useDefaultConversationQuery());
const { data: entries } = useQuery(
useListConversationEntriesQuery(conversation?.id),
);
return (
<FlashList
data={entries ?? []}
keyExtractor={(item) => item.id}
renderItem={({ item }) => <div key={item.id}>{item.kind}</div>}
/>
);
}

View File

@@ -0,0 +1,15 @@
import {
ConversationEntryKind,
ConversationEntryPayload,
ConversationEntryVisibility,
} from "@freya/core"
import { type } from "arktype"
export const ConversationEntry = type({
id: "string.uuid",
sequence: "number",
kind: type.enumerated(...Object.values(ConversationEntryKind)),
visibility: type.enumerated(...Object.values(ConversationEntryVisibility)),
fileId: "string | null",
payload: ConversationEntryPayload,
})

View File

@@ -0,0 +1,41 @@
import { queryOptions, skipToken } from "@tanstack/react-query"
import { type } from "arktype"
import { useApiClient } from "@/api/client"
import { ConversationEntry } from "./conversations"
const ConversationQueryResponse = type({
entries: ConversationEntry.array(),
})
export function useListConversationsQuery() {
const api = useApiClient()
return queryOptions({
queryKey: ["conversations"],
queryFn: async () =>
api
.request("/conversations", { method: "GET" })
.then(([, json]) => ConversationQueryResponse.assert(json)),
})
}
export function useDefaultConversationQuery() {
return queryOptions({
...useListConversationsQuery(),
select: (data) => (data.entries.length === 0 ? null : data.entries[0]),
})
}
export function useListConversationEntriesQuery(id?: string) {
const api = useApiClient()
return queryOptions({
queryKey: ["conversations", id],
queryFn: id
? async () =>
api
.request(`/conversations/${id}/entries`, { method: "GET" })
.then(([, json]) => ConversationQueryResponse.assert(json).entries)
: skipToken,
})
}