Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 49 additions & 6 deletions webapp/frontend/src/lib/components/MlogWatcherButton.svelte
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
<script lang="ts">
import type { MlogWatcherStore } from '$lib/mlog_watcher';
import { Check, CircleAlert, Cpu, LoaderCircle } from '@lucide/svelte';
import type {MlogWatcherStore} from '$lib/mlog_watcher';
import {Check, CircleAlert, Cpu, LoaderCircle} from '@lucide/svelte';
import EditorActionButton from './EditorActionButton.svelte';
import { toast } from 'svelte-sonner';
import {toast} from 'svelte-sonner';

let {
channel,
getText,
disabled = false
}: { channel: MlogWatcherStore; getText: () => string; disabled?: boolean } = $props();
disabled = false,
schematic = false
}: { channel: MlogWatcherStore; getText: () => string; disabled?: boolean; schematic?: boolean } = $props();

let status = $state<'idle' | 'sent' | 'loading' | 'error'>('idle');
// using ReturnType to avoid issues caused by @types/node
Expand Down Expand Up @@ -55,11 +56,53 @@
}
timeoutId = setTimeout(() => (status = 'idle'), 2000);
}

async function sendSchematicToMlogWatcher() {
if (timeoutId !== null) clearTimeout(timeoutId);

const text = getText();
status = 'loading';
try {
const response = await channel.putSchematicInLibrary(text, true);
if (response.status === 'success') {
status = 'sent';
} else {
status = 'error';
const errorCode = response.result.text;
let description = '';
switch (errorCode) {
case 'schematic_import_failed':
description = 'Schematic import failed (invalid file?).';
break;
case 'internal_error':
description = 'An internal error occurred while processing the mlog code.';
break;
case 'invalid_arguments':
case 'unknown_method':
case 'unsupported_method_version':
description = 'The MlogWatcher version is incompatible with this feature.';
break;
default:
description = 'An unknown error occurred.';
// typescript will generate an error if there is a case that is not covered
// by any case body
errorCode satisfies never;
}
toast.error(`Failed to send to MlogWatcher: ${description} (Error code: ${errorCode})`, {
duration: 8000
});
}
} catch (e) {
status = 'error';
console.error(e);
}
timeoutId = setTimeout(() => (status = 'idle'), 2000);
}
</script>

<EditorActionButton
tooltip={status === 'sent' ? 'Sent!' : 'Send to MlogWatcher'}
onClick={sendToMlogWatcher}
onClick={schematic ? sendSchematicToMlogWatcher : sendToMlogWatcher }
{disabled}
>
{#if status === 'sent'}
Expand Down
43 changes: 24 additions & 19 deletions webapp/frontend/src/routes/schematics/+page.svelte
Original file line number Diff line number Diff line change
@@ -1,31 +1,27 @@
<script lang="ts">
import { tick, untrack } from 'svelte';
import { Code, Play, Trash2 } from '@lucide/svelte';

import {
ApiHandler,
type CompileResponseMessage,
type RunResult,
type Sample,
type SourceRange
} from '$lib/api';
import { schemacode } from '$lib/grammars/schemacode_language';
import type { PageProps } from './$types';
import { setDiagnostics } from '@codemirror/lint';
import { compileMessagesToDiagnostics, jumpToRange, updateEditor } from '$lib/codemirror';
import { getThemeContext, LocalCompilerTarget, syncUrl } from '$lib/stores.svelte';
import {tick, untrack} from 'svelte';
import {Code, Play, Trash2} from '@lucide/svelte';

import {ApiHandler, type CompileResponseMessage, type RunResult, type Sample, type SourceRange} from '$lib/api';
import {schemacode} from '$lib/grammars/schemacode_language';
import type {PageProps} from './$types';
import {setDiagnostics} from '@codemirror/lint';
import {compileMessagesToDiagnostics, jumpToRange, updateEditor} from '$lib/codemirror';
import {getThemeContext, LocalCompilerTarget, syncUrl} from '$lib/stores.svelte';
import TargetPicker from '$lib/components/TargetPicker.svelte';
import ProjectLinks from '$lib/components/ProjectLinks.svelte';
import ControlBar from '$lib/components/ControlBar.svelte';
import SamplePicker from '$lib/components/SamplePicker.svelte';
import EditorLayout from '$lib/components/EditorLayout.svelte';
import BottomActionBar from '$lib/components/BottomActionBar.svelte';
import EditorActionButton from '$lib/components/EditorActionButton.svelte';
import { InputEditorStore, OutputEditorStore } from '$lib/editors.svelte';
import { getSettingsContext } from '$lib/settings.svelte';
import { EditorView } from 'codemirror';
import type { OutputTabName } from '$lib/components/TabsOutput.svelte';
import {InputEditorStore, OutputEditorStore} from '$lib/editors.svelte';
import {getSettingsContext} from '$lib/settings.svelte';
import {EditorView} from 'codemirror';
import type {OutputTabName} from '$lib/components/TabsOutput.svelte';
import PageInfoCard from '$lib/components/PageInfoCard.svelte';
import {MlogWatcherStore} from '$lib/mlog_watcher';
import MlogWatcherButton from '$lib/components/MlogWatcherButton.svelte';

let { data }: PageProps = $props();
const api = new ApiHandler();
Expand All @@ -40,6 +36,7 @@
extensions: [schemacode()],
settings
});
const channel = new MlogWatcherStore(() => settings.mlogWatcherPort);
const encodedEditor = new OutputEditorStore(theme, [EditorView.lineWrapping], settings);

let runResults = $state<RunResult[]>([]);
Expand Down Expand Up @@ -188,6 +185,14 @@
<Trash2 class="size-4" />
</EditorActionButton>
{/snippet}
{#snippet outputActions(showingCode)}
<MlogWatcherButton
{channel}
getText={() => encodedEditor.view?.state.doc.toString() ?? ''}
disabled={!showingCode}
schematic={true}
/>
{/snippet}
</EditorLayout>

<!-- Bottom Action Bar (Mobile) -->
Expand Down