Complete Phase 2: Full integration of multi-platform system
This completes the integration of the cross-platform translation engine into the main application, making it fully functional. App.tsx Changes: - Added platform state management (currentPlatform: PlatformId) - Added translation panel state (showTranslation) - Integrated TranslationPanel component with lazy loading - Updated Toolbar with platform selector and translate button - Passed platform prop to TemplatesDrawer and CodeEditor - Connected all state management for seamless platform switching TemplatesDrawer Changes: - Now accepts currentPlatform prop - Filters templates by selected platform using getTemplatesForPlatform() - Shows platform icon and name in header - Displays template count for current platform - Ready for UEFN/Spatial/Core templates CodeEditor Changes: - Accepts optional platform prop (defaults to 'roblox') - Dynamically sets Monaco editor language based on platform: * roblox → lua * uefn → plaintext (Verse not yet in Monaco) * spatial → typescript * core → lua - Maintains backward compatibility with existing code Functional Features: ✅ Platform switching in toolbar ✅ Templates filter by platform automatically ✅ Editor language changes with platform ✅ Translation panel opens with "Translate" button ✅ Side-by-side code comparison ✅ Mock translation working ✅ All state connected and reactive Next: Phase 3 (Create UEFN templates) or Phase 4 (Claude API integration)
This commit is contained in:
parent
0029ed685f
commit
f4e6651724
3 changed files with 51 additions and 13 deletions
24
src/App.tsx
24
src/App.tsx
|
|
@ -20,6 +20,8 @@ import { initPostHog, captureEvent } from './lib/posthog';
|
|||
import { initSentry, captureError } from './lib/sentry';
|
||||
import { LoadingSpinner } from './components/ui/loading-spinner';
|
||||
|
||||
import { PlatformId } from './lib/platforms';
|
||||
|
||||
// Lazy load heavy/modal components for code splitting and better initial load
|
||||
const TemplatesDrawer = lazy(() => import('./components/TemplatesDrawer').then(m => ({ default: m.TemplatesDrawer })));
|
||||
const WelcomeDialog = lazy(() => import('./components/WelcomeDialog').then(m => ({ default: m.WelcomeDialog })));
|
||||
|
|
@ -27,6 +29,7 @@ const PreviewModal = lazy(() => import('./components/PreviewModal').then(m => ({
|
|||
const NewProjectModal = lazy(() => import('./components/NewProjectModal').then(m => ({ default: m.NewProjectModal })));
|
||||
const EducationPanel = lazy(() => import('./components/EducationPanel').then(m => ({ default: m.EducationPanel })));
|
||||
const PassportLogin = lazy(() => import('./components/PassportLogin').then(m => ({ default: m.PassportLogin })));
|
||||
const TranslationPanel = lazy(() => import('./components/TranslationPanel').then(m => ({ default: m.TranslationPanel })));
|
||||
|
||||
function App() {
|
||||
const [currentCode, setCurrentCode] = useState('');
|
||||
|
|
@ -36,7 +39,9 @@ function App() {
|
|||
const [showFileSearch, setShowFileSearch] = useState(false);
|
||||
const [showCommandPalette, setShowCommandPalette] = useState(false);
|
||||
const [showSearchInFiles, setShowSearchInFiles] = useState(false);
|
||||
const [showTranslation, setShowTranslation] = useState(false);
|
||||
const [code, setCode] = useState('');
|
||||
const [currentPlatform, setCurrentPlatform] = useState<PlatformId>('roblox');
|
||||
const isMobile = useIsMobile();
|
||||
|
||||
const [showPassportLogin, setShowPassportLogin] = useState(false);
|
||||
|
|
@ -457,6 +462,9 @@ end)`,
|
|||
<div className="h-screen flex flex-col bg-background text-foreground">
|
||||
<Toolbar
|
||||
code={currentCode}
|
||||
currentPlatform={currentPlatform}
|
||||
onPlatformChange={setCurrentPlatform}
|
||||
onTranslateClick={() => setShowTranslation(true)}
|
||||
onTemplatesClick={() => setShowTemplates(true)}
|
||||
onPreviewClick={() => setShowPreview(true)}
|
||||
onNewProjectClick={() => setShowNewProject(true)}
|
||||
|
|
@ -490,7 +498,7 @@ end)`,
|
|||
onFileClose={handleFileClose}
|
||||
/>
|
||||
<div className="flex-1">
|
||||
<CodeEditor onCodeChange={handleCodeChange} />
|
||||
<CodeEditor onCodeChange={handleCodeChange} platform={currentPlatform} />
|
||||
</div>
|
||||
</TabsContent>
|
||||
<TabsContent value="ai" className="flex-1 m-0">
|
||||
|
|
@ -529,7 +537,7 @@ end)`,
|
|||
onFileClose={handleFileClose}
|
||||
/>
|
||||
<div className="flex-1">
|
||||
<CodeEditor onCodeChange={setCurrentCode} />
|
||||
<CodeEditor onCodeChange={setCurrentCode} platform={currentPlatform} />
|
||||
</div>
|
||||
</div>
|
||||
</ResizablePanel>
|
||||
|
|
@ -572,6 +580,7 @@ end)`,
|
|||
<TemplatesDrawer
|
||||
onSelectTemplate={handleTemplateSelect}
|
||||
onClose={() => setShowTemplates(false)}
|
||||
currentPlatform={currentPlatform}
|
||||
/>
|
||||
)}
|
||||
</Suspense>
|
||||
|
|
@ -592,6 +601,17 @@ end)`,
|
|||
/>
|
||||
</Suspense>
|
||||
|
||||
<Suspense fallback={null}>
|
||||
{showTranslation && (
|
||||
<TranslationPanel
|
||||
isOpen={showTranslation}
|
||||
onClose={() => setShowTranslation(false)}
|
||||
currentCode={currentCode}
|
||||
currentPlatform={currentPlatform}
|
||||
/>
|
||||
)}
|
||||
</Suspense>
|
||||
|
||||
<Suspense fallback={null}>
|
||||
<WelcomeDialog />
|
||||
</Suspense>
|
||||
|
|
|
|||
|
|
@ -1,14 +1,24 @@
|
|||
import Editor from '@monaco-editor/react';
|
||||
import { useKV } from '@github/spark/hooks';
|
||||
import { useEffect } from 'react';
|
||||
import { useEffect, useMemo } from 'react';
|
||||
import { LoadingSpinner } from './ui/loading-spinner';
|
||||
import { toast } from 'sonner';
|
||||
import { PlatformId } from '@/lib/platforms';
|
||||
|
||||
interface CodeEditorProps {
|
||||
onCodeChange?: (code: string) => void;
|
||||
platform?: PlatformId;
|
||||
}
|
||||
|
||||
export function CodeEditor({ onCodeChange }: CodeEditorProps) {
|
||||
export function CodeEditor({ onCodeChange, platform = 'roblox' }: CodeEditorProps) {
|
||||
const languageMap: Record<PlatformId, string> = useMemo(() => ({
|
||||
roblox: 'lua',
|
||||
uefn: 'plaintext', // Verse not yet supported by Monaco, use plaintext
|
||||
spatial: 'typescript',
|
||||
core: 'lua',
|
||||
}), []);
|
||||
|
||||
const editorLanguage = languageMap[platform];
|
||||
const [code, setCode] = useKV('aethex-current-code', `-- Welcome to AeThex Studio!
|
||||
-- Write your Roblox Lua code here
|
||||
|
||||
|
|
@ -61,7 +71,7 @@ end)
|
|||
<div className="flex-1 min-h-0">
|
||||
<Editor
|
||||
height="100%"
|
||||
defaultLanguage="lua"
|
||||
language={editorLanguage}
|
||||
theme="vs-dark"
|
||||
value={code}
|
||||
onChange={handleEditorChange}
|
||||
|
|
|
|||
|
|
@ -4,19 +4,24 @@ import { ScrollArea } from '@/components/ui/scroll-area';
|
|||
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
import { X } from '@phosphor-icons/react';
|
||||
import { templates, type ScriptTemplate } from '@/lib/templates';
|
||||
import { templates, type ScriptTemplate, getTemplatesForPlatform } from '@/lib/templates';
|
||||
import { PlatformId, getPlatform } from '@/lib/platforms';
|
||||
|
||||
interface TemplatesDrawerProps {
|
||||
onSelectTemplate: (code: string) => void;
|
||||
onClose: () => void;
|
||||
currentPlatform: PlatformId;
|
||||
}
|
||||
|
||||
export function TemplatesDrawer({ onSelectTemplate, onClose }: TemplatesDrawerProps) {
|
||||
export function TemplatesDrawer({ onSelectTemplate, onClose, currentPlatform }: TemplatesDrawerProps) {
|
||||
const platform = getPlatform(currentPlatform);
|
||||
const platformTemplates = getTemplatesForPlatform(currentPlatform);
|
||||
|
||||
const categories = {
|
||||
beginner: templates.filter(t => t.category === 'beginner'),
|
||||
gameplay: templates.filter(t => t.category === 'gameplay'),
|
||||
ui: templates.filter(t => t.category === 'ui'),
|
||||
tools: templates.filter(t => t.category === 'tools'),
|
||||
beginner: platformTemplates.filter(t => t.category === 'beginner'),
|
||||
gameplay: platformTemplates.filter(t => t.category === 'gameplay'),
|
||||
ui: platformTemplates.filter(t => t.category === 'ui'),
|
||||
tools: platformTemplates.filter(t => t.category === 'tools'),
|
||||
};
|
||||
|
||||
const handleTemplateClick = (template: ScriptTemplate) => {
|
||||
|
|
@ -29,9 +34,12 @@ export function TemplatesDrawer({ onSelectTemplate, onClose }: TemplatesDrawerPr
|
|||
<Card className="w-full max-w-4xl max-h-[80vh] flex flex-col bg-card border-border">
|
||||
<div className="flex items-center justify-between p-4 border-b border-border">
|
||||
<div>
|
||||
<h2 className="text-2xl font-bold">Script Templates</h2>
|
||||
<h2 className="text-2xl font-bold flex items-center gap-2">
|
||||
<span>{platform.icon}</span>
|
||||
{platform.displayName} Templates
|
||||
</h2>
|
||||
<p className="text-sm text-muted-foreground mt-1">
|
||||
Choose a template to get started quickly
|
||||
{platformTemplates.length} templates available • Choose one to get started
|
||||
</p>
|
||||
</div>
|
||||
<Button variant="ghost" size="icon" onClick={onClose}>
|
||||
|
|
|
|||
Loading…
Reference in a new issue