chore(release): clean up repo for v0.0.1 release
Excluded from release bundle:
- CONTEXT.md, CHANGELOG.md (agent/project working notes)
- client-app/ (React Native messenger — tracked separately)
- contracts/hello_go/ (unused standalone example)
Kept contracts/counter/ and contracts/name_registry/ as vm-test fixtures
(referenced by vm/vm_test.go; NOT production contracts).
Docs refactor:
- docs/README.md — new top-level index with cross-references
- docs/quickstart.md — rewrite around single-node as primary path
- docs/node/README.md — full rewrite, all CLI flags, schema table
- docs/api/README.md — add /api/well-known-version, /api/update-check
- docs/contracts/README.md — split native (Go) vs WASM (user-deployable)
- docs/update-system.md — new, full 5-layer update system design
- README.md — link into docs/, drop CHANGELOG/client-app references
Build-time version system (inherited from earlier commits this branch):
- node --version / client --version with ldflags-injected metadata
- /api/well-known-version with {build, protocol_version, features[]}
- Peer-version gossip on dchain/version/v1
- /api/update-check against Gitea release API
- deploy/single/update.sh with semver guard + 15-min systemd jitter
This commit is contained in:
@@ -1,127 +0,0 @@
|
||||
/**
|
||||
* Main app tab layout.
|
||||
* Redirects to welcome if no key found.
|
||||
*/
|
||||
|
||||
import React, { useEffect } from 'react';
|
||||
import { Tabs, router } from 'expo-router';
|
||||
import { Ionicons } from '@expo/vector-icons';
|
||||
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
||||
import { useStore } from '@/lib/store';
|
||||
import { useBalance } from '@/hooks/useBalance';
|
||||
import { useContacts } from '@/hooks/useContacts';
|
||||
import { useWellKnownContracts } from '@/hooks/useWellKnownContracts';
|
||||
import { getWSClient } from '@/lib/ws';
|
||||
|
||||
const C_ACCENT = '#7db5ff';
|
||||
const C_MUTED = '#98a7c2';
|
||||
const C_BG = '#111a2b';
|
||||
const C_BORDER = '#1c2840';
|
||||
|
||||
export default function AppLayout() {
|
||||
const keyFile = useStore(s => s.keyFile);
|
||||
const requests = useStore(s => s.requests);
|
||||
const insets = useSafeAreaInsets();
|
||||
|
||||
useBalance();
|
||||
useContacts();
|
||||
useWellKnownContracts(); // auto-discover canonical system contracts from node
|
||||
|
||||
// Arm the WS client with this user's Ed25519 keypair. The client signs the
|
||||
// server's auth nonce on every (re)connect so scoped subscriptions
|
||||
// (addr:<my_pub>, inbox:<my_x25519>) are accepted. Without this the
|
||||
// server would still accept global topic subs but reject scoped ones.
|
||||
useEffect(() => {
|
||||
const ws = getWSClient();
|
||||
if (keyFile) {
|
||||
ws.setAuthCreds({ pubKey: keyFile.pub_key, privKey: keyFile.priv_key });
|
||||
} else {
|
||||
ws.setAuthCreds(null);
|
||||
}
|
||||
}, [keyFile]);
|
||||
|
||||
useEffect(() => {
|
||||
if (keyFile === null) {
|
||||
const t = setTimeout(() => {
|
||||
if (!useStore.getState().keyFile) router.replace('/');
|
||||
}, 300);
|
||||
return () => clearTimeout(t);
|
||||
}
|
||||
}, [keyFile]);
|
||||
|
||||
// Tab bar layout math:
|
||||
// icon (22) + gap (4) + label (~13) = ~39px of content
|
||||
// We add a 12px visual margin above, and pad the bottom by the larger of
|
||||
// the platform safe-area inset or 10px so the bar never sits flush on the
|
||||
// home indicator.
|
||||
const BAR_CONTENT_HEIGHT = 52;
|
||||
const bottomPad = Math.max(insets.bottom, 10);
|
||||
|
||||
return (
|
||||
<Tabs
|
||||
screenOptions={{
|
||||
headerShown: false,
|
||||
tabBarActiveTintColor: C_ACCENT,
|
||||
tabBarInactiveTintColor: C_MUTED,
|
||||
tabBarLabelStyle: {
|
||||
fontSize: 10,
|
||||
fontWeight: '500',
|
||||
marginTop: 2,
|
||||
},
|
||||
tabBarStyle: {
|
||||
backgroundColor: C_BG,
|
||||
borderTopColor: C_BORDER,
|
||||
borderTopWidth: 1,
|
||||
height: BAR_CONTENT_HEIGHT + bottomPad,
|
||||
paddingTop: 8,
|
||||
paddingBottom: bottomPad,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Tabs.Screen
|
||||
name="chats"
|
||||
options={{
|
||||
tabBarLabel: 'Чаты',
|
||||
tabBarIcon: ({ color, focused }) => (
|
||||
<Ionicons
|
||||
name={focused ? 'chatbubbles' : 'chatbubbles-outline'}
|
||||
size={22}
|
||||
color={color}
|
||||
/>
|
||||
),
|
||||
tabBarBadge: requests.length > 0 ? requests.length : undefined,
|
||||
tabBarBadgeStyle: { backgroundColor: C_ACCENT, fontSize: 10 },
|
||||
}}
|
||||
/>
|
||||
<Tabs.Screen
|
||||
name="wallet"
|
||||
options={{
|
||||
tabBarLabel: 'Кошелёк',
|
||||
tabBarIcon: ({ color, focused }) => (
|
||||
<Ionicons
|
||||
name={focused ? 'wallet' : 'wallet-outline'}
|
||||
size={22}
|
||||
color={color}
|
||||
/>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
<Tabs.Screen
|
||||
name="settings"
|
||||
options={{
|
||||
tabBarLabel: 'Настройки',
|
||||
tabBarIcon: ({ color, focused }) => (
|
||||
<Ionicons
|
||||
name={focused ? 'settings' : 'settings-outline'}
|
||||
size={22}
|
||||
color={color}
|
||||
/>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
{/* Non-tab screens — hidden from tab bar */}
|
||||
<Tabs.Screen name="requests" options={{ href: null }} />
|
||||
<Tabs.Screen name="new-contact" options={{ href: null }} />
|
||||
</Tabs>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user