openpencil/src/components/editor/EditorWorkspace.vue
Danila Poyarkov be942783dc
refactor(i18n): migrate app copy to domain namespaces
* refactor(i18n): migrate app copy to domain namespaces

- Replace the monolithic dialogs catalog with 16 flat product-domain catalogs
- Preserve every translated locale value while moving all 356 messages
- Expose narrow domain composables and retain useI18n as a compatibility aggregate
- Document namespace ownership and admission rules

* fix(i18n): complete migrated locale coverage

- Translate exposed MCP automation, code editor, credential, and media placeholders
- Restore missing German, Spanish, French, Italian, Polish, and Russian diacritics
- Preserve technical product terms and interpolation placeholders

* fix(i18n): polish remaining locale wording

- Correct the mixed-language German code source label
- Preserve stock_photo and Pexels semantics in German and Polish
- Improve Italian MCP and code-editor grammar
- Use the standard Russian term for MCP endpoint

* fix(i18n): migrate diagnostics copy after rebase

- Add a diagnostics domain for newly merged usage and telemetry settings
- Keep settings navigation labels in the settings domain
- Preserve translated diagnostics catalogs from current master

* style(app): format rebased settings components

* refactor(i18n): simplify domain message keys

- Remove redundant domain prefixes from settings, diagnostics, automation, and integration catalogs
- Move feature-specific actions out of the common namespace
- Preserve current-master language picker and diagnostics copy across every locale
- Update consumers to concise semantic keys

* fix(app): preserve font and updater contracts

- Restore browser and abort-aware font loading from current master
- Remove the unused parameter helper from common messages
- Update updater tests for semantic domain keys

* fix(i18n): finish semantic diagnostics access

* refactor(i18n): derive active MCP status message

* fix(i18n): preserve rendering settings after rebase

- Add a rendering domain for tiled canvas preferences
- Preserve the current-master language and rendering settings UI
- Move every translated renderer preference out of the retired dialogs catalog

* fix(i18n): polish reviewed locale semantics

* test(i18n): enforce translation completeness baseline

- Fail on interpolation placeholder drift and suspicious mixed-script values
- Reject new source-identical translations while tracking existing debt explicitly
- Report translated-message coverage for every supported locale
- Require baseline cleanup when existing placeholders are translated

* refactor(i18n): baseline reviewed mixed-script messages

- Replace brittle product-vocabulary exceptions with Unicode script detection
- Track reviewed mixed-script messages by stable locale and message identity
- Reject new entries and stale baseline debt without hardcoded terminology

* fix(fig): resolve relocated stroke test helper
2026-08-31 23:54:14 +03:00

126 lines
4.2 KiB
Vue

<script setup lang="ts">
import { tv } from 'tailwind-variants'
import { SplitterGroup, SplitterPanel, SplitterResizeHandle } from 'reka-ui'
import { formatShortcut, useI18n, useViewportKind } from '@open-pencil/vue'
import { useEditorStore } from '@/app/editor/active-store'
import { appRuntimeConfig } from '@/app/runtime/config'
import { appMenuShortcut } from '@/app/shell/menu/shortcut'
import { activeTab } from '@/app/tabs'
import CanvasSplitRoot from '@/components/canvas/CanvasSplitRoot.vue'
import CollabPanel from '@/components/CollabPanel/CollabPanel.vue'
import EditorCanvas from '@/components/EditorCanvas.vue'
import LayersPanel from '@/components/LayersPanel.vue'
import MobileDrawer from '@/components/MobileDrawer.vue'
import MobileHud from '@/components/MobileHud/MobileHud.vue'
import PropertiesPanel from '@/components/PropertiesPanel.vue'
import Tip from '@/components/ui/Tip.vue'
import Toolbar from '@/components/Toolbar/Toolbar.vue'
import { loadEditorLayout, saveEditorLayout } from '@/app/shell/layout-storage'
import splitterTheme from '@/theme/splitter'
const showChrome = appRuntimeConfig.showChrome
const store = useEditorStore()
const { editor } = useI18n()
const { isMobile } = useViewportKind()
const initialEditorLayout = loadEditorLayout()
const horizontalSplitterStyles = tv(splitterTheme)({ direction: 'horizontal' })
</script>
<template>
<SplitterGroup
v-if="!isMobile && showChrome && store.state.showUI"
:key="activeTab?.id"
direction="horizontal"
class="flex-1 overflow-hidden"
@layout="saveEditorLayout"
>
<SplitterPanel
id="layers"
:default-size="initialEditorLayout[0]"
:min-size="10"
:max-size="30"
class="flex"
>
<LayersPanel />
</SplitterPanel>
<SplitterResizeHandle
data-test-id="left-splitter-handle"
:class="horizontalSplitterStyles.handle()"
>
<div :class="horizontalSplitterStyles.divider()" />
</SplitterResizeHandle>
<SplitterPanel id="canvas" :default-size="initialEditorLayout[1]" :min-size="30" class="flex">
<div class="relative flex min-w-0 flex-1">
<CanvasSplitRoot />
<Toolbar />
</div>
</SplitterPanel>
<SplitterResizeHandle :class="horizontalSplitterStyles.handle()">
<div :class="horizontalSplitterStyles.divider()" />
</SplitterResizeHandle>
<SplitterPanel
id="properties"
:default-size="initialEditorLayout[2]"
:min-size="10"
:max-size="30"
class="flex flex-col"
>
<div class="flex shrink-0 items-center justify-between border-b border-border px-1.5 py-1.5">
<CollabPanel />
</div>
<PropertiesPanel />
</SplitterPanel>
</SplitterGroup>
<div
v-else-if="isMobile && showChrome && store.state.showUI"
:key="'mobile-' + activeTab?.id"
class="flex flex-1 overflow-hidden"
>
<div class="relative flex min-w-0 flex-1">
<EditorCanvas />
<MobileHud />
<Toolbar />
</div>
<MobileDrawer />
</div>
<div
v-else-if="showChrome"
:key="'collapsed-' + activeTab?.id"
class="flex flex-1 overflow-hidden"
>
<div class="relative flex min-w-0 flex-1">
<EditorCanvas />
<div
v-if="!isMobile"
class="absolute top-7 left-7 z-10 flex items-center gap-2 rounded-lg border border-border bg-panel px-2 py-1 shadow-sm"
>
<img src="/favicon-32.png" class="size-4" alt="OpenPencil" />
<span data-test-id="editor-document-name" class="text-xs text-surface">{{
store.state.documentName
}}</span>
<Tip
:label="editor.showUI({ shortcut: formatShortcut(appMenuShortcut('toggle-ui')) ?? '' })"
>
<button
data-test-id="editor-show-ui"
class="ml-1 flex size-6 cursor-pointer items-center justify-center rounded text-muted transition-colors hover:bg-hover hover:text-surface"
@click="store.state.showUI = true"
>
<icon-lucide-sidebar class="size-3.5" />
</button>
</Tip>
</div>
</div>
</div>
<div v-else :key="'bare-' + activeTab?.id" class="flex flex-1 overflow-hidden">
<div class="relative flex min-w-0 flex-1">
<EditorCanvas />
</div>
</div>
</template>