chore(stage-tamagotchi): improve widget calling devtools

This commit is contained in:
Neko Ayaka
2026-04-11 05:21:46 +08:00
parent b18158bce2
commit b77a1af2c8
3 changed files with 61 additions and 40 deletions
@@ -8,6 +8,7 @@ import type { ServerChannel } from '../../services/airi/channel-server'
import { join, resolve } from 'node:path'
import { createContext } from '@moeru/eventa/adapters/electron/main'
import { safeClose } from '@proj-airi/electron-vueuse/main'
import { BrowserWindow as ElectronBrowserWindow, ipcMain, screen, shell } from 'electron'
import { isMacOS } from 'std-env'
import { number, object, optional } from 'valibot'
@@ -115,6 +116,7 @@ export function setupWidgetsWindowManager(params: {
let pendingRoute: string | undefined
let currentRoute: string | undefined
let activeWidgetsWindow: BrowserWindow | undefined
let widgetsManager: WidgetsWindowManager | undefined
@@ -125,6 +127,7 @@ export function setupWidgetsWindowManager(params: {
ipcMain.setMaxListeners(0)
const window = createWidgetsWindow()
activeWidgetsWindow = window
const { context } = createContext(ipcMain, window)
eventaContext = context
@@ -162,6 +165,8 @@ export function setupWidgetsWindowManager(params: {
window.on('closed', () => {
eventaContext = undefined
currentRoute = undefined
if (activeWidgetsWindow === window)
activeWidgetsWindow = undefined
windowContexts.forEach((context) => {
if (context.window === window)
context.window = undefined
@@ -303,6 +308,19 @@ export function setupWidgetsWindowManager(params: {
removeWidgetInternal(id, false)
eventaContext?.emit(widgetsClearEvent, undefined)
const windowsToClose = new Set<BrowserWindow>()
if (activeWidgetsWindow && !activeWidgetsWindow.isDestroyed())
windowsToClose.add(activeWidgetsWindow)
windowContexts.forEach((context) => {
if (context.window && !context.window.isDestroyed())
windowsToClose.add(context.window)
})
for (const window of windowsToClose)
safeClose(window)
windowContexts.clear()
}
@@ -274,6 +274,38 @@ function applyMapPreset() {
</div>
</div>
<div class="flex flex-wrap gap-3">
<Button
variant="primary"
:disabled="busy"
@click="handleAdd"
>
Spawn / Replace
</Button>
<Button
variant="secondary"
:disabled="busy"
@click="handleUpdate"
>
Update Props
</Button>
<Button
variant="secondary"
:disabled="busy"
@click="handleRemove"
>
Remove Widget
</Button>
<Button
class="ml-auto"
variant="danger"
:disabled="busy"
@click="handleClear"
>
Clear All
</Button>
</div>
<div class="grid gap-4 md:grid-cols-2">
<FieldInput
v-model="form.id"
@@ -333,38 +365,6 @@ function applyMapPreset() {
:rows="8"
/>
<div class="flex flex-wrap gap-3">
<Button
variant="primary"
:disabled="busy"
@click="handleAdd"
>
Spawn / Replace
</Button>
<Button
variant="secondary"
:disabled="busy"
@click="handleUpdate"
>
Update Props
</Button>
<Button
variant="secondary"
:disabled="busy"
@click="handleRemove"
>
Remove Widget
</Button>
<Button
class="ml-auto"
variant="danger"
:disabled="busy"
@click="handleClear"
>
Clear All
</Button>
</div>
<div class="text-sm space-y-1">
<p v-if="lastAction" class="text-primary-200/90">
{{ lastAction }}
@@ -196,20 +196,23 @@ function handleClose() {
</script>
<template>
<div class="h-full w-full">
<div class="relative h-full w-full">
<button
:class="[
'absolute right-2 top-2 z-10 size-7 rounded-full text-xs text-white transition',
'bg-black/40 hover:bg-black/60',
]"
title="Close widget"
@click="handleClose"
>
</button>
<div v-if="!widgetId" class="h-full flex items-center justify-center">
<div class="border border-neutral-200/20 rounded-xl bg-neutral-900/40 px-4 py-3 text-sm text-neutral-200/80 backdrop-blur">
Missing widget id. Launch the window via a component call to populate this view.
</div>
</div>
<div v-else-if="widget" class="relative h-full">
<button
class="absolute right-2 top-2 z-10 size-7 rounded-full bg-black/40 text-xs text-white transition hover:bg-black/60"
title="Close widget"
@click="handleClose"
>
</button>
<component
:is="resolveWidgetComponent(widget.componentName)"
:key="widget.id"