diff --git a/bun.lock b/bun.lock index b07896c..2da4841 100644 --- a/bun.lock +++ b/bun.lock @@ -74,7 +74,6 @@ "react-map-gl": "^8.0.4", "react-streaming": "^0.4.2", "react-textarea-autosize": "^8.5.5", - "react-use-pwa-install": "^1.0.3", "shiki": "^1.24.0", "tslog": "^4.9.3", "typescript": "^5.7.2", @@ -1646,8 +1645,6 @@ "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], - "pwa-install-handler": ["pwa-install-handler@2.6.2", "", {}, "sha512-9hMpqWNxGZx4ZoBe9k9gHkdZC/d/mvMJLA08FCVVMxOhwHBNuQVzb0DwH8ffEaqFvqu7GaotcvYgGNT1yVWduQ=="], - "qrcode.react": ["qrcode.react@4.2.0", "", { "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-QpgqWi8rD9DsS9EP3z7BT+5lY5SFhsqGjpgW5DY/i3mK4M9DTBNz3ErMi8BWYEfI3L0d8GIbGmcdFAS1uIRGjA=="], "quansync": ["quansync@0.2.10", "", {}, "sha512-t41VRkMYbkHyCYmOvx/6URnN80H7k4X0lLdBMGsz+maAwrJQYB1djpV6vHrQIBE0WBSGqhtEHrK9U3DWWH8v7A=="], @@ -1688,8 +1685,6 @@ "react-textarea-autosize": ["react-textarea-autosize@8.5.9", "", { "dependencies": { "@babel/runtime": "^7.20.13", "use-composed-ref": "^1.3.0", "use-latest": "^1.2.1" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-U1DGlIQN5AwgjTyOEnI1oCcMuEr1pv1qOtklB2l4nyMGbHzWrI0eFsYK0zos2YWqAolJyG0IWJaqWmWj5ETh0A=="], - "react-use-pwa-install": ["react-use-pwa-install@1.0.3", "", { "dependencies": { "pwa-install-handler": "^2.6.2" }, "peerDependencies": { "react": "18 || 19" } }, "sha512-poF5teATOCblAchP61+Hx/FIQJtSkjGFcZsJjiyXmG9SfmJWkj8M890lXKlu6QPg/bmG6GE3d+KP3aEO9ehgDw=="], - "readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="], "redent": ["redent@3.0.0", "", { "dependencies": { "indent-string": "^4.0.0", "strip-indent": "^3.0.0" } }, "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg=="], diff --git a/crates/yachtpit b/crates/yachtpit index 44081ad..348f206 160000 --- a/crates/yachtpit +++ b/crates/yachtpit @@ -1 +1 @@ -Subproject commit 44081ad73da99e5c88304d4eb40513033d8842a5 +Subproject commit 348f20641c8a3dcd3fb16ddeec8867d0a9d55b1b diff --git a/packages/ai/src/assistant-sdk/assistant-sdk.ts b/packages/ai/src/assistant-sdk/assistant-sdk.ts index e22a158..51d4541 100644 --- a/packages/ai/src/assistant-sdk/assistant-sdk.ts +++ b/packages/ai/src/assistant-sdk/assistant-sdk.ts @@ -22,9 +22,10 @@ export class AssistantSdk { const currentTime = `${now.getHours()}:${formattedMinutes} ${now.getSeconds()}s`; return `# Assistant Knowledge +## Assistant Name +### yachtpit-ai ## Current Context ### Date: ${currentDate} ${currentTime} -### Web Host: open-gsio.seemueller.workers.dev ${maxTokens ? `### Max Response Length: ${maxTokens} tokens (maximum)` : ''} ### Lexicographical Format: Markdown ### User Location: ${userLocation || 'Unknown'} diff --git a/packages/client/package.json b/packages/client/package.json index d3b37ee..c91a3b7 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -58,7 +58,6 @@ "react-map-gl": "^8.0.4", "react-streaming": "^0.4.2", "react-textarea-autosize": "^8.5.5", - "react-use-pwa-install": "^1.0.3", "shiki": "^1.24.0", "tslog": "^4.9.3", "typescript": "^5.7.2", diff --git a/packages/client/src/components/InstallButton.tsx b/packages/client/src/components/InstallButton.tsx index 9a1ae26..95f79bc 100644 --- a/packages/client/src/components/InstallButton.tsx +++ b/packages/client/src/components/InstallButton.tsx @@ -1,14 +1,15 @@ import { IconButton } from '@chakra-ui/react'; import { HardDriveDownload } from 'lucide-react'; import React from 'react'; -import { usePWAInstall } from 'react-use-pwa-install'; import { toolbarButtonZIndex } from './toolbar/Toolbar.tsx'; function InstallButton() { - const install = usePWAInstall(); + // const install = usePWAInstall(); - // ; + const install = () => { + console.warn('this does not work in all browsers'); + }; return ( { { const [shouldFollow, setShouldFollow] = useState(userOptionsStore.followModeEnabled); const [couldFollow, setCouldFollow] = useState(chatStore.isLoading); - const [inputWidth, setInputWidth] = useState('50%'); + const [inputWidth, setInputWidth] = useState('40%'); useEffect(() => { setShouldFollow(chatStore.isLoading && userOptionsStore.followModeEnabled); @@ -64,10 +64,10 @@ const ChatInput = observer(() => { }; const inputMaxWidth = useBreakpointValue( - { base: '50rem', lg: '50rem', md: '80%', sm: '100vw' }, + { base: '30rem', lg: '50rem', md: '80%', sm: '100vw' }, { ssr: true }, ); - const inputMinWidth = useBreakpointValue({ lg: '40rem' }, { ssr: true }); + const inputMinWidth = useBreakpointValue({ lg: '40rem', md: '30rem' }, { ssr: true }); useEffect(() => { setInputWidth('100%'); @@ -75,9 +75,7 @@ const ChatInput = observer(() => { return ( = observer( useEffect(() => { if (value.length > 10) { - setHeightConstraint(); + setHeightConstraint(parseInt(value)); } }, [value]); @@ -38,6 +38,7 @@ const InputTextArea: React.FC = observer( ref={inputRef} value={value} height={heightConstraint} + maxH={heightConstraint} autoFocus onChange={e => onChange(e.target.value)} onKeyDown={onKeyDown} @@ -48,8 +49,14 @@ const InputTextArea: React.FC = observer( color="text.primary" borderRadius="20px" border="none" - placeholder="Free my mind..." - _placeholder={{ color: 'gray.400' }} + placeholder="To Gilligan's island!" + _placeholder={{ + color: 'gray.400', + textWrap: 'nowrap', + textOverflow: 'ellipsis', + overflow: 'hidden', + width: '90%', + }} _focus={{ outline: 'none', }} diff --git a/packages/client/src/components/chat/lib/exportConversationAsMarkdown.ts b/packages/client/src/components/chat/lib/exportConversationAsMarkdown.ts index 2547c84..e1ae2d3 100644 --- a/packages/client/src/components/chat/lib/exportConversationAsMarkdown.ts +++ b/packages/client/src/components/chat/lib/exportConversationAsMarkdown.ts @@ -9,7 +9,7 @@ export function formatConversationMarkdown(messages: Instance[] if (message.role === 'user') { return `**You**: ${message.content}`; } else if (message.role === 'assistant') { - return `**Geoff's AI**: ${message.content}`; + return `**yachtpit-ai**: ${message.content}`; } return ''; }) diff --git a/packages/client/src/components/chat/messages/MessageBubble.tsx b/packages/client/src/components/chat/messages/MessageBubble.tsx index 0226722..88a53d7 100644 --- a/packages/client/src/components/chat/messages/MessageBubble.tsx +++ b/packages/client/src/components/chat/messages/MessageBubble.tsx @@ -51,7 +51,7 @@ const MessageBubble = observer(({ msg, scrollRef }) => { const [isEditing, setIsEditing] = useState(false); const [isHovered, setIsHovered] = useState(false); const isUser = msg.role === 'user'; - const senderName = isUser ? 'You' : "Geoff's AI"; + const senderName = isUser ? 'You' : 'yachtpit-ai'; const isLoading = !msg.content || !(msg.content.trim().length > 0); const messageRef = useRef(); diff --git a/packages/client/src/components/chat/messages/__tests__/MessageBubble.test.tsx b/packages/client/src/components/chat/messages/__tests__/MessageBubble.test.tsx index 9d6345c..f507ba4 100644 --- a/packages/client/src/components/chat/messages/__tests__/MessageBubble.test.tsx +++ b/packages/client/src/components/chat/messages/__tests__/MessageBubble.test.tsx @@ -104,7 +104,7 @@ describe('MessageBubble', () => { it('should render assistant message correctly', () => { render(); - expect(screen.getByText("Geoff's AI")).toBeInTheDocument(); + expect(screen.getByText('yachtpit-ai')).toBeInTheDocument(); expect(screen.getByTestId('message-content')).toHaveTextContent('Assistant response'); }); diff --git a/packages/client/src/components/contexts/ComponentContext.tsx b/packages/client/src/components/contexts/ComponentContext.tsx new file mode 100644 index 0000000..cb103ae --- /dev/null +++ b/packages/client/src/components/contexts/ComponentContext.tsx @@ -0,0 +1,25 @@ +import React, { createContext, useContext, useState } from 'react'; + +type ComponentContextType = { + enabledComponent: string; + setEnabledComponent: (component: string) => void; +}; + +const ComponentContext = createContext({ + enabledComponent: '', + setEnabledComponent: () => {}, +}); + +export const useComponent = () => useContext(ComponentContext); + +export const ComponentProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => { + const [enabledComponent, setEnabledComponent] = useState(''); + + return ( + + {children} + + ); +}; + +export default ComponentContext; diff --git a/packages/client/src/components/landing-component/BevyScene.tsx b/packages/client/src/components/landing-component/BevyScene.tsx index d94d37f..3e213e1 100644 --- a/packages/client/src/components/landing-component/BevyScene.tsx +++ b/packages/client/src/components/landing-component/BevyScene.tsx @@ -1,4 +1,4 @@ -import { Box } from '@chakra-ui/react'; +import { Box, useBreakpointValue } from '@chakra-ui/react'; import React, { memo, useEffect, useMemo } from 'react'; export interface BevySceneProps { @@ -14,6 +14,8 @@ const BevySceneInner: React.FC = ({ glow = false, visible, }) => { + const maxWidth = useBreakpointValue({ base: 640, md: 720 }, { ssr: true }); + /* initialise once */ useEffect(() => { let dispose: (() => void) | void; @@ -31,7 +33,8 @@ const BevySceneInner: React.FC = ({ () => ({ position: 'absolute' as const, inset: 0, - zIndex: 0, + zIndex: 1, + maxWidth: maxWidth, opacity: visible ? Math.min(Math.max(intensity, 0), 1) : 0, filter: glow ? 'blur(1px)' : 'none', transition: `opacity ${speed}s ease-in-out`, @@ -42,7 +45,12 @@ const BevySceneInner: React.FC = ({ return ( - + ); }; diff --git a/packages/client/src/components/landing-component/LandingComponent.tsx b/packages/client/src/components/landing-component/LandingComponent.tsx index 46244e1..8537701 100644 --- a/packages/client/src/components/landing-component/LandingComponent.tsx +++ b/packages/client/src/components/landing-component/LandingComponent.tsx @@ -1,20 +1,30 @@ import { Box } from '@chakra-ui/react'; -import React, { useState } from 'react'; +import React, { useEffect, useState } from 'react'; + +import { useComponent } from '../contexts/ComponentContext.tsx'; import { BevyScene } from './BevyScene.tsx'; -import Map from './Map.tsx'; import Tweakbox from './Tweakbox.tsx'; export const LandingComponent: React.FC = () => { const [speed, setSpeed] = useState(0.2); - const [intensity, setIntensity] = useState(0.5); - const [particles, setParticles] = useState(false); + const [intensity, setIntensity] = useState(0.99); const [glow, setGlow] = useState(false); - const [matrixRain, setMatrixRain] = useState(false); const [bevyScene, setBevyScene] = useState(true); - const [mapActive, setMapActive] = useState(false); + const [mapActive, setMapActive] = useState(true); + const [aiActive, setAiActive] = useState(false); - const map = ; + const component = useComponent(); + const { setEnabledComponent } = component; + + useEffect(() => { + if (mapActive) { + setEnabledComponent('gpsmap'); + } + if (aiActive) { + setEnabledComponent('ai'); + } + }, []); return ( { { bevyScene: { value: bevyScene, onChange(enabled) { - if (enabled) { - setParticles(!enabled); - setMatrixRain(!enabled); - setMapActive(!enabled); - } setBevyScene(enabled); }, label: 'Instruments', @@ -62,19 +67,32 @@ export const LandingComponent: React.FC = () => { value: mapActive, onChange(enabled) { if (enabled) { - setParticles(!enabled); - setMatrixRain(!enabled); - setBevyScene(!enabled); + setEnabledComponent('gpsmap'); + setAiActive(false); + } else { + setEnabledComponent(''); } setMapActive(enabled); }, label: 'Map', }, + AI: { + value: aiActive, + onChange(enabled) { + if (enabled) { + setEnabledComponent('ai'); + setMapActive(false); + } else { + setEnabledComponent(''); + } + setAiActive(enabled); + }, + label: 'AI', + }, }} /> - {mapActive && map} ); }; diff --git a/packages/client/src/components/landing-component/Map.tsx b/packages/client/src/components/landing-component/Map.tsx index 222c6ce..6e6fc39 100644 --- a/packages/client/src/components/landing-component/Map.tsx +++ b/packages/client/src/components/landing-component/Map.tsx @@ -3,6 +3,8 @@ import 'mapbox-gl/dist/mapbox-gl.css'; import { Box, HStack, Button, Input, Center } from '@chakra-ui/react'; import { useState, useEffect, useCallback } from 'react'; +import MapNext from './MapNext.tsx'; + // Types for bevy_flurx_ipc communication interface GpsPosition { latitude: number; @@ -33,64 +35,27 @@ 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 ( - - - {/* Map itself */} - {authenticated && ( - - )} - + /* Full-screen wrapper — fills the viewport and becomes the positioning context */ + {/* Button bar — absolutely positioned inside the wrapper */} - - - - + + + {/**/} + {/* /!*{vesselPosition && (*!/*/} + {/* /!* *!/*/} + {/* /!* *!/*/} + {/* /!* *!/*/} + {/* /!*)}*!/*/} + {/**/} ); } diff --git a/packages/client/src/components/landing-component/MapNext.tsx b/packages/client/src/components/landing-component/MapNext.tsx new file mode 100644 index 0000000..9d51f96 --- /dev/null +++ b/packages/client/src/components/landing-component/MapNext.tsx @@ -0,0 +1,173 @@ +import { Box, Button, HStack, Input } from '@chakra-ui/react'; +import { useCallback, useEffect, useMemo, useState } from 'react'; +import Map, { + FullscreenControl, + GeolocateControl, + Marker, + NavigationControl, + Popup, + ScaleControl, +} from 'react-map-gl/mapbox'; + +import PORTS from './nautical-base-data.json'; +import Pin from './pin'; + +export default function MapNext(props: any = { mapboxPublicKey: '' } as any) { + const [popupInfo, setPopupInfo] = useState(null); + const [isSearchOpen, setIsSearchOpen] = useState(false); + 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 }); + }, []); + + const pins = useMemo( + () => + PORTS.map((city, index) => ( + { + // If we let the click event propagates to the map, it will immediately close the popup + // with `closeOnClick: true` + e.originalEvent.stopPropagation(); + /* + src/MapNext.tsx:34:38 - error TS2345: Argument of type '{ city: string; population: string; image: string; state: string; latitude: number; longitude: number; }' is not assignable to parameter of type 'SetStateAction'. +Type '{ city: string; population: string; image: string; state: string; latitude: number; longitude: number; }' provides no match for the signature '(prevState: null): null'. + */ + // @ts-ignore + setPopupInfo(city); + }} + > + + + )), + [], + ); + + return ( + + {/**/} + {/* */} + {/* */} + {/* {isSearchOpen && (*/} + {/* */} + {/* */} + {/* */} + {/* )}*/} + {/* */} + {/* */} + {/**/} + + + + + + + {pins} + + {popupInfo && ( + setPopupInfo(null)} + > +
+ {/*src/MapNext.tsx:71:40 - error TS2339: Property 'city' does not exist on type 'never'. + +71 {popupInfo.city}, {popupInfo.state} |{' '} + ~~~~*/} + {/*@ts-ignore*/} + {/*@ts-ignore*/} + {popupInfo.city},{popupInfo.state} + {/*@ts-ignore*/} +
+ {/*@ts-ignore*/} + +
+ + Wikipedia + +
+ )} +
+
+ ); +} diff --git a/packages/client/src/components/landing-component/control-panel.tsx b/packages/client/src/components/landing-component/control-panel.tsx new file mode 100644 index 0000000..5eca3aa --- /dev/null +++ b/packages/client/src/components/landing-component/control-panel.tsx @@ -0,0 +1,24 @@ +import * as React from 'react'; + +function ControlPanel() { + return ( +
+

+ Data source:{' '} + + Wikipedia + +

+ +
+ ); +} + +export default React.memo(ControlPanel); diff --git a/packages/client/src/components/landing-component/nautical-base-data.json b/packages/client/src/components/landing-component/nautical-base-data.json new file mode 100644 index 0000000..c9ed859 --- /dev/null +++ b/packages/client/src/components/landing-component/nautical-base-data.json @@ -0,0 +1,22 @@ +[ + {"city":"New York","population":"8,335,897","image":"https://upload.wikimedia.org/wikipedia/commons/thumb/b/b9/Above_Gotham.jpg/240px-Above_Gotham.jpg","state":"New York","latitude":40.7128,"longitude":-74.0060}, + {"city":"Los Angeles","population":"3,822,238","image":"https://upload.wikimedia.org/wikipedia/commons/thumb/5/57/LA_Skyline_Mountains2.jpg/240px-LA_Skyline_Mountains2.jpg","state":"California","latitude":34.0522,"longitude":-118.2437}, + {"city":"Long Beach","population":"456,062","image":"https://upload.wikimedia.org/wikipedia/commons/thumb/d/d9/Long_Beach_skyline_from_Shoreline_Village.jpg/240px-Long_Beach_skyline_from_Shoreline_Village.jpg","state":"California","latitude":33.7701,"longitude":-118.1937}, + {"city":"Seattle","population":"749,256","image":"https://upload.wikimedia.org/wikipedia/commons/thumb/3/36/SeattleI5Skyline.jpg/240px-SeattleI5Skyline.jpg","state":"Washington","latitude":47.6062,"longitude":-122.3321}, + {"city":"San Francisco","population":"808,437","image":"https://upload.wikimedia.org/wikipedia/commons/thumb/6/6a/San_Francisco_skyline_from_Coit_Tower.jpg/240px-San_Francisco_skyline_from_Coit_Tower.jpg","state":"California","latitude":37.7749,"longitude":-122.4194}, + {"city":"San Diego","population":"1,386,932","image":"https://upload.wikimedia.org/wikipedia/commons/thumb/5/53/US_Navy_110604-N-NS602-574_Navy_and_Marine_Corps_personnel%2C_along_with_community_leaders_from_the_greater_San_Diego_area_come_together_to_commemora.jpg/240px-US_Navy_110604-N-NS602-574_Navy_and_Marine_Corps_personnel%2C_along_with_community_leaders_from_the_greater_San_Diego_area_come_together_to_commemora.jpg","state":"California","latitude":32.7157,"longitude":-117.1611}, + {"city":"Norfolk","population":"235,089","image":"https://upload.wikimedia.org/wikipedia/commons/thumb/6/6e/Norfolk_Skyline_from_Portsmouth.jpg/240px-Norfolk_Skyline_from_Portsmouth.jpg","state":"Virginia","latitude":36.8508,"longitude":-76.2859}, + {"city":"Miami","population":"449,514","image":"https://upload.wikimedia.org/wikipedia/commons/thumb/4/4b/Miami_skyline_201807_cat.jpg/240px-Miami_skyline_201807_cat.jpg","state":"Florida","latitude":25.7617,"longitude":-80.1918}, + {"city":"Boston","population":"675,647","image":"https://upload.wikimedia.org/wikipedia/commons/thumb/1/1b/Boston_skyline_and_Boston_Harbor.jpg/240px-Boston_skyline_and_Boston_Harbor.jpg","state":"Massachusetts","latitude":42.3601,"longitude":-71.0589}, + {"city":"Baltimore","population":"585,708","image":"https://upload.wikimedia.org/wikipedia/commons/thumb/3/3b/Baltimore_Skyline.jpg/240px-Baltimore_Skyline.jpg","state":"Maryland","latitude":39.2904,"longitude":-76.6122}, + {"city":"Charleston","population":"151,612","image":"https://upload.wikimedia.org/wikipedia/commons/thumb/a/a7/Charleston_SC_Skyline.jpg/240px-Charleston_SC_Skyline.jpg","state":"South Carolina","latitude":32.7765,"longitude":-79.9311}, + {"city":"Savannah","population":"147,780","image":"https://upload.wikimedia.org/wikipedia/commons/thumb/4/40/Savannah_GA%2C_River_Street.jpg/240px-Savannah_GA%2C_River_Street.jpg","state":"Georgia","latitude":32.0809,"longitude":-81.0912}, + {"city":"Tampa","population":"403,364","image":"https://upload.wikimedia.org/wikipedia/commons/thumb/4/4d/Tampa_skyline_from_South%2C_2022.jpg/240px-Tampa_skyline_from_South%2C_2022.jpg","state":"Florida","latitude":27.9506,"longitude":-82.4572}, + {"city":"Mobile","population":"187,041","image":"https://upload.wikimedia.org/wikipedia/commons/thumb/7/70/Mobile_skyline_from_Mobile_River.jpg/240px-Mobile_skyline_from_Mobile_River.jpg","state":"Alabama","latitude":30.6954,"longitude":-88.0399}, + {"city":"Anchorage","population":"288,121","image":"https://upload.wikimedia.org/wikipedia/commons/thumb/5/55/Anchorage_skyline_and_susitna.jpg/240px-Anchorage_skyline_and_susitna.jpg","state":"Alaska","latitude":61.2181,"longitude":-149.9003}, + {"city":"Portland","population":"68,408","image":"https://upload.wikimedia.org/wikipedia/commons/thumb/4/48/Portland_Maine_skyline.jpg/240px-Portland_Maine_skyline.jpg","state":"Maine","latitude":43.6591,"longitude":-70.2568}, + {"city":"Honolulu","population":"349,547","image":"https://upload.wikimedia.org/wikipedia/commons/thumb/1/10/Honolulu_and_Diamond_Head.jpg/240px-Honolulu_and_Diamond_Head.jpg","state":"Hawaii","latitude":21.3069,"longitude":-157.8583}, + {"city":"New Orleans","population":"376,971","image":"https://upload.wikimedia.org/wikipedia/commons/thumb/f/fb/New_Orleans_skyline_sunset_Dec_28_2021_PANO_DSC07177-07179.jpg/240px-New_Orleans_skyline_sunset_Dec_28_2021_PANO_DSC07177-07179.jpg","state":"Louisiana","latitude":29.9511,"longitude":-90.0715}, + {"city":"Jacksonville","population":"971,319","image":"https://upload.wikimedia.org/wikipedia/commons/thumb/f/f3/Skyline_of_Jacksonville_FL%2C_South_view_20160706_1.jpg/240px-Skyline_of_Jacksonville_FL%2C_South_view_20160706_1.jpg","state":"Florida","latitude":30.3322,"longitude":-81.6557}, + {"city":"Houston","population":"2,302,878","image":"https://upload.wikimedia.org/wikipedia/commons/thumb/6/60/Aerial_views_of_the_Houston%2C_Texas%2C_28005u.jpg/240px-Aerial_views_of_the_Houston%2C_Texas%2C_28005u.jpg","state":"Texas","latitude":29.7604,"longitude":-95.3698} +] \ No newline at end of file diff --git a/packages/client/src/components/landing-component/pin.tsx b/packages/client/src/components/landing-component/pin.tsx new file mode 100644 index 0000000..45dffeb --- /dev/null +++ b/packages/client/src/components/landing-component/pin.tsx @@ -0,0 +1,21 @@ +import * as React from 'react'; + +const ICON = `M20.2,15.7L20.2,15.7c1.1-1.6,1.8-3.6,1.8-5.7c0-5.6-4.5-10-10-10S2,4.5,2,10c0,2,0.6,3.9,1.6,5.4c0,0.1,0.1,0.2,0.2,0.3 + c0,0,0.1,0.1,0.1,0.2c0.2,0.3,0.4,0.6,0.7,0.9c2.6,3.1,7.4,7.6,7.4,7.6s4.8-4.5,7.4-7.5c0.2-0.3,0.5-0.6,0.7-0.9 + C20.1,15.8,20.2,15.8,20.2,15.7z`; + +const pinStyle = { + cursor: 'pointer', + fill: '#d00', + stroke: 'none' +}; + +function Pin({size = 20}) { + return ( + + + + ); +} + +export default React.memo(Pin); \ No newline at end of file diff --git a/packages/client/src/layout/Layout.tsx b/packages/client/src/layout/Layout.tsx index f33f9c9..4e6d151 100644 --- a/packages/client/src/layout/Layout.tsx +++ b/packages/client/src/layout/Layout.tsx @@ -2,6 +2,7 @@ import { observer } from 'mobx-react-lite'; import React, { useEffect, useState } from 'react'; import { Chakra } from '../components/contexts/ChakraContext'; +import ComponentContext, { ComponentProvider } from '../components/contexts/ComponentContext.tsx'; import { MobileProvider } from '../components/contexts/MobileContext'; import { PageContextProvider } from '../renderer/usePageContext'; import userOptionsStore from '../stores/UserOptionsStore'; @@ -13,6 +14,7 @@ export { Layout }; const Layout = observer(({ pageContext, children }) => { const [activeTheme, setActiveTheme] = useState('darknight'); + const [enabledComponent, setEnabledComponent] = useState('gpsmap'); useEffect(() => { if (userOptionsStore.theme !== activeTheme) { @@ -47,7 +49,9 @@ const Layout = observer(({ pageContext, children }) => { - {children} + + {children} + diff --git a/packages/client/src/layout/Navigation.tsx b/packages/client/src/layout/Navigation.tsx index 91b7d9f..fd56433 100644 --- a/packages/client/src/layout/Navigation.tsx +++ b/packages/client/src/layout/Navigation.tsx @@ -42,6 +42,7 @@ const Navigation = observer(({ children, routeRegistry }) => { return ( + {/*this is the menu button*/} - + + + + + + ); diff --git a/packages/cloudflare-workers/open-gsio/wrangler.jsonc b/packages/cloudflare-workers/open-gsio/wrangler.jsonc index 2f2789e..d84bb06 100644 --- a/packages/cloudflare-workers/open-gsio/wrangler.jsonc +++ b/packages/cloudflare-workers/open-gsio/wrangler.jsonc @@ -20,10 +20,9 @@ { "binding": "KV_STORAGE", // $ npx wrangler kv namespace create open-gsio - // $ npx wrangler kv namespace create open-gsio - "id": "placeholderId", + "id": "", // $ npx wrangler kv namespace create open-gsio --preview - "preview_id": "placeholderId" + "preview_id": "" } ], "migrations": [