mirror of
https://github.com/ayangweb/BongoCat.git
synced 2026-03-12 17:51:48 +08:00
Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d9fb19aa2f | ||
|
|
ef17ba9ebc | ||
|
|
d69669bd3a | ||
|
|
2fc6ec9d2f | ||
|
|
50803eb2ce | ||
|
|
57892f3ab3 | ||
|
|
b59ec09354 | ||
|
|
49b5d9954c | ||
|
|
f1fac05975 | ||
|
|
6554508c30 | ||
|
|
7e7c1aded0 | ||
|
|
1e24c04da2 |
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -450,7 +450,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "bongo-cat"
|
||||
version = "0.8.2"
|
||||
version = "0.9.0"
|
||||
dependencies = [
|
||||
"fs_extra",
|
||||
"gilrs",
|
||||
|
||||
100
README.md
100
README.md
@@ -2,50 +2,25 @@
|
||||
|
||||
<div align="center">
|
||||
<div>
|
||||
<a href="https://github.com/ayangweb/BongoCat/releases">
|
||||
<img
|
||||
alt="Windows"
|
||||
src="https://img.shields.io/badge/-Windows-blue?style=flat-square&logo=data:image/svg+xml;base64,PHN2ZyB0PSIxNzI2MzA1OTcxMDA2IiBjbGFzcz0iaWNvbiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHAtaWQ9IjE1NDgiIHdpZHRoPSIxMjgiIGhlaWdodD0iMTI4Ij48cGF0aCBkPSJNNTI3LjI3NTU1MTYxIDk2Ljk3MTAzMDEzdjM3My45OTIxMDY2N2g0OTQuNTEzNjE5NzVWMTUuMDI2NzU3NTN6TTUyNy4yNzU1NTE2MSA5MjguMzIzNTA4MTVsNDk0LjUxMzYxOTc1IDgwLjUyMDI4MDQ5di00NTUuNjc3NDcxNjFoLTQ5NC41MTM2MTk3NXpNNC42NzA0NTEzNiA0NzAuODMzNjgyOTdINDIyLjY3Njg1OTI1VjExMC41NjM2ODE5N2wtNDE4LjAwNjQwNzg5IDY5LjI1Nzc5NzUzek00LjY3MDQ1MTM2IDg0Ni43Njc1OTcwM0w0MjIuNjc2ODU5MjUgOTE0Ljg2MDMxMDEzVjU1My4xNjYzMTcwM0g0LjY3MDQ1MTM2eiIgcC1pZD0iMTU0OSIgZmlsbD0iI2ZmZmZmZiI+PC9wYXRoPjwvc3ZnPg=="
|
||||
/>
|
||||
</a>
|
||||
<a href="https://github.com/ayangweb/BongoCat/releases">
|
||||
<img
|
||||
alt="MacOS"
|
||||
src="https://img.shields.io/badge/-MacOS-black?style=flat-square&logo=apple&logoColor=white"
|
||||
/>
|
||||
</a>
|
||||
<a href="https://github.com/ayangweb/BongoCat/releases">
|
||||
<img
|
||||
alt="Linux"
|
||||
src="https://img.shields.io/badge/-Linux-yellow?style=flat-square&logo=linux&logoColor=white"
|
||||
/>
|
||||
</a>
|
||||
<a href="https://github.com/ayangweb/BongoCat/releases"><img alt="Windows" src="https://img.shields.io/badge/-Windows-blue?style=flat-square&logo=data:image/svg+xml;base64,PHN2ZyB0PSIxNzI2MzA1OTcxMDA2IiBjbGFzcz0iaWNvbiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHAtaWQ9IjE1NDgiIHdpZHRoPSIxMjgiIGhlaWdodD0iMTI4Ij48cGF0aCBkPSJNNTI3LjI3NTU1MTYxIDk2Ljk3MTAzMDEzdjM3My45OTIxMDY2N2g0OTQuNTEzNjE5NzVWMTUuMDI2NzU3NTN6TTUyNy4yNzU1NTE2MSA5MjguMzIzNTA4MTVsNDk0LjUxMzYxOTc1IDgwLjUyMDI4MDQ5di00NTUuNjc3NDcxNjFoLTQ5NC41MTM2MTk3NXpNNC42NzA0NTEzNiA0NzAuODMzNjgyOTdINDIyLjY3Njg1OTI1VjExMC41NjM2ODE5N2wtNDE4LjAwNjQwNzg5IDY5LjI1Nzc5NzUzek00LjY3MDQ1MTM2IDg0Ni43Njc1OTcwM0w0MjIuNjc2ODU5MjUgOTE0Ljg2MDMxMDEzVjU1My4xNjYzMTcwM0g0LjY3MDQ1MTM2eiIgcC1pZD0iMTU0OSIgZmlsbD0iI2ZmZmZmZiI+PC9wYXRoPjwvc3ZnPg==" /></a>
|
||||
<a href="https://github.com/ayangweb/BongoCat/releases"><img alt="MacOS" src="https://img.shields.io/badge/-MacOS-black?style=flat-square&logo=apple&logoColor=white" /></a>
|
||||
<a href="https://github.com/ayangweb/BongoCat/releases"><img alt="Linux" src="https://img.shields.io/badge/-Linux-yellow?style=flat-square&logo=linux&logoColor=white" /></a>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
<a href="./LICENSE">
|
||||
<img
|
||||
src="https://img.shields.io/github/license/ayangweb/BongoCat?style=flat-square"
|
||||
/>
|
||||
</a>
|
||||
<a href="https://github.com/ayangweb/BongoCat/releases/latest">
|
||||
<img
|
||||
src="https://img.shields.io/github/package-json/v/ayangweb/BongoCat?style=flat-square"
|
||||
/>
|
||||
</a>
|
||||
<a href="https://github.com/ayangweb/BongoCat/releases">
|
||||
<img
|
||||
src="https://img.shields.io/github/downloads/ayangweb/BongoCat/total?style=flat-square"
|
||||
/>
|
||||
</a>
|
||||
<a href="./LICENSE"><img src="https://img.shields.io/github/license/ayangweb/BongoCat?style=flat-square" /></a>
|
||||
<a href="https://github.com/ayangweb/BongoCat/releases/latest"><img src="https://img.shields.io/github/package-json/v/ayangweb/BongoCat?style=flat-square"/></a>
|
||||
<a href="https://github.com/ayangweb/BongoCat/releases"><img src="https://img.shields.io/github/downloads/ayangweb/BongoCat/total?style=flat-square"/></a>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<a href="https://trendshift.io/developers/8507" target="_blank"><img src="https://trendshift.io/api/badge/developers/8507" alt="ayangweb | Trendshift" width="250" height="55" /></a>
|
||||
<a href="https://trendshift.io/repositories/14605" target="_blank"><img src="https://trendshift.io/api/badge/repositories/14605" alt="ayangweb%2FBongoCat | Trendshift" width="250" height="55" /></a>
|
||||
<a href="https://hellogithub.com/repository/7d23863fd4be47b39e816193ded385c9" target="_blank">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://abroad.hellogithub.com/v1/widgets/recommend.svg?rid=7d23863fd4be47b39e816193ded385c9&claim_uid=5ihRVIuTYBmSGtQ&theme=dark" />
|
||||
<source media="(prefers-color-scheme: light)" srcset="https://abroad.hellogithub.com/v1/widgets/recommend.svg?rid=7d23863fd4be47b39e816193ded385c9&claim_uid=5ihRVIuTYBmSGtQ&theme=neutral" />
|
||||
<img alt="Star History Chart" src="https://abroad.hellogithub.com/v1/widgets/recommend.svg?rid=7d23863fd4be47b39e816193ded385c9&claim_uid=5ihRVIuTYBmSGtQ&theme=neutral" />
|
||||
<img alt="Star History Chart" src="https://abroad.hellogithub.com/v1/widgets/recommend.svg?rid=7d23863fd4be47b39e816193ded385c9&claim_uid=5ihRVIuTYBmSGtQ&theme=neutral" width="250" height="55" />
|
||||
</picture>
|
||||
</a>
|
||||
</p>
|
||||
@@ -96,13 +71,56 @@
|
||||
|
||||
## 社区交流
|
||||
|
||||
<a href="https://qm.qq.com/q/AS3gNv2Vzy">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://i0.hdslb.com/bfs/openplatform/5ad8e4278c525cca6d3b4426c30b6d299d8a9654.png" />
|
||||
<source media="(prefers-color-scheme: light)" srcset="https://i0.hdslb.com/bfs/openplatform/599680ad67bc9f9f876f76069c2239e9a85bb54d.png" />
|
||||
<img alt="QQ Group" src="https://i0.hdslb.com/bfs/openplatform/599680ad67bc9f9f876f76069c2239e9a85bb54d.png" height="250" />
|
||||
</picture>
|
||||
</a>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>QQ 群 1</th>
|
||||
<th>QQ 群 2</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<a href="https://qm.qq.com/q/AS3gNv2Vzy">
|
||||
<picture>
|
||||
<source
|
||||
media="(prefers-color-scheme: dark)"
|
||||
srcset="https://i0.hdslb.com/bfs/openplatform/8ecdc4982ab01b59d7731fcca3ec26631a274560.png"
|
||||
/>
|
||||
<source
|
||||
media="(prefers-color-scheme: light)"
|
||||
srcset="https://i0.hdslb.com/bfs/openplatform/09f56580397063e1819c4c2ed63d07dee12720e1.png"
|
||||
/>
|
||||
<img
|
||||
alt="QQ Group 1"
|
||||
src="https://i0.hdslb.com/bfs/openplatform/09f56580397063e1819c4c2ed63d07dee12720e1.png"
|
||||
height="250"
|
||||
/>
|
||||
</picture>
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
<a href="https://qm.qq.com/q/TmltLAod2O">
|
||||
<picture>
|
||||
<source
|
||||
media="(prefers-color-scheme: dark)"
|
||||
srcset="https://i0.hdslb.com/bfs/openplatform/473c522487ff33e0f32b15466aeb0734f17161c8.png"
|
||||
/>
|
||||
<source
|
||||
media="(prefers-color-scheme: light)"
|
||||
srcset="https://i0.hdslb.com/bfs/openplatform/d5ae8c5af6ae1d0a1f066705ee822d1287384cf6.png"
|
||||
/>
|
||||
<img
|
||||
alt="QQ Group 2"
|
||||
src="https://i0.hdslb.com/bfs/openplatform/d5ae8c5af6ae1d0a1f066705ee822d1287384cf6.png"
|
||||
height="250"
|
||||
/>
|
||||
</picture>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
## 赞赏
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "bongo-cat",
|
||||
"type": "module",
|
||||
"version": "0.8.2",
|
||||
"version": "0.9.0",
|
||||
"private": true,
|
||||
"author": {
|
||||
"name": "ayangweb",
|
||||
@@ -39,6 +39,7 @@
|
||||
"dayjs": "^1.11.13",
|
||||
"es-toolkit": "^1.38.0",
|
||||
"is-url": "^1.2.4",
|
||||
"json5": "^2.2.3",
|
||||
"nanoid": "^5.1.5",
|
||||
"pinia": "^3.0.3",
|
||||
"pixi-live2d-display": "^0.4.0",
|
||||
|
||||
10
pnpm-lock.yaml
generated
10
pnpm-lock.yaml
generated
@@ -62,6 +62,9 @@ importers:
|
||||
is-url:
|
||||
specifier: ^1.2.4
|
||||
version: 1.2.4
|
||||
json5:
|
||||
specifier: ^2.2.3
|
||||
version: 2.2.3
|
||||
nanoid:
|
||||
specifier: ^5.1.5
|
||||
version: 5.1.5
|
||||
@@ -3227,6 +3230,11 @@ packages:
|
||||
json-stable-stringify-without-jsonify@1.0.1:
|
||||
resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==}
|
||||
|
||||
json5@2.2.3:
|
||||
resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==}
|
||||
engines: {node: '>=6'}
|
||||
hasBin: true
|
||||
|
||||
jsonc-eslint-parser@2.4.0:
|
||||
resolution: {integrity: sha512-WYDyuc/uFcGp6YtM2H0uKmUwieOuzeE/5YocFJLnLfclZ4inf3mRn8ZVy1s7Hxji7Jxm6Ss8gqpexD/GlKoGgg==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
@@ -8031,6 +8039,8 @@ snapshots:
|
||||
|
||||
json-stable-stringify-without-jsonify@1.0.1: {}
|
||||
|
||||
json5@2.2.3: {}
|
||||
|
||||
jsonc-eslint-parser@2.4.0:
|
||||
dependencies:
|
||||
acorn: 8.14.1
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "bongo-cat"
|
||||
version = "0.8.2"
|
||||
version = "0.9.0"
|
||||
description = "A Tauri App"
|
||||
authors = [ "ayangweb" ]
|
||||
edition = "2024"
|
||||
|
||||
@@ -57,7 +57,7 @@ pub fn platform(
|
||||
"window_did_resize" => {
|
||||
window_move_event();
|
||||
|
||||
if let Ok(size) = main_window.inner_size() {
|
||||
if let Ok(size) = main_window.outer_size() {
|
||||
let _ = main_window.emit_to(target, WINDOW_RESIZED_EVENT, size);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,8 @@
|
||||
"transparent": true,
|
||||
"decorations": false,
|
||||
"acceptFirstMouse": true,
|
||||
"skipTaskbar": true
|
||||
"skipTaskbar": true,
|
||||
"maximizable": false
|
||||
},
|
||||
{
|
||||
"label": "preference",
|
||||
|
||||
@@ -7,11 +7,12 @@
|
||||
"languages": [
|
||||
"English",
|
||||
"Vietnamese",
|
||||
"SimpChinese"
|
||||
"SimpChinese",
|
||||
"PortugueseBR"
|
||||
],
|
||||
"installMode": "both",
|
||||
"displayLanguageSelector": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,10 @@ html {
|
||||
|
||||
color-scheme: light;
|
||||
|
||||
body {
|
||||
--uno: transition-opacity-300;
|
||||
}
|
||||
|
||||
&.dark {
|
||||
color-scheme: dark;
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ useTauriListen<boolean>(LISTEN_KEY.UPDATE_APP, () => {
|
||||
message.loading({
|
||||
key: MESSAGE_KEY,
|
||||
duration: 0,
|
||||
content: t('components.proShortcut.updateApp.hints.checkingUpdates'),
|
||||
content: t('components.updateApp.hints.checkingUpdates'),
|
||||
})
|
||||
})
|
||||
|
||||
@@ -93,7 +93,7 @@ async function checkUpdate(visibleMessage = false) {
|
||||
|
||||
message.destroy(MESSAGE_KEY)
|
||||
} else if (visibleMessage) {
|
||||
message.success({ key: MESSAGE_KEY, content: t('components.proShortcut.updateApp.hints.alreadyLatest') })
|
||||
message.success({ key: MESSAGE_KEY, content: t('components.updateApp.hints.alreadyLatest') })
|
||||
}
|
||||
} catch (error) {
|
||||
if (!visibleMessage) return
|
||||
@@ -140,15 +140,15 @@ async function handleOk() {
|
||||
<template>
|
||||
<Modal
|
||||
v-model:open="state.open"
|
||||
:cancel-text="$t('components.proShortcut.updateApp.buttons.updateLater')"
|
||||
:cancel-text="$t('components.updateApp.buttons.updateLater')"
|
||||
centered
|
||||
:closable="false"
|
||||
:mask-closable="false"
|
||||
:title="$t('components.proShortcut.updateApp.title')"
|
||||
:title="$t('components.updateApp.title')"
|
||||
@ok="handleOk"
|
||||
>
|
||||
<template #okText>
|
||||
{{ state.downloading ? downloadProgress : $t('components.proShortcut.updateApp.buttons.updateNow') }}
|
||||
{{ state.downloading ? downloadProgress : $t('components.updateApp.buttons.updateNow') }}
|
||||
</template>
|
||||
|
||||
<Flex
|
||||
@@ -157,7 +157,7 @@ async function handleOk() {
|
||||
vertical
|
||||
>
|
||||
<Flex align="center">
|
||||
<span>更新版本:</span>
|
||||
<span>{{ $t('components.updateApp.labels.updateVersion') }}</span>
|
||||
<span>
|
||||
<span>{{ state.update?.currentVersion }} 👉 </span>
|
||||
<a
|
||||
@@ -169,12 +169,12 @@ async function handleOk() {
|
||||
</Flex>
|
||||
|
||||
<Flex align="center">
|
||||
<span>更新时间:</span>
|
||||
<span>{{ $t('components.updateApp.labels.updateTime') }}</span>
|
||||
<span>{{ state.update?.date }}</span>
|
||||
</Flex>
|
||||
|
||||
<Flex vertical>
|
||||
<span>更新日志:</span>
|
||||
<span>{{ $t('components.updateApp.labels.changelog') }}</span>
|
||||
|
||||
<VueMarkdown
|
||||
class="update-note max-h-40 overflow-auto"
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import type { CursorPoint } from '@/utils/monitor'
|
||||
|
||||
import { invoke } from '@tauri-apps/api/core'
|
||||
import { isEqual, mapValues } from 'es-toolkit'
|
||||
import { ref } from 'vue'
|
||||
import { getCurrentWebviewWindow } from '@tauri-apps/api/webviewWindow'
|
||||
import { cursorPosition } from '@tauri-apps/api/window'
|
||||
|
||||
import { INVOKE_KEY, LISTEN_KEY } from '../constants'
|
||||
|
||||
@@ -11,6 +9,7 @@ import { useTauriListen } from './useTauriListen'
|
||||
|
||||
import { useCatStore } from '@/stores/cat'
|
||||
import { useModelStore } from '@/stores/model'
|
||||
import { inBetween } from '@/utils/is'
|
||||
import { isWindows } from '@/utils/platform'
|
||||
|
||||
interface MouseButtonEvent {
|
||||
@@ -18,6 +17,11 @@ interface MouseButtonEvent {
|
||||
value: string
|
||||
}
|
||||
|
||||
export interface CursorPoint {
|
||||
x: number
|
||||
y: number
|
||||
}
|
||||
|
||||
interface MouseMoveEvent {
|
||||
kind: 'MouseMove'
|
||||
value: CursorPoint
|
||||
@@ -32,7 +36,6 @@ type DeviceEvent = MouseButtonEvent | MouseMoveEvent | KeyboardEvent
|
||||
|
||||
export function useDevice() {
|
||||
const modelStore = useModelStore()
|
||||
const lastCursorPoint = ref<CursorPoint>({ x: 0, y: 0 })
|
||||
const releaseTimers = new Map<string, NodeJS.Timeout>()
|
||||
const catStore = useCatStore()
|
||||
const { handlePress, handleRelease, handleMouseChange, handleMouseMove } = useModel()
|
||||
@@ -60,14 +63,25 @@ export function useDevice() {
|
||||
return nextKey
|
||||
}
|
||||
|
||||
const processMouseMove = (point: CursorPoint) => {
|
||||
const roundedValue = mapValues(point, Math.round)
|
||||
const handleCursorMove = async () => {
|
||||
const cursorPoint = await cursorPosition()
|
||||
|
||||
if (isEqual(lastCursorPoint.value, roundedValue)) return
|
||||
handleMouseMove(cursorPoint)
|
||||
|
||||
lastCursorPoint.value = roundedValue
|
||||
if (catStore.window.hideOnHover) {
|
||||
const appWindow = getCurrentWebviewWindow()
|
||||
const position = await appWindow.outerPosition()
|
||||
const { width, height } = await appWindow.innerSize()
|
||||
|
||||
return handleMouseMove(point)
|
||||
const isInWindow = inBetween(cursorPoint.x, position.x, position.x + width)
|
||||
&& inBetween(cursorPoint.y, position.y, position.y + height)
|
||||
|
||||
document.body.style.setProperty('opacity', isInWindow ? '0' : 'unset')
|
||||
|
||||
if (!catStore.window.passThrough) {
|
||||
appWindow.setIgnoreCursorEvents(isInWindow)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const handleAutoRelease = (key: string, delay = 100) => {
|
||||
@@ -117,7 +131,7 @@ export function useDevice() {
|
||||
case 'MouseRelease':
|
||||
return handleMouseChange(value, false)
|
||||
case 'MouseMove':
|
||||
return processMouseMove(value)
|
||||
return handleCursorMove()
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { CursorPoint } from '@/utils/monitor'
|
||||
import type { PhysicalPosition } from '@tauri-apps/api/dpi'
|
||||
|
||||
import { LogicalSize } from '@tauri-apps/api/dpi'
|
||||
import { resolveResource, sep } from '@tauri-apps/api/path'
|
||||
@@ -107,12 +107,12 @@ export function useModel() {
|
||||
live2d.setParameterValue(id, pressed)
|
||||
}
|
||||
|
||||
async function handleMouseMove(point: CursorPoint) {
|
||||
const monitor = await getCursorMonitor(point)
|
||||
async function handleMouseMove(cursorPoint: PhysicalPosition) {
|
||||
const monitor = await getCursorMonitor(cursorPoint)
|
||||
|
||||
if (!monitor) return
|
||||
|
||||
const { size, position, cursorPoint } = monitor
|
||||
const { size, position } = monitor
|
||||
|
||||
const xRatio = (cursorPoint.x - position.x) / size.width
|
||||
const yRatio = (cursorPoint.y - position.y) / size.height
|
||||
|
||||
47
src/composables/useWindowPosition.ts
Normal file
47
src/composables/useWindowPosition.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
import { PhysicalPosition } from '@tauri-apps/api/dpi'
|
||||
import { getCurrentWebviewWindow } from '@tauri-apps/api/webviewWindow'
|
||||
import { onMounted, ref, watch } from 'vue'
|
||||
|
||||
import { useCatStore } from '@/stores/cat'
|
||||
import { getCursorMonitor } from '@/utils/monitor'
|
||||
|
||||
const appWindow = getCurrentWebviewWindow()
|
||||
|
||||
export function useWindowPosition() {
|
||||
const catStore = useCatStore()
|
||||
const isMounted = ref(false)
|
||||
|
||||
const setWindowPosition = async () => {
|
||||
const monitor = await getCursorMonitor()
|
||||
|
||||
if (!monitor) return
|
||||
|
||||
const windowSize = await appWindow.outerSize()
|
||||
|
||||
switch (catStore.window.position) {
|
||||
case 'topLeft':
|
||||
return appWindow.setPosition(new PhysicalPosition(0, 0))
|
||||
case 'topRight':
|
||||
return appWindow.setPosition(new PhysicalPosition(monitor.size.width - windowSize.width, 0))
|
||||
case 'bottomLeft':
|
||||
return appWindow.setPosition(new PhysicalPosition(0, monitor.size.height - windowSize.height))
|
||||
default:
|
||||
return appWindow.setPosition(new PhysicalPosition(monitor.size.width - windowSize.width, monitor.size.height - windowSize.height))
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
await setWindowPosition()
|
||||
|
||||
isMounted.value = true
|
||||
|
||||
appWindow.onScaleChanged(setWindowPosition)
|
||||
})
|
||||
|
||||
watch(() => catStore.window.position, setWindowPosition)
|
||||
|
||||
return {
|
||||
isMounted,
|
||||
setWindowPosition,
|
||||
}
|
||||
}
|
||||
@@ -21,4 +21,5 @@ export const LANGUAGE = {
|
||||
ZH_CN: 'zh-CN',
|
||||
EN_US: 'en-US',
|
||||
VI_VN: 'vi-VN',
|
||||
PT_BR: 'pt-BR',
|
||||
} as const
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"pages": {
|
||||
"main": {
|
||||
"hints": {
|
||||
"redrawing": "Resizing..."
|
||||
"redrawing": "Redrawing..."
|
||||
}
|
||||
},
|
||||
"preference": {
|
||||
@@ -12,38 +12,48 @@
|
||||
"labels": {
|
||||
"modelSettings": "Model Settings",
|
||||
"mirrorMode": "Mirror Mode",
|
||||
"singleMode": "Show Last Key Only",
|
||||
"singleMode": "Single Key Mode",
|
||||
"mouseMirror": "Mouse Mirror",
|
||||
"windowSettings": "Window Settings",
|
||||
"passThrough": "Window Penetration",
|
||||
"alwaysOnTop": "Always On Top",
|
||||
"passThrough": "Pass Through",
|
||||
"alwaysOnTop": "Always on Top",
|
||||
"windowSize": "Window Size",
|
||||
"windowRadius": "Window Radius",
|
||||
"opacity": "Opacity",
|
||||
"autoReleaseDelay": "Auto Release Delay"
|
||||
"autoReleaseDelay": "Auto Release Delay",
|
||||
"hideOnHover": "Hide on Hover",
|
||||
"position": "Window Position"
|
||||
},
|
||||
"hints": {
|
||||
"mirrorMode": "When enabled, the model will be horizontally flipped.",
|
||||
"singleMode": "When enabled, only the last key pressed on each hand is displayed (prevents showing multiple hands when pressing multiple keys at once).",
|
||||
"mouseMirror": "When enabled, the mouse will mirror follow the hand movement.",
|
||||
"passThrough": "When enabled, the window will not affect operations on other applications.",
|
||||
"alwaysOnTop": "When enabled, the window will always stay above other applications.",
|
||||
"windowSize": "Move the mouse to the edge of the window or hold Shift and right-drag to resize.",
|
||||
"autoReleaseDelay": "Due to Windows not capturing the release events of certain system-level keys, they will be automatically treated as released after a timeout."
|
||||
"mirrorMode": "When enabled, the model will be mirrored horizontally.",
|
||||
"singleMode": "When enabled, only the last pressed key is displayed for each hand.",
|
||||
"mouseMirror": "When enabled, the mouse will mirror the hand movement.",
|
||||
"passThrough": "When enabled, clicks pass through the window without affecting it.",
|
||||
"alwaysOnTop": "When enabled, the window stays above all other windows.",
|
||||
"windowSize": "Move mouse to window edge, or hold Shift and right-drag to resize.",
|
||||
"autoReleaseDelay": "On Windows, some system keys cannot capture release events and will auto-release after timeout.",
|
||||
"hideOnHover": "When enabled, the window hides when mouse hovers over it.",
|
||||
"position": "Takes effect after the app starts, or when this parameter, window size, model, or screen resolution changes."
|
||||
},
|
||||
"options": {
|
||||
"topLeft": "Top Left",
|
||||
"topRight": "Top Right",
|
||||
"bottomLeft": "Bottom Left",
|
||||
"bottomRight": "Bottom Right"
|
||||
}
|
||||
},
|
||||
"general": {
|
||||
"title": "General",
|
||||
"labels": {
|
||||
"appSettings": "Application settings",
|
||||
"launchOnStartup": "Launch at startup",
|
||||
"showTaskbarIcon": "Show taskbar icon",
|
||||
"appearanceSettings": "Appearance settings",
|
||||
"themeMode": "Theme",
|
||||
"language": "Languages",
|
||||
"updateSettings": "Update settings",
|
||||
"autoCheckUpdate": "Check for updates automatically",
|
||||
"permissionsSettings": "Permission Settings",
|
||||
"appSettings": "Application Settings",
|
||||
"launchOnStartup": "Launch on Startup",
|
||||
"showTaskbarIcon": "Show Taskbar Icon",
|
||||
"appearanceSettings": "Appearance Settings",
|
||||
"themeMode": "Theme Mode",
|
||||
"language": "Language",
|
||||
"updateSettings": "Update Settings",
|
||||
"autoCheckUpdate": "Auto Check for Updates",
|
||||
"permissionsSettings": "Permissions Settings",
|
||||
"inputMonitoringPermission": "Input Monitoring Permission"
|
||||
},
|
||||
"options": {
|
||||
@@ -52,9 +62,9 @@
|
||||
"darkMode": "Dark"
|
||||
},
|
||||
"hints": {
|
||||
"showTaskbarIcon": "Once enabled, you can capture the window via OBS Studio.",
|
||||
"inputMonitoringPermission": "Enable input monitoring permission to receive system keyboard and mouse events to respond to your actions.",
|
||||
"inputMonitoringPermissionGuide": "If the permission is already enabled, first select it and click the \"-\" button to remove it. Then add it again manually and restart the application to ensure the permission takes effect."
|
||||
"showTaskbarIcon": "When enabled, the window can be captured via OBS Studio.",
|
||||
"inputMonitoringPermission": "Enable input monitoring to receive keyboard and mouse events from the system.",
|
||||
"inputMonitoringPermissionGuide": "If the permission is already enabled, select it and click the \"-\" button to remove it, then manually add it again and restart the app."
|
||||
},
|
||||
"status": {
|
||||
"authorized": "Authorized",
|
||||
@@ -68,34 +78,34 @@
|
||||
"model": {
|
||||
"title": "Model",
|
||||
"labels": {
|
||||
"deleteModel": "Delete model"
|
||||
"deleteModel": "Delete Model"
|
||||
},
|
||||
"hints": {
|
||||
"deleteSuccess": "Deleted successfully",
|
||||
"deleteSuccess": "Deleted Successfully",
|
||||
"deleteModel": "Are you sure you want to delete this model?",
|
||||
"importSuccess": "Import successful",
|
||||
"clickOrDragToImport": "Click or drag to import"
|
||||
"importSuccess": "Imported Successfully",
|
||||
"clickOrDragToImport": "Click or drag here to import"
|
||||
},
|
||||
"tooltips": {
|
||||
"createModel": "Create model",
|
||||
"convertModel": "Convert model",
|
||||
"moreModels": "More models"
|
||||
"createModel": "Create Model",
|
||||
"convertModel": "Convert Model",
|
||||
"moreModels": "More Models"
|
||||
}
|
||||
},
|
||||
"shortcut": {
|
||||
"title": "Shortcuts",
|
||||
"labels": {
|
||||
"toggleCat": "Show/Hide Cat",
|
||||
"togglePreferences": "Open Preferences",
|
||||
"toggleCat": "Toggle Cat",
|
||||
"togglePreferences": "Toggle Preferences",
|
||||
"mirrorMode": "Mirror Mode",
|
||||
"passThrough": "Window Penetration",
|
||||
"alwaysOnTop": "Always On Top"
|
||||
"passThrough": "Pass Through",
|
||||
"alwaysOnTop": "Always on Top"
|
||||
},
|
||||
"hints": {
|
||||
"toggleCat": "Toggle the cat window's visibility.",
|
||||
"togglePreferences": "Toggle the preferences window visibility.",
|
||||
"toggleCat": "Toggle the visibility of the cat window.",
|
||||
"togglePreferences": "Toggle the visibility of the preferences window.",
|
||||
"mirrorMode": "Toggle the cat's mirror mode.",
|
||||
"passThrough": "Toggle whether the cat window is click-through.",
|
||||
"passThrough": "Toggle whether the cat window is pass-through.",
|
||||
"alwaysOnTop": "Toggle whether the cat window stays on top."
|
||||
}
|
||||
},
|
||||
@@ -108,13 +118,13 @@
|
||||
"openSource": "Open Source"
|
||||
},
|
||||
"hints": {
|
||||
"appInfo": "Copy app information to include in bug reports.",
|
||||
"copySuccess": "Copied successfully"
|
||||
"appInfo": "Copy app information and provide it to bug issue.",
|
||||
"copySuccess": "Copied Successfully"
|
||||
},
|
||||
"buttons": {
|
||||
"checkUpdate": "Check for updates",
|
||||
"checkUpdate": "Check for Updates",
|
||||
"copy": "Copy",
|
||||
"feedbackIssues": "Report Issue",
|
||||
"feedbackIssues": "Feedback Issues",
|
||||
"viewLog": "View Logs"
|
||||
}
|
||||
}
|
||||
@@ -123,24 +133,24 @@
|
||||
"components": {
|
||||
"proShortcut": {
|
||||
"hints": {
|
||||
"pressRecordShortcut": "Press keys to record shortcut",
|
||||
"pressRecordShortcut": "Press to record shortcut",
|
||||
"clickRecordShortcut": "Click to record shortcut"
|
||||
}
|
||||
},
|
||||
"updateApp": {
|
||||
"title": "New Version Found 🥳",
|
||||
"labels": {
|
||||
"updateVersion": "Update Version: ",
|
||||
"updateTime": "Update Time: ",
|
||||
"changelog": "Changelog: "
|
||||
},
|
||||
"updateApp": {
|
||||
"title": "New version found 🥳",
|
||||
"labels": {
|
||||
"updateVersion": "Version: ",
|
||||
"updateTime": "Update time: ",
|
||||
"changelog": "Changelog: "
|
||||
},
|
||||
"hints": {
|
||||
"checkingUpdates": "Checking for updates...",
|
||||
"alreadyLatest": "You are already on the latest version 🎉"
|
||||
},
|
||||
"buttons": {
|
||||
"updateNow": "Update Now",
|
||||
"updateLater": "Update later"
|
||||
}
|
||||
"hints": {
|
||||
"checkingUpdates": "Checking for updates...",
|
||||
"alreadyLatest": "Already on the latest version 🎉"
|
||||
},
|
||||
"buttons": {
|
||||
"updateNow": "Update Now",
|
||||
"updateLater": "Update Later"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -150,16 +160,23 @@
|
||||
"preference": "Preferences...",
|
||||
"hideCat": "Hide Cat",
|
||||
"showCat": "Show Cat",
|
||||
"passThrough": "Window Penetration",
|
||||
"passThrough": "Pass Through",
|
||||
"windowSize": "Window Size",
|
||||
"opacity": "Opacity"
|
||||
}
|
||||
},
|
||||
"useTray": {
|
||||
"checkUpdate": "Check for updates",
|
||||
"openSource": "Source Code",
|
||||
"restartApp": "Restart",
|
||||
"quitApp": "Exit"
|
||||
"checkUpdate": "Check for Updates",
|
||||
"openSource": "Open Source",
|
||||
"restartApp": "Restart App",
|
||||
"quitApp": "Quit App"
|
||||
}
|
||||
},
|
||||
"utils": {
|
||||
"live2d": {
|
||||
"hints": {
|
||||
"notFound": "Model master configuration file not found, please ensure the model files are complete."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,11 +2,13 @@ import type { Language } from '@/stores/general'
|
||||
import type { Locale as AntdLocale } from 'ant-design-vue/es/locale'
|
||||
|
||||
import antdEnUS from 'ant-design-vue/locale/en_US'
|
||||
import antdPtBR from 'ant-design-vue/locale/pt_BR'
|
||||
import antdViVN from 'ant-design-vue/locale/vi_VN'
|
||||
import antdZhCN from 'ant-design-vue/locale/zh_CN'
|
||||
import { createI18n } from 'vue-i18n'
|
||||
|
||||
import enUS from './en-US.json'
|
||||
import ptBR from './pt-BR.json'
|
||||
import viVN from './vi-VN.json'
|
||||
import zhCN from './zh-CN.json'
|
||||
|
||||
@@ -20,6 +22,7 @@ export const i18n = createI18n({
|
||||
[LANGUAGE.ZH_CN]: zhCN,
|
||||
[LANGUAGE.EN_US]: enUS,
|
||||
[LANGUAGE.VI_VN]: viVN,
|
||||
[LANGUAGE.PT_BR]: ptBR,
|
||||
},
|
||||
})
|
||||
|
||||
@@ -28,6 +31,7 @@ export function getAntdLocale(language: Language = LANGUAGE.EN_US) {
|
||||
[LANGUAGE.ZH_CN]: antdZhCN,
|
||||
[LANGUAGE.EN_US]: antdEnUS,
|
||||
[LANGUAGE.VI_VN]: antdViVN,
|
||||
[LANGUAGE.PT_BR]: antdPtBR,
|
||||
}
|
||||
|
||||
return antdLanguage[language]
|
||||
|
||||
182
src/locales/pt-BR.json
Normal file
182
src/locales/pt-BR.json
Normal file
@@ -0,0 +1,182 @@
|
||||
{
|
||||
"pages": {
|
||||
"main": {
|
||||
"hints": {
|
||||
"redrawing": "Redimensionando..."
|
||||
}
|
||||
},
|
||||
"preference": {
|
||||
"title": "Preferências",
|
||||
"cat": {
|
||||
"title": "Gato",
|
||||
"labels": {
|
||||
"modelSettings": "Configurações do Modelo",
|
||||
"mirrorMode": "Modo Espelho",
|
||||
"singleMode": "Mostrar Apenas Última Tecla",
|
||||
"mouseMirror": "Espelho do Mouse",
|
||||
"windowSettings": "Configurações da Janela",
|
||||
"passThrough": "Janela Transparente",
|
||||
"alwaysOnTop": "Sempre no Topo",
|
||||
"windowSize": "Tamanho da Janela",
|
||||
"windowRadius": "Raio da Janela",
|
||||
"opacity": "Opacidade",
|
||||
"autoReleaseDelay": "Atraso de Liberação Automática",
|
||||
"hideOnHover": "Ocultar ao Passar o Mouse",
|
||||
"position": "Posição da Janela"
|
||||
},
|
||||
"hints": {
|
||||
"mirrorMode": "Quando ativado, o modelo será invertido horizontalmente.",
|
||||
"singleMode": "Quando ativado, apenas a última tecla pressionada em cada mão é exibida (evita mostrar múltiplas mãos ao pressionar várias teclas ao mesmo tempo).",
|
||||
"mouseMirror": "Quando ativado, o mouse espelhará o movimento da mão.",
|
||||
"passThrough": "Quando ativado, a janela não afetará operações em outros aplicativos.",
|
||||
"alwaysOnTop": "Quando ativado, a janela sempre ficará acima de outros aplicativos.",
|
||||
"windowSize": "Mova o mouse para a borda da janela ou segure Shift e arraste com o botão direito para redimensionar.",
|
||||
"autoReleaseDelay": "Devido ao Windows não capturar eventos de liberação de certas teclas de nível do sistema, elas serão automaticamente tratadas como liberadas após um tempo limite.",
|
||||
"hideOnHover": "Quando ativado, a janela será ocultada quando o mouse passar sobre ela.",
|
||||
"position": "Entra em vigor após inicializar o aplicativo ou quando este parâmetro, o tamanho da janela, o modelo ou a resolução de tela é alterado."
|
||||
},
|
||||
"options": {
|
||||
"topLeft": "Canto Superior Esquerdo",
|
||||
"topRight": "Canto Superior Direito",
|
||||
"bottomLeft": "Canto Inferior Esquerdo",
|
||||
"bottomRight": "Canto Inferior Direito"
|
||||
}
|
||||
},
|
||||
"general": {
|
||||
"title": "Geral",
|
||||
"labels": {
|
||||
"appSettings": "Configurações do aplicativo",
|
||||
"launchOnStartup": "Iniciar na inicialização",
|
||||
"showTaskbarIcon": "Mostrar ícone na barra de tarefas",
|
||||
"appearanceSettings": "Configurações de aparência",
|
||||
"themeMode": "Tema",
|
||||
"language": "Idiomas",
|
||||
"updateSettings": "Configurações de atualização",
|
||||
"autoCheckUpdate": "Verificar atualizações automaticamente",
|
||||
"permissionsSettings": "Configurações de Permissões",
|
||||
"inputMonitoringPermission": "Permissão de Monitoramento de Entrada"
|
||||
},
|
||||
"options": {
|
||||
"auto": "Sistema",
|
||||
"lightMode": "Claro",
|
||||
"darkMode": "Escuro"
|
||||
},
|
||||
"hints": {
|
||||
"showTaskbarIcon": "Uma vez ativado, você pode capturar a janela via OBS Studio.",
|
||||
"inputMonitoringPermission": "Ative a permissão de monitoramento de entrada para receber eventos de teclado e mouse do sistema para responder às suas ações.",
|
||||
"inputMonitoringPermissionGuide": "Se a permissão já estiver ativada, primeiro selecione-a e clique no botão \"-\" para removê-la. Em seguida, adicione-a novamente manualmente e reinicie o aplicativo para garantir que a permissão entre em vigor."
|
||||
},
|
||||
"status": {
|
||||
"authorized": "Autorizado",
|
||||
"authorize": "Ir para Ativar"
|
||||
},
|
||||
"buttons": {
|
||||
"openNow": "Abrir Agora",
|
||||
"openLater": "Abrir Mais Tarde"
|
||||
}
|
||||
},
|
||||
"model": {
|
||||
"title": "Modelo",
|
||||
"labels": {
|
||||
"deleteModel": "Excluir modelo"
|
||||
},
|
||||
"hints": {
|
||||
"deleteSuccess": "Excluído com sucesso",
|
||||
"deleteModel": "Tem certeza de que deseja excluir este modelo?",
|
||||
"importSuccess": "Importação bem-sucedida",
|
||||
"clickOrDragToImport": "Clique ou arraste para importar"
|
||||
},
|
||||
"tooltips": {
|
||||
"createModel": "Criar modelo",
|
||||
"convertModel": "Converter modelo",
|
||||
"moreModels": "Mais modelos"
|
||||
}
|
||||
},
|
||||
"shortcut": {
|
||||
"title": "Atalhos",
|
||||
"labels": {
|
||||
"toggleCat": "Mostrar/Ocultar Gato",
|
||||
"togglePreferences": "Abrir Preferências",
|
||||
"mirrorMode": "Modo Espelho",
|
||||
"passThrough": "Janela Transparente",
|
||||
"alwaysOnTop": "Sempre no Topo"
|
||||
},
|
||||
"hints": {
|
||||
"toggleCat": "Alternar a visibilidade da janela do gato.",
|
||||
"togglePreferences": "Alternar a visibilidade da janela de preferências.",
|
||||
"mirrorMode": "Alternar o modo espelho do gato.",
|
||||
"passThrough": "Alternar se a janela do gato é clicável.",
|
||||
"alwaysOnTop": "Alternar se a janela do gato permanece no topo."
|
||||
}
|
||||
},
|
||||
"about": {
|
||||
"title": "Sobre",
|
||||
"labels": {
|
||||
"aboutApp": "Sobre o Aplicativo",
|
||||
"appLog": "Logs do Aplicativo",
|
||||
"appInfo": "Informações do Aplicativo",
|
||||
"openSource": "Código Aberto"
|
||||
},
|
||||
"hints": {
|
||||
"appInfo": "Copiar informações do aplicativo para incluir em relatórios de bugs.",
|
||||
"copySuccess": "Copiado com sucesso"
|
||||
},
|
||||
"buttons": {
|
||||
"checkUpdate": "Verificar atualizações",
|
||||
"copy": "Copiar",
|
||||
"feedbackIssues": "Reportar Problema",
|
||||
"viewLog": "Ver Logs"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"proShortcut": {
|
||||
"hints": {
|
||||
"pressRecordShortcut": "Pressione as teclas para gravar atalho",
|
||||
"clickRecordShortcut": "Clique para gravar atalho"
|
||||
}
|
||||
},
|
||||
"updateApp": {
|
||||
"title": "Nova versão encontrada 🥳",
|
||||
"labels": {
|
||||
"updateVersion": "Versão: ",
|
||||
"updateTime": "Hora da atualização: ",
|
||||
"changelog": "Registro de alterações: "
|
||||
},
|
||||
"hints": {
|
||||
"checkingUpdates": "Verificando atualizações...",
|
||||
"alreadyLatest": "Você já está na versão mais recente 🎉"
|
||||
},
|
||||
"buttons": {
|
||||
"updateNow": "Atualizar Agora",
|
||||
"updateLater": "Atualizar mais tarde"
|
||||
}
|
||||
}
|
||||
},
|
||||
"composables": {
|
||||
"useSharedMenu": {
|
||||
"labels": {
|
||||
"preference": "Preferências...",
|
||||
"hideCat": "Ocultar Gato",
|
||||
"showCat": "Mostrar Gato",
|
||||
"passThrough": "Janela Transparente",
|
||||
"windowSize": "Tamanho da Janela",
|
||||
"opacity": "Opacidade"
|
||||
}
|
||||
},
|
||||
"useTray": {
|
||||
"checkUpdate": "Verificar atualizações",
|
||||
"openSource": "Código Fonte",
|
||||
"restartApp": "Reiniciar",
|
||||
"quitApp": "Sair"
|
||||
}
|
||||
},
|
||||
"utils": {
|
||||
"live2d": {
|
||||
"hints": {
|
||||
"notFound": "Arquivo de configuração principal do modelo não encontrado. Verifique se os arquivos do modelo estão completos."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,9 @@
|
||||
"windowSize": "Kích thước",
|
||||
"windowRadius": "Độ bo tròn cửa sổ",
|
||||
"opacity": "Độ mờ",
|
||||
"autoReleaseDelay": "Độ trễ tự động nhả phím"
|
||||
"autoReleaseDelay": "Độ trễ tự động nhả phím",
|
||||
"hideOnHover": "Ẩn khi di chuột",
|
||||
"position": "Vị trí cửa sổ"
|
||||
},
|
||||
"hints": {
|
||||
"mirrorMode": "Bật để lật ngang mô hình.",
|
||||
@@ -29,7 +31,15 @@
|
||||
"passThrough": "Bật để cửa sổ không ảnh hưởng đến thao tác trên ứng dụng khác.",
|
||||
"alwaysOnTop": "Bật để cửa sổ luôn nằm trên ứng dụng khác.",
|
||||
"windowSize": "Di chuyển chuột đến mép cửa sổ hoặc giữ Shift và kéo chuột phải để thay đổi kích thước.",
|
||||
"autoReleaseDelay": "Do Windows không bắt được sự kiện nhả của một số phím hệ thống, các phím đó sẽ được tự động xem như đã nhả sau khi hết thời gian chờ."
|
||||
"autoReleaseDelay": "Do Windows không bắt được sự kiện nhả của một số phím hệ thống, các phím đó sẽ được tự động xem như đã nhả sau khi hết thời gian chờ.",
|
||||
"hideOnHover": "Khi bật, cửa sổ sẽ ẩn khi chuột di chuyển vào.",
|
||||
"position": "Có hiệu lực sau khi khởi động ứng dụng hoặc khi tham số này, kích thước cửa sổ, mô hình hoặc độ phân giải màn hình thay đổi."
|
||||
},
|
||||
"options": {
|
||||
"topLeft": "Góc trên cùng bên trái",
|
||||
"topRight": "Góc trên cùng bên phải",
|
||||
"bottomLeft": "Góc dưới cùng bên trái",
|
||||
"bottomRight": "Góc dưới cùng bên phải"
|
||||
}
|
||||
},
|
||||
"general": {
|
||||
@@ -125,22 +135,22 @@
|
||||
"hints": {
|
||||
"pressRecordShortcut": "Nhấn phím/tổ hợp phím để ghi",
|
||||
"clickRecordShortcut": "Click để ghi phím tắt"
|
||||
}
|
||||
},
|
||||
"updateApp": {
|
||||
"title": "Đã tìm thấy phiên bản mới 🥳",
|
||||
"labels": {
|
||||
"updateVersion": "Phiên bản: ",
|
||||
"updateTime": "Thời gian cập nhật: ",
|
||||
"changelog": "Nhật ký thay đổi: "
|
||||
},
|
||||
"updateApp": {
|
||||
"title": "Đã tìm thấy phiên bản mới 🥳",
|
||||
"labels": {
|
||||
"updateVersion": "Phiên bản: ",
|
||||
"updateTime": "Thời gian cập nhật: ",
|
||||
"changelog": "Nhật ký thay đổi: "
|
||||
},
|
||||
"hints": {
|
||||
"checkingUpdates": "Đang kiểm tra cập nhật...",
|
||||
"alreadyLatest": "Bạn đang dùng phiên bản mới nhất 🎉"
|
||||
},
|
||||
"buttons": {
|
||||
"updateNow": "Cập nhật ngay",
|
||||
"updateLater": "Để sau"
|
||||
}
|
||||
"hints": {
|
||||
"checkingUpdates": "Đang kiểm tra cập nhật...",
|
||||
"alreadyLatest": "Bạn đang dùng phiên bản mới nhất 🎉"
|
||||
},
|
||||
"buttons": {
|
||||
"updateNow": "Cập nhật ngay",
|
||||
"updateLater": "Để sau"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -161,5 +171,12 @@
|
||||
"restartApp": "Khởi động lại",
|
||||
"quitApp": "Thoát"
|
||||
}
|
||||
},
|
||||
"utils": {
|
||||
"live2d": {
|
||||
"hints": {
|
||||
"notFound": "Không tìm thấy tệp cấu hình chính của mô hình, vui lòng xác nhận các tệp mô hình có đầy đủ không."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,9 @@
|
||||
"windowSize": "窗口尺寸",
|
||||
"windowRadius": "窗口圆角",
|
||||
"opacity": "不透明度",
|
||||
"autoReleaseDelay": "按键自动释放延迟"
|
||||
"autoReleaseDelay": "按键自动释放延迟",
|
||||
"hideOnHover": "鼠标移入隐藏",
|
||||
"position": "窗口位置"
|
||||
},
|
||||
"hints": {
|
||||
"mirrorMode": "启用后,模型将水平镜像翻转。",
|
||||
@@ -29,7 +31,15 @@
|
||||
"passThrough": "启用后,窗口不影响对其他应用程序的操作。",
|
||||
"alwaysOnTop": "启用后,窗口始终显示在其他应用程序上方。",
|
||||
"windowSize": "将鼠标移至窗口边缘,或按住 Shift 并右键拖动,也可以调整窗口大小。",
|
||||
"autoReleaseDelay": "由于 Windows 下部分系统级按键无法捕获释放事件,超时后将自动视为已释放。"
|
||||
"autoReleaseDelay": "由于 Windows 下部分系统级按键无法捕获释放事件,超时后将自动视为已释放。",
|
||||
"hideOnHover": "启用后,鼠标悬停在窗口上时,窗口会隐藏。",
|
||||
"position": "应用启动后,或当此参数、窗口尺寸、模型、电脑分辨率发生变化时生效。"
|
||||
},
|
||||
"options": {
|
||||
"topLeft": "左上角",
|
||||
"topRight": "右上角",
|
||||
"bottomLeft": "左下角",
|
||||
"bottomRight": "右下角"
|
||||
}
|
||||
},
|
||||
"general": {
|
||||
@@ -125,22 +135,22 @@
|
||||
"hints": {
|
||||
"pressRecordShortcut": "按下录制快捷键",
|
||||
"clickRecordShortcut": "点击录制快捷键"
|
||||
}
|
||||
},
|
||||
"updateApp": {
|
||||
"title": "发现新版本🥳",
|
||||
"labels": {
|
||||
"updateVersion": "更新版本:",
|
||||
"updateTime": "更新时间:",
|
||||
"changelog": "更新日志:"
|
||||
},
|
||||
"updateApp": {
|
||||
"title": "发现新版本🥳",
|
||||
"labels": {
|
||||
"updateVersion": "更新版本:",
|
||||
"updateTime": "更新时间:",
|
||||
"changelog": "更新日志:"
|
||||
},
|
||||
"hints": {
|
||||
"checkingUpdates": "正在检查更新...",
|
||||
"alreadyLatest": "当前已是最新版本🎉"
|
||||
},
|
||||
"buttons": {
|
||||
"updateNow": "立即更新",
|
||||
"updateLater": "稍后更新"
|
||||
}
|
||||
"hints": {
|
||||
"checkingUpdates": "正在检查更新...",
|
||||
"alreadyLatest": "当前已是最新版本🎉"
|
||||
},
|
||||
"buttons": {
|
||||
"updateNow": "立即更新",
|
||||
"updateLater": "稍后更新"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -161,5 +171,12 @@
|
||||
"restartApp": "重启应用",
|
||||
"quitApp": "退出应用"
|
||||
}
|
||||
},
|
||||
"utils": {
|
||||
"live2d": {
|
||||
"hints": {
|
||||
"notFound": "未找到模型主配置文件,请确认模型文件是否完整。"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import { useDevice } from '@/composables/useDevice'
|
||||
import { useGamepad } from '@/composables/useGamepad'
|
||||
import { useModel } from '@/composables/useModel'
|
||||
import { useSharedMenu } from '@/composables/useSharedMenu'
|
||||
import { useWindowPosition } from '@/composables/useWindowPosition'
|
||||
import { hideWindow, setAlwaysOnTop, setTaskbarVisibility, showWindow } from '@/plugins/window'
|
||||
import { useCatStore } from '@/stores/cat'
|
||||
import { useGeneralStore } from '@/stores/general.ts'
|
||||
@@ -32,6 +33,7 @@ const generalStore = useGeneralStore()
|
||||
const resizing = ref(false)
|
||||
const backgroundImagePath = ref<string>()
|
||||
const { stickActive } = useGamepad()
|
||||
const { isMounted, setWindowPosition } = useWindowPosition()
|
||||
|
||||
onMounted(startListening)
|
||||
|
||||
@@ -40,6 +42,8 @@ onUnmounted(handleDestroy)
|
||||
const debouncedResize = useDebounceFn(async () => {
|
||||
await handleResize()
|
||||
|
||||
await setWindowPosition()
|
||||
|
||||
resizing.value = false
|
||||
}, 100)
|
||||
|
||||
@@ -52,7 +56,7 @@ useEventListener('resize', () => {
|
||||
watch(() => modelStore.currentModel, async (model) => {
|
||||
if (!model) return
|
||||
|
||||
handleLoad()
|
||||
await handleLoad()
|
||||
|
||||
const path = join(model.path, 'resources', 'background.png')
|
||||
|
||||
@@ -76,6 +80,8 @@ watch(() => modelStore.currentModel, async (model) => {
|
||||
modelStore.supportKeys[fileName] = join(groupDir, file.name)
|
||||
}
|
||||
}
|
||||
|
||||
setWindowPosition()
|
||||
}, { deep: true, immediate: true })
|
||||
|
||||
watch([() => catStore.window.scale, modelSize], async ([scale, modelSize]) => {
|
||||
@@ -145,6 +151,7 @@ function handleMouseMove(event: MouseEvent) {
|
||||
|
||||
<template>
|
||||
<div
|
||||
v-show="isMounted"
|
||||
class="relative size-screen overflow-hidden children:(absolute size-full)"
|
||||
:class="{ '-scale-x-100': catStore.model.mirror }"
|
||||
:style="{
|
||||
@@ -174,7 +181,7 @@ function handleMouseMove(event: MouseEvent) {
|
||||
v-show="resizing"
|
||||
class="flex items-center justify-center bg-black"
|
||||
>
|
||||
<span class="text-center text-10vw text-white">
|
||||
<span class="text-center text-[10vw] text-white">
|
||||
{{ $t('pages.main.hints.redrawing') }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
<script setup lang="ts">
|
||||
import { Select, SelectOption } from 'ant-design-vue'
|
||||
|
||||
import ProListItem from '@/components/pro-list-item/index.vue'
|
||||
import { useCatStore } from '@/stores/cat'
|
||||
|
||||
const catStore = useCatStore()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ProListItem
|
||||
:description="$t('pages.preference.cat.hints.position')"
|
||||
:title="$t('pages.preference.cat.labels.position')"
|
||||
>
|
||||
<Select v-model:value="catStore.window.position">
|
||||
<SelectOption value="bottomRight">
|
||||
{{ $t('pages.preference.cat.options.bottomRight') }}
|
||||
</SelectOption>
|
||||
<SelectOption value="bottomLeft">
|
||||
{{ $t('pages.preference.cat.options.bottomLeft') }}
|
||||
</SelectOption>
|
||||
<SelectOption value="topLeft">
|
||||
{{ $t('pages.preference.cat.options.topLeft') }}
|
||||
</SelectOption>
|
||||
<SelectOption value="topRight">
|
||||
{{ $t('pages.preference.cat.options.topRight') }}
|
||||
</SelectOption>
|
||||
</Select>
|
||||
</ProListItem>
|
||||
</template>
|
||||
@@ -1,6 +1,8 @@
|
||||
<script setup lang="ts">
|
||||
import { InputNumber, Slider, Switch } from 'ant-design-vue'
|
||||
|
||||
import Position from './components/position/index.vue'
|
||||
|
||||
import ProList from '@/components/pro-list/index.vue'
|
||||
import ProListItem from '@/components/pro-list-item/index.vue'
|
||||
import { useCatStore } from '@/stores/cat'
|
||||
@@ -46,6 +48,8 @@ const catStore = useCatStore()
|
||||
</ProList>
|
||||
|
||||
<ProList :title="$t('pages.preference.cat.labels.windowSettings')">
|
||||
<Position />
|
||||
|
||||
<ProListItem
|
||||
:description="$t('pages.preference.cat.hints.passThrough')"
|
||||
:title="$t('pages.preference.cat.labels.passThrough')"
|
||||
@@ -60,6 +64,13 @@ const catStore = useCatStore()
|
||||
<Switch v-model:checked="catStore.window.alwaysOnTop" />
|
||||
</ProListItem>
|
||||
|
||||
<ProListItem
|
||||
:description="$t('pages.preference.cat.hints.hideOnHover')"
|
||||
:title="$t('pages.preference.cat.labels.hideOnHover')"
|
||||
>
|
||||
<Switch v-model:checked="catStore.window.hideOnHover" />
|
||||
</ProListItem>
|
||||
|
||||
<ProListItem
|
||||
:description="$t('pages.preference.cat.hints.windowSize')"
|
||||
:title="$t('pages.preference.cat.labels.windowSize')"
|
||||
@@ -68,6 +79,7 @@ const catStore = useCatStore()
|
||||
v-model:value="catStore.window.scale"
|
||||
addon-after="%"
|
||||
class="w-28"
|
||||
:max="500"
|
||||
:min="1"
|
||||
/>
|
||||
</ProListItem>
|
||||
|
||||
@@ -55,6 +55,9 @@ watch(() => generalStore.app.autostart, async (value) => {
|
||||
<Select.Option value="vi-VN">
|
||||
Tiếng Việt
|
||||
</Select.Option>
|
||||
<Select.Option value="pt-BR">
|
||||
Português
|
||||
</Select.Option>
|
||||
</Select>
|
||||
</ProListItem>
|
||||
</ProList>
|
||||
|
||||
@@ -15,6 +15,8 @@ export interface CatStore {
|
||||
scale: number
|
||||
opacity: number
|
||||
radius: number
|
||||
hideOnHover: boolean
|
||||
position: 'topLeft' | 'topRight' | 'bottomLeft' | 'bottomRight'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,6 +61,8 @@ export const useCatStore = defineStore('cat', () => {
|
||||
scale: 100,
|
||||
opacity: 100,
|
||||
radius: 0,
|
||||
hideOnHover: false,
|
||||
position: 'bottomRight',
|
||||
})
|
||||
|
||||
const init = () => {
|
||||
|
||||
@@ -3,3 +3,7 @@ export function isImage(value: string) {
|
||||
|
||||
return regex.test(value)
|
||||
}
|
||||
|
||||
export function inBetween(value: number, minimum: number, maximum: number) {
|
||||
return value >= minimum && value <= maximum
|
||||
}
|
||||
|
||||
@@ -3,11 +3,14 @@ import type { Cubism4InternalModel } from 'pixi-live2d-display'
|
||||
|
||||
import { convertFileSrc } from '@tauri-apps/api/core'
|
||||
import { readDir, readTextFile } from '@tauri-apps/plugin-fs'
|
||||
import JSON5 from 'json5'
|
||||
import { Cubism4ModelSettings, Live2DModel } from 'pixi-live2d-display'
|
||||
import { Application, Ticker } from 'pixi.js'
|
||||
|
||||
import { join } from './path'
|
||||
|
||||
import { i18n } from '@/locales'
|
||||
|
||||
Live2DModel.registerTicker(Ticker)
|
||||
|
||||
class Live2d {
|
||||
@@ -39,12 +42,12 @@ class Live2d {
|
||||
const modelFile = files.find(file => file.name.endsWith('.model3.json'))
|
||||
|
||||
if (!modelFile) {
|
||||
throw new Error('未找到模型主配置文件,请确认模型文件是否完整。')
|
||||
throw new Error(i18n.global.t('utils.live2d.hints.notFound'))
|
||||
}
|
||||
|
||||
const modelPath = join(path, modelFile.name)
|
||||
|
||||
const modelJSON = JSON.parse(await readTextFile(modelPath))
|
||||
const modelJSON = JSON5.parse(await readTextFile(modelPath))
|
||||
|
||||
const modelSettings = new Cubism4ModelSettings({
|
||||
...modelJSON,
|
||||
@@ -71,7 +74,11 @@ class Live2d {
|
||||
}
|
||||
|
||||
public destroy() {
|
||||
if (!this.model) return
|
||||
|
||||
this.model?.destroy()
|
||||
|
||||
this.model = null
|
||||
}
|
||||
|
||||
public resizeModel(modelSize: ModelSize) {
|
||||
|
||||
@@ -1,33 +1,20 @@
|
||||
import type { PhysicalPosition } from '@tauri-apps/api/window'
|
||||
|
||||
import { getCurrentWebviewWindow } from '@tauri-apps/api/webviewWindow'
|
||||
import { monitorFromPoint } from '@tauri-apps/api/window'
|
||||
import { mapValues } from 'es-toolkit'
|
||||
import { cursorPosition, monitorFromPoint } from '@tauri-apps/api/window'
|
||||
|
||||
import { isMac } from './platform'
|
||||
export async function getCursorMonitor(cursorPoint?: PhysicalPosition) {
|
||||
cursorPoint ??= await cursorPosition()
|
||||
|
||||
export interface CursorPoint {
|
||||
x: number
|
||||
y: number
|
||||
}
|
||||
const appWindow = getCurrentWebviewWindow()
|
||||
|
||||
export async function getCursorMonitor(point: CursorPoint) {
|
||||
let cursorPoint = point
|
||||
const scaleFactor = await appWindow.scaleFactor()
|
||||
|
||||
if (isMac) {
|
||||
const appWindow = getCurrentWebviewWindow()
|
||||
|
||||
const scaleFactor = await appWindow.scaleFactor()
|
||||
|
||||
cursorPoint = mapValues(cursorPoint, value => value * scaleFactor)
|
||||
}
|
||||
|
||||
const { x, y } = point
|
||||
const { x, y } = cursorPoint.toLogical(scaleFactor)
|
||||
|
||||
const monitor = await monitorFromPoint(x, y)
|
||||
|
||||
if (!monitor) return
|
||||
|
||||
return {
|
||||
...monitor,
|
||||
cursorPoint,
|
||||
}
|
||||
return monitor
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user