macos update
Publish npm package / publish (push) Canceled after 0s

This commit is contained in:
2026-10-07 14:02:19 +02:00
parent 7fb87fbb96
commit c7e7e615c2
17 changed files with 284 additions and 130 deletions
@@ -1,13 +1,47 @@
import { createRouter, Todo } from "@<@var(context.project.name)>/rpc"
import { useEffect, useState } from "react"
import { ScrollView, Button, Checkbox, Host, Column, TextInput, Text, useNativeState, Row, Icon } from "@expo/ui";
import { Platform, PlatformColor, ScrollView, useColorScheme } from "react-native"
import Animated, { FadeIn, FadeOut, LinearTransition } from "react-native-reanimated"
import { SafeAreaView } from "react-native-safe-area-context"
import { Button, Checkbox, Host, Column, TextInput, Text, useNativeState, Row, Icon } from "@expo/ui";
import * as Crypto from "expo-crypto"
import { colorInvert, controlSize } from "@expo/ui/swift-ui/modifiers";
import { fillMaxWidth, padding, width } from "@expo/ui/jetpack-compose/modifiers";
import { background, colorInvert, controlSize, padding as iosPadding, shapes } from "@expo/ui/swift-ui/modifiers";
// No numeric width() on Android: @expo/ui 57 can't convert it natively and crashes.
import { fillMaxWidth, padding, weight } from "@expo/ui/jetpack-compose/modifiers";
// The Android emulator reaches the host via 10.0.2.2; the iOS simulator shares the host's network.
const apiUrl = Platform.OS === "android" ? "http://10.0.2.2:8080" : "http://127.0.0.1:8080"
// SwiftUI clips a border to its corner radius, cutting off the corners, so on iOS the
// border is an outer rounded fill showing 1pt around an inner one.
const iosInputBorder = Platform.OS === "ios" ? [
iosPadding({ all: 10 }),
background(PlatformColor("secondarySystemGroupedBackground"), shapes.roundedRectangle({ cornerRadius: 9, roundedCornerStyle: "continuous" })),
iosPadding({ all: 1 }),
background(PlatformColor("separator"), shapes.roundedRectangle({ cornerRadius: 10, roundedCornerStyle: "continuous" })),
] : []
// Animates its position when the list re-sorts. The Host's measured height goes through state:
// on Android a layout transition ignores the size matchContents sets natively, collapsing the row.
function AnimatedRow({ children }: { children: React.ReactNode }) {
const [height, setHeight] = useState<number>()
return (
<Animated.View layout={LinearTransition.springify()} entering={FadeIn} exiting={FadeOut}>
<Host
matchContents={{ vertical: true }}
style={height ? { height } : undefined}
onLayoutContent={(e) => setHeight(e.nativeEvent.height)}
>
{children}
</Host>
</Animated.View>
)
}
export default function Index() {
const router = createRouter("http://10.0.2.2:8080")
const router = createRouter(apiUrl)
const [todos, setTodos] = useState<Array<Todo>>([])
const todoToCreateTask = useNativeState<string>("")
const colorScheme = useColorScheme()
const fetchTodos = () => {
router.todos.listTodos({}).then((r) => {
setTodos(r.todos)
@@ -15,19 +49,17 @@ export default function Index() {
}
useEffect(() => {
fetchTodos();
})
}, [])
const setTodoDone = (id: string, task: string) => {
return (done: boolean) => {
router.todos.updateTodo({ todo: { id, task, done } })
fetchTodos()
router.todos.updateTodo({ todo: { id, task, done } }).then(fetchTodos)
}
}
const deleteTodo = (id: string) => {
return () => {
router.todos.deleteTodo({ todo: { id } })
fetchTodos()
router.todos.deleteTodo({ todo: { id } }).then(fetchTodos)
}
}
@@ -45,29 +77,43 @@ export default function Index() {
}
return (
<Host style={{ flex: 1 }}>
<Column alignment="center" modifiers={[fillMaxWidth()]}>
<Text textStyle={{fontSize:30}}> Create Todo </Text>
<TextInput value={todoToCreateTask} onChangeText={updateTodoToCreateTask} />
<Button modifiers={[controlSize('regular')]} label="create Todo" onPress={createTodo} />
<ScrollView modifiers={[fillMaxWidth()]}>
{
todos.map((todo) => (
<SafeAreaView style={{ flex: 1 }}>
<Host matchContents={{ vertical: true }}>
<Column alignment="center" modifiers={[fillMaxWidth()]}>
<Text textStyle={{fontSize:30}}> Create Todo </Text>
<TextInput
value={todoToCreateTask}
onChangeText={updateTodoToCreateTask}
placeholder="What needs to be done?"
style={Platform.OS === "ios"
? { width: 280 }
// Android draws the border as a fill behind the background, so the background must be opaque.
: { padding: 10, borderWidth: 1, borderColor: "#8E8E93", borderRadius: 8, backgroundColor: colorScheme === "dark" ? "#1C1B1F" : "#FFFFFF" }}
modifiers={Platform.OS === "ios" ? iosInputBorder : [fillMaxWidth(0.75)]}
/>
<Button modifiers={[controlSize('regular')]} label="create Todo" onPress={createTodo} />
</Column>
</Host>
<ScrollView>
{
todos.map((todo) => (
// Keyed by id so native toggles follow their todo.
<AnimatedRow key={todo.id}>
<Row alignment="center" modifiers={[fillMaxWidth(),padding(20,0,20,0)]}>
<Column alignment="start" modifiers={[width(200)]}>
<Text> {todo.task} </Text>
<Column alignment="start" modifiers={[weight(1)]}>
<Text>{todo.task}</Text>
</Column>
<Column alignment="center">
<Checkbox value={todo.done || false} onValueChange={setTodoDone(todo.id || "", todo.task)} />
</Column>
<Column alignment="end" modifiers={[fillMaxWidth()]}>
<Column alignment="end">
<Button modifiers={[controlSize('regular')]} label="delete" onPress={deleteTodo(todo.id || "")}/>
</Column>
</Row>
))
}
</ScrollView>
</Column>
</Host>
</AnimatedRow>
))
}
</ScrollView>
</SafeAreaView>
)
}