mirror of
https://github.com/geoffsee/open-gsio.git
synced 2025-09-08 22:56:46 +00:00
chat + maps + ai + tools
This commit is contained in:

committed by
Geoff Seemueller

parent
48655474e3
commit
818e0e672a
@@ -43,6 +43,7 @@
|
||||
"jsdom": "^24.0.0",
|
||||
"katex": "^0.16.20",
|
||||
"lucide-react": "^0.436.0",
|
||||
"mapbox-gl": "^3.13.0",
|
||||
"marked": "^15.0.4",
|
||||
"marked-extended-latex": "^1.1.0",
|
||||
"marked-footnote": "^1.2.4",
|
||||
@@ -54,6 +55,7 @@
|
||||
"react": "^19.1.0",
|
||||
"react-dom": "^19.1.0",
|
||||
"react-icons": "^5.4.0",
|
||||
"react-map-gl": "^8.0.4",
|
||||
"react-streaming": "^0.4.2",
|
||||
"react-textarea-autosize": "^8.5.5",
|
||||
"react-use-pwa-install": "^1.0.3",
|
||||
|
@@ -32,6 +32,17 @@ const repoRoot = resolve(getRepoRoot);
|
||||
const publicDir = resolve(repoRoot, 'packages/client/public');
|
||||
const indexHtml = resolve(publicDir, 'index.html');
|
||||
|
||||
// Build the yachtpit project
|
||||
const buildCwd = resolve(repoRoot, 'crates/yachtpit/crates/yachtpit');
|
||||
logger.info(`🔨 Building in directory: ${buildCwd}`);
|
||||
|
||||
function needsRebuild() {
|
||||
const optimizedWasm = join(buildCwd, 'dist', 'yachtpit_bg.wasm_optimized');
|
||||
if (!existsSync(optimizedWasm)) return true;
|
||||
}
|
||||
|
||||
const NEEDS_REBUILD = needsRebuild();
|
||||
|
||||
function bundleCrate() {
|
||||
// ───────────── Build yachtpit project ───────────────────────────────────
|
||||
logger.info('🔨 Building yachtpit...');
|
||||
@@ -49,15 +60,15 @@ function bundleCrate() {
|
||||
logger.info(`✅ Submodules already initialized at: ${yachtpitPath}`);
|
||||
}
|
||||
|
||||
// Build the yachtpit project
|
||||
const buildCwd = resolve(repoRoot, 'crates/yachtpit/crates/yachtpit');
|
||||
logger.info(`🔨 Building in directory: ${buildCwd}`);
|
||||
|
||||
try {
|
||||
execSync('trunk build --release', {
|
||||
cwd: buildCwd,
|
||||
});
|
||||
logger.info('✅ Yachtpit built');
|
||||
if (NEEDS_REBUILD) {
|
||||
logger.info('🛠️ Changes detected — rebuilding yachtpit...');
|
||||
execSync('trunk build --release', { cwd: buildCwd, stdio: 'inherit' });
|
||||
logger.info('✅ Yachtpit built');
|
||||
} else {
|
||||
logger.info('⏩ No changes since last build — skipping yachtpit rebuild');
|
||||
process.exit(0);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('❌ Failed to build yachtpit:', error.message);
|
||||
process.exit(1);
|
||||
@@ -158,7 +169,6 @@ function bundleCrate() {
|
||||
|
||||
function optimizeWasmSize() {
|
||||
logger.info('🔨 Checking WASM size...');
|
||||
|
||||
const wasmPath = resolve(publicDir, 'yachtpit_bg.wasm');
|
||||
const fileSize = statSync(wasmPath).size;
|
||||
const sizeInMb = fileSize / (1024 * 1024);
|
||||
|
@@ -2,8 +2,7 @@ import { Box } from '@chakra-ui/react';
|
||||
import React, { useState } from 'react';
|
||||
|
||||
import { BevyScene } from './BevyScene.tsx';
|
||||
import { MatrixRain } from './MatrixRain.tsx';
|
||||
import Particles from './Particles.tsx';
|
||||
import Map from './Map.tsx';
|
||||
import Tweakbox from './Tweakbox.tsx';
|
||||
|
||||
export const LandingComponent: React.FC = () => {
|
||||
@@ -13,6 +12,9 @@ export const LandingComponent: React.FC = () => {
|
||||
const [glow, setGlow] = useState(false);
|
||||
const [matrixRain, setMatrixRain] = useState(false);
|
||||
const [bevyScene, setBevyScene] = useState(true);
|
||||
const [mapActive, setMapActive] = useState(false);
|
||||
|
||||
const map = <Map visible={mapActive} />;
|
||||
|
||||
return (
|
||||
<Box
|
||||
@@ -25,27 +27,18 @@ export const LandingComponent: React.FC = () => {
|
||||
>
|
||||
<Box
|
||||
position="fixed"
|
||||
bottom="24px"
|
||||
right="24px"
|
||||
bottom="100x"
|
||||
right="12px"
|
||||
maxWidth="300px"
|
||||
minWidth="200px"
|
||||
zIndex={1000}
|
||||
>
|
||||
<Tweakbox
|
||||
sliders={{
|
||||
speed: {
|
||||
value: !particles ? speed : 0.99,
|
||||
onChange: setSpeed,
|
||||
label: 'Animation Speed',
|
||||
min: 0.01,
|
||||
max: 0.99,
|
||||
step: 0.01,
|
||||
ariaLabel: 'animation-speed',
|
||||
},
|
||||
intensity: {
|
||||
value: !particles ? intensity : 0.99,
|
||||
onChange: setIntensity,
|
||||
label: 'Effect Intensity',
|
||||
label: 'Brightness',
|
||||
min: 0.01,
|
||||
max: 0.99,
|
||||
step: 0.01,
|
||||
@@ -53,50 +46,35 @@ export const LandingComponent: React.FC = () => {
|
||||
},
|
||||
}}
|
||||
switches={{
|
||||
particles: {
|
||||
value: particles,
|
||||
onChange(enabled) {
|
||||
if (enabled) {
|
||||
setMatrixRain(!enabled);
|
||||
setBevyScene(!enabled);
|
||||
}
|
||||
setParticles(enabled);
|
||||
},
|
||||
label: 'Particles',
|
||||
},
|
||||
matrixRain: {
|
||||
value: matrixRain,
|
||||
onChange(enabled) {
|
||||
if (enabled) {
|
||||
setParticles(!enabled);
|
||||
setBevyScene(!enabled);
|
||||
}
|
||||
setMatrixRain(enabled);
|
||||
},
|
||||
label: 'Matrix Rain',
|
||||
},
|
||||
bevyScene: {
|
||||
value: bevyScene,
|
||||
onChange(enabled) {
|
||||
if (enabled) {
|
||||
setParticles(!enabled);
|
||||
setMatrixRain(!enabled);
|
||||
setMapActive(!enabled);
|
||||
}
|
||||
setBevyScene(enabled);
|
||||
},
|
||||
label: 'Bevy Scene',
|
||||
label: 'Instruments',
|
||||
},
|
||||
glow: {
|
||||
value: glow,
|
||||
onChange: setGlow,
|
||||
label: 'Glow Effect',
|
||||
GpsMap: {
|
||||
value: mapActive,
|
||||
onChange(enabled) {
|
||||
if (enabled) {
|
||||
setParticles(!enabled);
|
||||
setMatrixRain(!enabled);
|
||||
setBevyScene(!enabled);
|
||||
}
|
||||
setMapActive(enabled);
|
||||
},
|
||||
label: 'Map',
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
<BevyScene speed={speed} intensity={intensity} glow={glow} visible={bevyScene} />
|
||||
<MatrixRain speed={speed} intensity={intensity} glow={glow} visible={matrixRain} />
|
||||
<Particles glow speed={speed} intensity={intensity} visible={particles} />
|
||||
{mapActive && map}
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
98
packages/client/src/components/landing-component/Map.tsx
Normal file
98
packages/client/src/components/landing-component/Map.tsx
Normal file
@@ -0,0 +1,98 @@
|
||||
import ReactMap from 'react-map-gl/mapbox'; // ↔ v5+ uses this import path
|
||||
import 'mapbox-gl/dist/mapbox-gl.css';
|
||||
import { Box, HStack, Button, Input, Center } from '@chakra-ui/react';
|
||||
import { useState, useEffect, useCallback } from 'react';
|
||||
|
||||
// Types for bevy_flurx_ipc communication
|
||||
interface GpsPosition {
|
||||
latitude: number;
|
||||
longitude: number;
|
||||
zoom: number;
|
||||
}
|
||||
|
||||
interface VesselStatus {
|
||||
latitude: number;
|
||||
longitude: number;
|
||||
heading: number;
|
||||
speed: number;
|
||||
}
|
||||
|
||||
interface MapViewParams {
|
||||
latitude: number;
|
||||
longitude: number;
|
||||
zoom: number;
|
||||
}
|
||||
|
||||
interface AuthParams {
|
||||
authenticated: boolean;
|
||||
token: string | null;
|
||||
}
|
||||
|
||||
// public key
|
||||
const key =
|
||||
'cGsuZXlKMUlqb2laMlZ2Wm1aelpXVWlMQ0poSWpvaVkycDFOalo0YkdWNk1EUTRjRE41YjJnNFp6VjNNelp6YXlKOS56LUtzS1l0X3VGUGdCSDYwQUFBNFNn';
|
||||
|
||||
function Map(props: { visible: boolean }) {
|
||||
const [mapboxToken, setMapboxToken] = useState(atob(key));
|
||||
const [isTokenLoading, setIsTokenLoading] = useState(false);
|
||||
const [authenticated, setAuthenticated] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
setAuthenticated(true);
|
||||
setIsTokenLoading(false);
|
||||
}, []);
|
||||
|
||||
const [mapView, setMapView] = useState({
|
||||
longitude: -122.4,
|
||||
latitude: 37.8,
|
||||
zoom: 14,
|
||||
});
|
||||
|
||||
const handleNavigationClick = useCallback(async () => {
|
||||
console.log('handling navigation in map');
|
||||
}, []);
|
||||
|
||||
const handleSearchClick = useCallback(async () => {
|
||||
console.log('handling click search in map');
|
||||
}, []);
|
||||
|
||||
const handleMapViewChange = useCallback(async (evt: any) => {
|
||||
const { longitude, latitude, zoom } = evt.viewState;
|
||||
setMapView({ longitude, latitude, zoom });
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Box
|
||||
p={4}
|
||||
height="80%"
|
||||
width="100%"
|
||||
position="relative"
|
||||
display={props.visible ? undefined : 'none'}
|
||||
>
|
||||
<Box width={'100%'} height={'100%'} position="relative" zIndex={0}>
|
||||
{/* Map itself */}
|
||||
{authenticated && (
|
||||
<ReactMap
|
||||
mapboxAccessToken={mapboxToken}
|
||||
initialViewState={mapView}
|
||||
onMove={handleMapViewChange}
|
||||
mapStyle="mapbox://styles/mapbox/dark-v11"
|
||||
attributionControl={false}
|
||||
style={{ width: '100%', height: '100%' }} // let the wrapper dictate size
|
||||
/>
|
||||
)}
|
||||
</Box>
|
||||
{/* Button bar — absolutely positioned inside the wrapper */}
|
||||
<HStack position="relative" top={1} right={4} zIndex={1} justify={'right'}>
|
||||
<Button size="sm" variant="solid" onClick={handleNavigationClick}>
|
||||
Navigation
|
||||
</Button>
|
||||
<Button size="sm" variant="solid" onClick={handleSearchClick}>
|
||||
Search
|
||||
</Button>
|
||||
</HStack>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
export default Map;
|
@@ -10,7 +10,7 @@ export default function Hero() {
|
||||
const isMobile = useIsMobile();
|
||||
|
||||
return (
|
||||
<Box p={2}>
|
||||
<Box p={2} mt={2}>
|
||||
<Box>
|
||||
<Heading
|
||||
textAlign={isMobile ? 'left' : 'right'}
|
||||
|
@@ -1,6 +1,7 @@
|
||||
import { Stack } from '@chakra-ui/react';
|
||||
import { Grid, GridItem, Stack } from '@chakra-ui/react';
|
||||
import React, { useEffect } from 'react';
|
||||
|
||||
import Chat from '../../components/chat/Chat.tsx';
|
||||
import { LandingComponent } from '../../components/landing-component/LandingComponent.tsx';
|
||||
import clientChatStore from '../../stores/ClientChatStore';
|
||||
|
||||
@@ -15,11 +16,14 @@ export default function IndexPage() {
|
||||
// Fall back to default model
|
||||
}
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Stack direction="column" height="100%" width="100%" spacing={0}>
|
||||
<LandingComponent />
|
||||
{/*<Chat height="100%" width="100%" />*/}
|
||||
</Stack>
|
||||
<Grid templateColumns="repeat(2, 1fr)" height="100%" width="100%" gap={0}>
|
||||
<GridItem>
|
||||
<LandingComponent />
|
||||
</GridItem>
|
||||
<GridItem p={2}>
|
||||
<Chat />
|
||||
</GridItem>
|
||||
</Grid>
|
||||
);
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
export const welcome_home_text = `
|
||||
# welcome!
|
||||
# yachtpit-ai
|
||||
---
|
||||
Please enjoy [responsibly](https://centerforresponsible.ai/the-center)
|
||||
|
||||
<br/>
|
||||
<br/>
|
||||
`;
|
||||
|
Reference in New Issue
Block a user