From d55cdc220a5b5be8c4a3953f7c26e29425898d38 Mon Sep 17 00:00:00 2001 From: LemonNeko Date: Fri, 5 Sep 2025 13:27:26 +0800 Subject: [PATCH] feat(tamagotchi): generate preview image when import live2d model (#555) * fix(tamagotchi): set min width of settings page, use grid model selector view * fix(tamagotchi): sort model by import time * feat(tamagotchi): generate preview image when import live2d model * fix(tamagotchi): don't show onboarding page when window open unless `/` * fix: thanks to gemini --- .../src-tauri/src/app/windows/settings.rs | 1 + apps/stage-tamagotchi/src/App.vue | 8 -- apps/stage-tamagotchi/src/pages/index.vue | 11 +++ packages/stage-ui/package.json | 1 + .../Dialogs/model-selector/model-selector.vue | 45 +++++----- .../src/components/Scenes/Live2D/Model.vue | 2 +- .../stage-ui/src/stores/display-models.ts | 85 ++++++++++++++++++- pnpm-lock.yaml | 44 ++++++---- 8 files changed, 142 insertions(+), 55 deletions(-) diff --git a/apps/stage-tamagotchi/src-tauri/src/app/windows/settings.rs b/apps/stage-tamagotchi/src-tauri/src/app/windows/settings.rs index a5df369c0..15591d479 100644 --- a/apps/stage-tamagotchi/src-tauri/src/app/windows/settings.rs +++ b/apps/stage-tamagotchi/src-tauri/src/app/windows/settings.rs @@ -22,6 +22,7 @@ pub fn new_settings_window( ) .title("Settings") .inner_size(550.0, 900.0) + .min_inner_size(550.0, 900.0) .shadow(true) .transparent(false) .accept_first_mouse(true); diff --git a/apps/stage-tamagotchi/src/App.vue b/apps/stage-tamagotchi/src/App.vue index 637e2d165..e00216979 100644 --- a/apps/stage-tamagotchi/src/App.vue +++ b/apps/stage-tamagotchi/src/App.vue @@ -11,7 +11,6 @@ import { computed, onMounted, watch } from 'vue' import { useI18n } from 'vue-i18n' import { RouterView } from 'vue-router' -import { commands } from './bindings/tauri-plugins/window-router-link' import { useAppRuntime } from './composables/runtime' import { useTauriEvent } from './composables/tauri' import { useWindowMode } from './stores/window-controls' @@ -22,7 +21,6 @@ const displayModelsStore = useDisplayModelsStore() const settingsStore = useSettings() const { language, themeColorsHue, themeColorsHueDynamic, allowVisibleOnAllWorkspaces } = storeToRefs(settingsStore) const onboardingStore = useOnboardingStore() -const { shouldShowSetup } = storeToRefs(onboardingStore) const mcpStore = useMcpStore() const { listen } = useTauriEvent() @@ -48,12 +46,6 @@ watch(themeColorsHueDynamic, () => { document.documentElement.classList.toggle('dynamic-hue', themeColorsHueDynamic.value) }, { immediate: true }) -watch(shouldShowSetup, () => { - if (shouldShowSetup.value) { - commands.go('/onboarding', 'onboarding') - } -}) - onMounted(() => { listen('mcp_plugin_destroyed', () => { mcpStore.connected = false diff --git a/apps/stage-tamagotchi/src/pages/index.vue b/apps/stage-tamagotchi/src/pages/index.vue index 26f391ceb..275715faa 100644 --- a/apps/stage-tamagotchi/src/pages/index.vue +++ b/apps/stage-tamagotchi/src/pages/index.vue @@ -4,6 +4,7 @@ import type { AiriTamagotchiEvents, Point } from '../composables/tauri' import { WidgetStage } from '@proj-airi/stage-ui/components/scenes' import { useLive2d } from '@proj-airi/stage-ui/stores/live2d' import { useMcpStore } from '@proj-airi/stage-ui/stores/mcp' +import { useOnboardingStore } from '@proj-airi/stage-ui/stores/onboarding' import { connectServer } from '@proj-airi/tauri-plugin-mcp' import { watchThrottled } from '@vueuse/core' import { storeToRefs } from 'pinia' @@ -12,6 +13,7 @@ import { computed, onMounted, onUnmounted, ref, watch } from 'vue' import ResourceStatusIsland from '../components/Widgets/ResourceStatusIsland/index.vue' import { commands as passThroughCommands } from '../bindings/tauri-plugins/window-pass-through-on-hover' +import { commands } from '../bindings/tauri-plugins/window-router-link' import { useTauriCore, useTauriEvent, useTauriWindow } from '../composables/tauri' import { useTauriGlobalShortcuts } from '../composables/tauri-global-shortcuts' import { useRdevMouse } from '../composables/use-rdev-mouse' @@ -20,6 +22,9 @@ import { useWindowStore } from '../stores/window' import { useWindowControlStore } from '../stores/window-controls' import { WindowControlMode } from '../types/window-controls' +const onboardingStore = useOnboardingStore() +const { shouldShowSetup } = storeToRefs(onboardingStore) + useTauriGlobalShortcuts() const windowControlStore = useWindowControlStore() const resourcesStore = useResourcesStore() @@ -44,6 +49,12 @@ const isPassingThrough = ref(false) const isOverUI = ref(false) const isFirstTime = ref(true) +watch(shouldShowSetup, () => { + if (shouldShowSetup.value) { + commands.go('/onboarding', 'onboarding') + } +}, { immediate: true }) + watchThrottled([mouseX, mouseY], async ([x, y]) => { const canvas = widgetStageRef.value?.canvasElement() if (!canvas) { diff --git a/packages/stage-ui/package.json b/packages/stage-ui/package.json index db60c2569..23b4c5e17 100644 --- a/packages/stage-ui/package.json +++ b/packages/stage-ui/package.json @@ -42,6 +42,7 @@ "@date-fns/utc": "^2.1.1", "@formkit/auto-animate": "^0.8.4", "@huggingface/transformers": "^3.7.2", + "@lemonneko/crop-empty-pixels": "0.1.1", "@pixi/app": "^6.5.10", "@pixi/constants": "^6.5.10", "@pixi/core": "^6.5.10", diff --git a/packages/stage-ui/src/components/Scenarios/Dialogs/model-selector/model-selector.vue b/packages/stage-ui/src/components/Scenarios/Dialogs/model-selector/model-selector.vue index 156ccb2ad..d355d8401 100644 --- a/packages/stage-ui/src/components/Scenarios/Dialogs/model-selector/model-selector.vue +++ b/packages/stage-ui/src/components/Scenarios/Dialogs/model-selector/model-selector.vue @@ -1,10 +1,10 @@