mirror of
https://github.com/hanzo-templates/expo-chat.git
synced 2026-10-30 20:54:58 +00:00
The catalogue shipped 71 web templates and one EMPTY `mobile` repo, so "build an app" had no starting point on the platform people actually ship to. This is the iOS lane — Expo/React Native and Flutter for cross-platform, SwiftUI for native. The constraint that shaped every file here: an iOS archive needs macOS + Xcode + a signing identity, and our arc fleet has none. hanzoai has 519 registered runners and every one reports `os: linux`; luxfi has 151, same story; zooai has none. The only macOS builds in the org today (hanzoai/world build-desktop.yml) run on GitHub-HOSTED macos-14, which is exactly what the house CI rule says not to do. So `hanzo.yml` declares only what a Linux arc runner can genuinely execute — typecheck + web bundle for Expo, analyze + test + web for Flutter, `swiftc -parse` for SwiftUI — and the macOS archive lives in a separate `workflow_dispatch`-only `ios.yml`. A job pinned to a label no runner advertises would sit queued forever if it fired on push; parking it is honest, a permanently-yellow check is not. The README of every template states the gap and the one command that closes it. Same reasoning on the demos. Expo and Flutter both have a real web target, so `<slug>.hanzo.app` serves the SAME source the simulator runs. SwiftUI has no web target, so those two templates ship with no demo link rather than a screenshot pretending to be one. Upstreams are permissive only and recorded per template: expo/expo templates (MIT), flutter/samples (BSD-3-Clause), XcodeGen (MIT). Second measured gap, found while wiring this up: `hanzo-templates` is not in arcd's `orgs:` list either (hanzoai, luxfi, zooai, parsdao, zenlm), so the Linux jobs would queue with no runner too. Both gaps are one installer re-run, no code change; both are spelled out in every README rather than left to be discovered on the first red build. Third gap, found by probing rather than assuming, and FIXED here: every run in this org died as `startup_failure` with no logs and no annotation. A bare `runs-on: [self-hosted, linux]` probe queued fine while the same job importing hanzoai/ci failed identically at @v1 and at a pinned SHA — so it was never the tag. The org defaulted GITHUB_TOKEN to `read`, and the reusable declares `permissions: packages: write`; a caller cannot exceed the org maximum, so GitHub kills the run before creating a job. hanzo-templates now defaults to `write` like hanzoai/luxfi/zooai, and runs reach `queued` — the honest state, waiting on gap 2.
47 lines
1.6 KiB
TypeScript
47 lines
1.6 KiB
TypeScript
import { ScrollView, StyleSheet, Text, TextInput, View } from 'react-native';
|
|
import { setConfig, useConfig } from '../hanzo';
|
|
import { t } from '../theme';
|
|
|
|
export default function Settings() {
|
|
const cfg = useConfig();
|
|
return (
|
|
<ScrollView style={s.wrap} contentContainerStyle={{ padding: t.pad, gap: 18 }}>
|
|
<Field label="API base" value={cfg.base} onChange={(base) => setConfig({ base })} />
|
|
<Field label="Model" value={cfg.model} onChange={(model) => setConfig({ model })} />
|
|
<Field label="API key" value={cfg.key} onChange={(key) => setConfig({ key })} secure
|
|
hint="Held in memory only. Persist it with expo-secure-store before you ship." />
|
|
</ScrollView>
|
|
);
|
|
}
|
|
|
|
function Field({ label, value, onChange, secure, hint }: {
|
|
label: string; value: string; onChange: (v: string) => void; secure?: boolean; hint?: string;
|
|
}) {
|
|
return (
|
|
<View style={{ gap: 6 }}>
|
|
<Text style={s.label}>{label}</Text>
|
|
<TextInput
|
|
style={s.input}
|
|
value={value}
|
|
onChangeText={onChange}
|
|
secureTextEntry={secure}
|
|
autoCapitalize="none"
|
|
autoCorrect={false}
|
|
placeholder={secure ? 'sk-…' : undefined}
|
|
placeholderTextColor={t.dim}
|
|
/>
|
|
{hint && <Text style={s.hint}>{hint}</Text>}
|
|
</View>
|
|
);
|
|
}
|
|
|
|
const s = StyleSheet.create({
|
|
wrap: { flex: 1, backgroundColor: t.bg },
|
|
label: { color: t.text, fontSize: 15, fontWeight: '600' },
|
|
hint: { color: t.dim, fontSize: 13, lineHeight: 18 },
|
|
input: {
|
|
backgroundColor: t.card, color: t.text, borderRadius: t.radius, borderWidth: 1,
|
|
borderColor: t.line, paddingHorizontal: 14, paddingVertical: 12, fontSize: 16,
|
|
},
|
|
});
|