fix(stage-tamagotchi): deadlock of window-state due to wrapped window-state call
Great thanks to @sumimakito for the fix! Co-authored-by: Makito <5277268+sumimakito@users.noreply.github.com>
This commit is contained in:
@@ -15,6 +15,10 @@
|
||||
"core:window:allow-set-focus",
|
||||
"core:window:allow-set-minimizable",
|
||||
"core:window:allow-set-visible-on-all-workspaces",
|
||||
"core:window:allow-set-position",
|
||||
"core:window:allow-available-monitors",
|
||||
"core:window:allow-current-monitor",
|
||||
"core:window:allow-primary-monitor",
|
||||
"mcp:default",
|
||||
"global-shortcut:allow-is-registered",
|
||||
"global-shortcut:allow-register",
|
||||
|
||||
@@ -27,8 +27,6 @@ pub fn run() {
|
||||
.plugin(tauri_plugin_window_state::Builder::default().build())
|
||||
.plugin(tauri_plugin_positioner::init())
|
||||
// Internal plugins
|
||||
.plugin(plugins::window::init())
|
||||
.plugin(plugins::window_persistence::init())
|
||||
.plugin(plugins::window_pass_through_on_hover::init())
|
||||
.plugin(plugins::window_router_link::init())
|
||||
.plugin(plugins::audio_transcription::init())
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
pub mod audio_transcription;
|
||||
pub mod audio_vad;
|
||||
pub mod window;
|
||||
pub mod window_pass_through_on_hover;
|
||||
pub mod window_persistence;
|
||||
pub mod window_router_link;
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
use tauri::{
|
||||
Monitor,
|
||||
Runtime,
|
||||
plugin::{Builder, TauriPlugin},
|
||||
};
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn get_display_info<R: Runtime>(
|
||||
window: tauri::Window<R>
|
||||
) -> Result<(Vec<Monitor>, Monitor), String> {
|
||||
let monitors = match window.available_monitors() {
|
||||
std::result::Result::Ok(monitors) => monitors,
|
||||
_ => vec![],
|
||||
};
|
||||
let primary_monitor = match window.primary_monitor() {
|
||||
std::result::Result::Ok(monitor) => match monitor {
|
||||
Some(monitor) => monitor,
|
||||
None => {
|
||||
return Err("Primary monitor not found".to_string());
|
||||
},
|
||||
},
|
||||
_ => return Err("Failed to get primary monitor".to_string()),
|
||||
};
|
||||
|
||||
Ok((monitors, primary_monitor))
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn get_current_window_info<R: Runtime>(
|
||||
window: tauri::Window<R>
|
||||
) -> Result<((u32, u32), (i32, i32)), String> {
|
||||
match window.current_monitor() {
|
||||
std::result::Result::Ok(optional_monitor) => match optional_monitor {
|
||||
Some(monitor) => {
|
||||
let monitor_size = monitor.size();
|
||||
let position = monitor.position();
|
||||
|
||||
Ok((
|
||||
(monitor_size.width, monitor_size.height),
|
||||
(position.x, position.y),
|
||||
))
|
||||
},
|
||||
_ => Ok(((0, 0), (0, 0))),
|
||||
},
|
||||
_ => Ok(((0, 0), (0, 0))),
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn set_position<R: Runtime>(
|
||||
window: tauri::Window<R>,
|
||||
x: i32,
|
||||
y: i32,
|
||||
) -> Result<(), String> {
|
||||
use tauri::Position;
|
||||
|
||||
window
|
||||
.set_position(Position::Physical(tauri::PhysicalPosition { x, y }))
|
||||
.map_err(|e| format!("Failed to set window position: {}", e))
|
||||
}
|
||||
|
||||
pub fn init<R: Runtime>() -> TauriPlugin<R> {
|
||||
Builder::new("proj-airi-tauri-plugin-window")
|
||||
.invoke_handler(tauri::generate_handler![
|
||||
get_display_info,
|
||||
get_current_window_info,
|
||||
set_position
|
||||
])
|
||||
.build()
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
use log::info;
|
||||
use tauri::{
|
||||
Manager,
|
||||
Result,
|
||||
RunEvent,
|
||||
Runtime,
|
||||
Window,
|
||||
plugin::{Builder, TauriPlugin},
|
||||
};
|
||||
use tauri_plugin_window_state::{AppHandleExt, WindowExt};
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn save<R: Runtime>(window: Window<R>) -> Result<()> {
|
||||
info!("Saving window state...");
|
||||
|
||||
window
|
||||
.app_handle()
|
||||
.save_window_state(tauri_plugin_window_state::StateFlags::all())
|
||||
.map_err(|e| format!("Failed to save window state: {}", e))
|
||||
.unwrap_or_else(|err| {
|
||||
info!("Failed to restore window state: {}", err);
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn restore<R: Runtime>(window: Window<R>) -> Result<()> {
|
||||
info!("Restoring window state...");
|
||||
|
||||
window
|
||||
.restore_state(tauri_plugin_window_state::StateFlags::all())
|
||||
.map_err(|e| format!("Failed to restore window state: {}", e))
|
||||
.unwrap_or_else(|err| {
|
||||
info!("Failed to restore window state: {}", err);
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn init<R: Runtime>() -> TauriPlugin<R> {
|
||||
Builder::new("proj-airi-tauri-plugin-window-persistence")
|
||||
.invoke_handler(tauri::generate_handler![save, restore,])
|
||||
.on_window_ready(|window| {
|
||||
window
|
||||
.restore_state(tauri_plugin_window_state::StateFlags::all())
|
||||
.map_err(|e| format!("Failed to restore window state: {}", e))
|
||||
.unwrap_or_else(|err| {
|
||||
info!("Failed to restore window state: {}", err);
|
||||
});
|
||||
})
|
||||
.on_event(|app, event| match event {
|
||||
RunEvent::Exit { .. } => {
|
||||
info!("Exiting app");
|
||||
info!("Exited app");
|
||||
|
||||
// Save window state on exit
|
||||
app
|
||||
.save_window_state(tauri_plugin_window_state::StateFlags::all())
|
||||
.map_err(|e| format!("Failed to save window state: {}", e))
|
||||
.unwrap_or_else(|err| {
|
||||
info!("Failed to save window state on exit: {}", err);
|
||||
});
|
||||
},
|
||||
RunEvent::ExitRequested { .. } => {
|
||||
info!("Requested Exiting app");
|
||||
info!("Requested Exited app");
|
||||
|
||||
app
|
||||
.save_window_state(tauri_plugin_window_state::StateFlags::all())
|
||||
.map_err(|e| format!("Failed to save window state: {}", e))
|
||||
.unwrap_or_else(|err| {
|
||||
info!("Failed to save window state on exit: {}", err);
|
||||
});
|
||||
},
|
||||
_ => {},
|
||||
})
|
||||
.build()
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
import type { Position } from '@tauri-apps/plugin-positioner'
|
||||
|
||||
import { computedAsync, until } from '@vueuse/core'
|
||||
|
||||
import { useAppRuntime } from './runtime'
|
||||
import { untilImported } from './tauri'
|
||||
|
||||
export function useTauriPositioner() {
|
||||
const { platform, isInitialized } = useAppRuntime()
|
||||
|
||||
const tauriPositionerApi = computedAsync(async () => {
|
||||
await until(isInitialized).toBeTruthy()
|
||||
|
||||
if (platform.value !== 'web') {
|
||||
return untilImported(() => import('@tauri-apps/plugin-positioner'), console.warn)
|
||||
}
|
||||
})
|
||||
|
||||
async function ensureImported() {
|
||||
await until(isInitialized).toBeTruthy()
|
||||
|
||||
if (platform.value === 'web') {
|
||||
console.warn('Attempted to use Tauri positioner in web platform')
|
||||
return
|
||||
}
|
||||
|
||||
await until(tauriPositionerApi).toBeTruthy()
|
||||
const imported = await tauriPositionerApi.value
|
||||
if (!imported) {
|
||||
throw new Error('Tauri positioner API not available')
|
||||
}
|
||||
}
|
||||
|
||||
async function moveWindow(to: Position) {
|
||||
await ensureImported()
|
||||
return tauriPositionerApi.value?.moveWindow(to)
|
||||
}
|
||||
|
||||
return {
|
||||
moveWindow,
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,14 @@
|
||||
import type {
|
||||
DisplayInfo,
|
||||
Monitor,
|
||||
Point,
|
||||
Size,
|
||||
} from './tauri'
|
||||
import type { Monitor } from '@tauri-apps/api/window'
|
||||
|
||||
import type { DisplayInfo, Point, Size } from './tauri'
|
||||
|
||||
import { useThrottleFn, watchThrottled } from '@vueuse/core'
|
||||
import { computed, readonly, ref } from 'vue'
|
||||
|
||||
import { useAppRuntime } from './runtime'
|
||||
import { useTauriCore } from './tauri'
|
||||
import { useTauriWindow } from './tauri'
|
||||
import { useTauriPointAndWindowFrame } from './tauri-window-pass-through-on-hover'
|
||||
import { useTauriWindowState } from './tauri-window-state'
|
||||
|
||||
export interface WindowPersistenceConfig {
|
||||
autoSave?: boolean
|
||||
@@ -42,8 +40,9 @@ export function useWindowPersistence(config: WindowPersistenceConfig = {}) {
|
||||
} = config
|
||||
|
||||
const { platform } = useAppRuntime()
|
||||
const { invoke } = useTauriCore()
|
||||
const { windowFrame } = useTauriPointAndWindowFrame()
|
||||
const { saveWindowState, restoreStateCurrent } = useTauriWindowState()
|
||||
const { setPosition, getAvailableMonitors, getPrimaryMonitor } = useTauriWindow()
|
||||
|
||||
// Debounced save function (declare early to avoid usage before definition)
|
||||
const throttledSave = useThrottleFn(() => savePosition(), savePeriod)
|
||||
@@ -144,7 +143,7 @@ export function useWindowPersistence(config: WindowPersistenceConfig = {}) {
|
||||
}
|
||||
|
||||
try {
|
||||
// invoke('plugin:proj-airi-tauri-plugin-window-persistence|save')
|
||||
saveWindowState()
|
||||
|
||||
return true
|
||||
}
|
||||
@@ -163,7 +162,7 @@ export function useWindowPersistence(config: WindowPersistenceConfig = {}) {
|
||||
isRestoring.value = true
|
||||
|
||||
// Restore window state using Tauri plugin
|
||||
// await invoke('plugin:proj-airi-tauri-plugin-window-persistence|restore')
|
||||
await restoreStateCurrent()
|
||||
|
||||
// Ensure the restored position is within bounds
|
||||
if (constrainToDisplays && currentWindowPosition.value) {
|
||||
@@ -228,7 +227,7 @@ export function useWindowPersistence(config: WindowPersistenceConfig = {}) {
|
||||
|
||||
try {
|
||||
isPositioning.value = true
|
||||
await invoke('plugin:proj-airi-tauri-plugin-window|set_position', { x: pos.x, y: pos.y })
|
||||
await setPosition(pos.x, pos.y)
|
||||
|
||||
if (autoSave) {
|
||||
throttledSave()
|
||||
@@ -418,7 +417,18 @@ export function useWindowPersistence(config: WindowPersistenceConfig = {}) {
|
||||
return
|
||||
|
||||
try {
|
||||
const [monitors, primaryMonitor] = (await invoke('plugin:proj-airi-tauri-plugin-window|get_display_info'))!
|
||||
const monitors = await getAvailableMonitors()
|
||||
if (!monitors || monitors.length === 0) {
|
||||
console.warn('[WindowPersistence] Failed to get available monitors')
|
||||
return
|
||||
}
|
||||
|
||||
const primaryMonitor = await getPrimaryMonitor()
|
||||
if (!primaryMonitor) {
|
||||
console.warn('[WindowPersistence] Failed to get primary monitor')
|
||||
return
|
||||
}
|
||||
|
||||
displayInfo.value = {
|
||||
monitors,
|
||||
primaryMonitor,
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
import { computedAsync, until } from '@vueuse/core'
|
||||
|
||||
import { useAppRuntime } from './runtime'
|
||||
import { untilImported } from './tauri'
|
||||
|
||||
export enum StateFlags {
|
||||
SIZE = 1,
|
||||
POSITION = 2,
|
||||
MAXIMIZED = 4,
|
||||
VISIBLE = 8,
|
||||
DECORATIONS = 16,
|
||||
FULLSCREEN = 32,
|
||||
ALL = 63,
|
||||
}
|
||||
|
||||
export function useTauriWindowState() {
|
||||
const { platform, isInitialized } = useAppRuntime()
|
||||
|
||||
const tauriWindowStateApi = computedAsync(async () => {
|
||||
await until(isInitialized).toBeTruthy()
|
||||
|
||||
if (platform.value !== 'web') {
|
||||
return untilImported(() => import('@tauri-apps/plugin-window-state'), console.warn)
|
||||
}
|
||||
})
|
||||
|
||||
async function ensureImported() {
|
||||
await until(isInitialized).toBeTruthy()
|
||||
|
||||
if (platform.value === 'web') {
|
||||
console.warn('Attempted to save window state in web platform')
|
||||
return
|
||||
}
|
||||
|
||||
await until(tauriWindowStateApi).toBeTruthy()
|
||||
const imported = await tauriWindowStateApi.value
|
||||
if (!imported) {
|
||||
throw new Error('Tauri window state API not available')
|
||||
}
|
||||
}
|
||||
|
||||
async function saveWindowState(stateFlag?: StateFlags) {
|
||||
await ensureImported()
|
||||
if (stateFlag != null) {
|
||||
return tauriWindowStateApi.value?.saveWindowState(stateFlag)
|
||||
}
|
||||
else {
|
||||
return tauriWindowStateApi.value?.saveWindowState(tauriWindowStateApi.value.StateFlags.ALL)
|
||||
}
|
||||
}
|
||||
|
||||
async function restoreState(stateFlag?: StateFlags, windowLabel = 'main') {
|
||||
await ensureImported()
|
||||
if (stateFlag != null) {
|
||||
return tauriWindowStateApi.value?.restoreState(windowLabel, stateFlag)
|
||||
}
|
||||
else {
|
||||
return tauriWindowStateApi.value?.restoreState(windowLabel, tauriWindowStateApi.value.StateFlags.ALL)
|
||||
}
|
||||
}
|
||||
|
||||
async function restoreStateCurrent(stateFlag?: StateFlags) {
|
||||
await ensureImported()
|
||||
if (stateFlag != null) {
|
||||
return tauriWindowStateApi.value?.restoreStateCurrent(stateFlag)
|
||||
}
|
||||
else {
|
||||
return tauriWindowStateApi.value?.restoreStateCurrent(tauriWindowStateApi.value.StateFlags.ALL)
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
saveWindowState,
|
||||
restoreState,
|
||||
restoreStateCurrent,
|
||||
}
|
||||
}
|
||||
@@ -1,19 +1,18 @@
|
||||
import type { InvokeArgs, InvokeOptions } from '@tauri-apps/api/core'
|
||||
import type { EventCallback, EventName, UnlistenFn } from '@tauri-apps/api/event'
|
||||
import type { Position } from '@tauri-apps/plugin-positioner'
|
||||
import type { StateFlags } from '@tauri-apps/plugin-window-state'
|
||||
import type { Monitor } from '@tauri-apps/api/window'
|
||||
|
||||
import { withRetry } from '@moeru/std'
|
||||
import { computedAsync, until } from '@vueuse/core'
|
||||
|
||||
import { useAppRuntime } from './runtime'
|
||||
|
||||
async function untilNoError<T>(fn: () => Promise<T>, onError?: (err?: unknown | null) => void): Promise<T> {
|
||||
export async function untilNoError<T>(fn: () => Promise<T>, onError?: (err?: unknown | null) => void): Promise<T> {
|
||||
const fnRetry = withRetry(fn, { retryDelay: 5000, retry: 5, onError })
|
||||
return await fnRetry()
|
||||
}
|
||||
|
||||
async function untilImported<T>(fn: () => Promise<T>, onError?: (err?: unknown | null) => void): Promise<T> {
|
||||
export async function untilImported<T>(fn: () => Promise<T>, onError?: (err?: unknown | null) => void): Promise<T> {
|
||||
return await untilNoError(fn, onError)
|
||||
}
|
||||
|
||||
@@ -57,17 +56,6 @@ export interface AiriTamagotchiEvents extends Events {
|
||||
'mcp_plugin_destroyed': undefined
|
||||
}
|
||||
|
||||
export interface Monitor {
|
||||
name: string
|
||||
size: { width: number, height: number }
|
||||
position: { x: number, y: number }
|
||||
workArea: {
|
||||
position: { x: number, y: number }
|
||||
size: { width: number, height: number }
|
||||
}
|
||||
scale_factor: number
|
||||
}
|
||||
|
||||
export interface DisplayInfo {
|
||||
monitors: Monitor[]
|
||||
primaryMonitor: Monitor
|
||||
@@ -157,41 +145,12 @@ export interface InvokeMethods {
|
||||
'plugin:proj-airi-tauri-plugin-window-pass-through-on-hover|start_pass_through': { args: undefined, options: undefined, returns: void }
|
||||
'plugin:proj-airi-tauri-plugin-window-pass-through-on-hover|stop_pass_through': { args: undefined, options: undefined, returns: void }
|
||||
|
||||
// Plugin - Window
|
||||
'plugin:proj-airi-tauri-plugin-window|get_display_info': {
|
||||
args: undefined
|
||||
options: undefined
|
||||
returns: [Monitor[], Monitor]
|
||||
}
|
||||
'plugin:proj-airi-tauri-plugin-window|get_current_window_info': {
|
||||
args: undefined
|
||||
options: undefined
|
||||
returns: [[number, number], [number, number]]
|
||||
}
|
||||
'plugin:proj-airi-tauri-plugin-window|set_position': {
|
||||
args: { x: number, y: number }
|
||||
options: undefined
|
||||
returns: void
|
||||
}
|
||||
|
||||
// Plugin - WindowRouterLink
|
||||
'plugin:proj-airi-tauri-plugin-window-router-link|go': {
|
||||
args: { route: string, windowLabel?: string } | undefined
|
||||
options: undefined
|
||||
returns: void
|
||||
}
|
||||
|
||||
// // Plugin - Window Persistence
|
||||
// 'plugin:proj-airi-tauri-plugin-window-persistence|save': {
|
||||
// args: undefined
|
||||
// options: undefined
|
||||
// returns: void
|
||||
// }
|
||||
// 'plugin:proj-airi-tauri-plugin-window-persistence|restore': {
|
||||
// args: undefined
|
||||
// options: undefined
|
||||
// returns: void
|
||||
// }
|
||||
}
|
||||
|
||||
interface InvokeMethodShape {
|
||||
@@ -234,89 +193,107 @@ export function useTauriCore<IM extends Record<keyof IM, InvokeMethodShape> = In
|
||||
|
||||
return {
|
||||
invoke,
|
||||
core: tauriCoreApi,
|
||||
}
|
||||
}
|
||||
|
||||
export function useTauriPositioner() {
|
||||
export function useTauriDpi() {
|
||||
const { platform, isInitialized } = useAppRuntime()
|
||||
|
||||
const tauriPositionerApi = computedAsync(async () => {
|
||||
const tauriDpiApi = computedAsync(async () => {
|
||||
await until(isInitialized).toBeTruthy()
|
||||
|
||||
if (platform.value !== 'web') {
|
||||
return untilImported(() => import('@tauri-apps/plugin-positioner'), console.warn)
|
||||
return untilImported(() => import('@tauri-apps/api/window'), console.warn)
|
||||
}
|
||||
})
|
||||
|
||||
async function ensureImported() {
|
||||
await until(isInitialized).toBeTruthy()
|
||||
|
||||
if (platform.value === 'web') {
|
||||
console.warn('Attempted to use Tauri positioner in web platform')
|
||||
return
|
||||
}
|
||||
|
||||
await until(tauriPositionerApi).toBeTruthy()
|
||||
const imported = await tauriPositionerApi.value
|
||||
async function createLogicalPosition(x: number, y: number) {
|
||||
const imported = await tauriDpiApi.value
|
||||
if (!imported) {
|
||||
throw new Error('Tauri positioner API not available')
|
||||
throw new Error('Tauri DPI API not available')
|
||||
}
|
||||
}
|
||||
|
||||
async function moveWindow(to: Position) {
|
||||
await ensureImported()
|
||||
return tauriPositionerApi.value?.moveWindow(to)
|
||||
return new imported.LogicalPosition(x, y)
|
||||
}
|
||||
|
||||
return {
|
||||
moveWindow,
|
||||
createLogicalPosition,
|
||||
}
|
||||
}
|
||||
|
||||
export function useTauriWindowState() {
|
||||
export function useTauriWindow() {
|
||||
const { platform, isInitialized } = useAppRuntime()
|
||||
const { createLogicalPosition } = useTauriDpi()
|
||||
|
||||
const tauriWindowStateApi = computedAsync(async () => {
|
||||
const tauriWindowApi = computedAsync(async () => {
|
||||
await until(isInitialized).toBeTruthy()
|
||||
|
||||
if (platform.value !== 'web') {
|
||||
return untilImported(() => import('@tauri-apps/plugin-window-state'), console.warn)
|
||||
return untilImported(() => import('@tauri-apps/api/window'), console.warn)
|
||||
}
|
||||
})
|
||||
|
||||
async function ensureImported() {
|
||||
async function _ensureImported() {
|
||||
await until(isInitialized).toBeTruthy()
|
||||
|
||||
if (platform.value === 'web') {
|
||||
console.warn('Attempted to save window state in web platform')
|
||||
return
|
||||
throw new Error('Tauri Window API is not available in web platform')
|
||||
}
|
||||
|
||||
await until(tauriWindowStateApi).toBeTruthy()
|
||||
const imported = await tauriWindowStateApi.value
|
||||
await until(tauriWindowApi).toBeTruthy()
|
||||
const imported = await tauriWindowApi.value
|
||||
if (!imported) {
|
||||
throw new Error('Tauri window state API not available')
|
||||
throw new Error('Tauri Window API not available')
|
||||
}
|
||||
|
||||
return imported
|
||||
}
|
||||
|
||||
async function getCurrentMonitor() {
|
||||
try {
|
||||
return await _ensureImported().then(imported => imported.currentMonitor())
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Failed to get current monitor:', error)
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
|
||||
async function saveWindowState(stateFlag: StateFlags) {
|
||||
await ensureImported()
|
||||
return tauriWindowStateApi.value?.saveWindowState(stateFlag)
|
||||
async function getAvailableMonitors() {
|
||||
try {
|
||||
return await _ensureImported().then(imported => imported.availableMonitors())
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Failed to get available monitors:', error)
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
async function restoreState(stateFlag: StateFlags, windowLabel = 'main') {
|
||||
await ensureImported()
|
||||
return tauriWindowStateApi.value?.restoreState(windowLabel, stateFlag)
|
||||
async function getPrimaryMonitor() {
|
||||
try {
|
||||
return await _ensureImported().then(imported => imported.primaryMonitor())
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Failed to get primary monitor:', error)
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
|
||||
async function restoreStateCurrent(stateFlag: StateFlags) {
|
||||
await ensureImported()
|
||||
return tauriWindowStateApi.value?.restoreStateCurrent(stateFlag)
|
||||
async function setPosition(x: number, y: number) {
|
||||
try {
|
||||
const imported = await _ensureImported()
|
||||
const window = imported.getCurrentWindow()
|
||||
return await window.setPosition(await createLogicalPosition(x, y))
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Failed to set window position:', error)
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
saveWindowState,
|
||||
restoreState,
|
||||
restoreStateCurrent,
|
||||
getAvailableMonitors,
|
||||
getCurrentMonitor,
|
||||
getPrimaryMonitor,
|
||||
setPosition,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
declare module '*.vue' {
|
||||
import type { DefineComponent } from 'vue'
|
||||
|
||||
const component: DefineComponent<object, object, any>
|
||||
export default component
|
||||
}
|
||||
-14
@@ -1,14 +0,0 @@
|
||||
declare module '*.js?url' {
|
||||
const content: string
|
||||
export default content
|
||||
}
|
||||
|
||||
declare module '*.wasm?url' {
|
||||
const content: string
|
||||
export default content
|
||||
}
|
||||
|
||||
declare module '*.cjs?url' {
|
||||
const content: string
|
||||
export default content
|
||||
}
|
||||
Reference in New Issue
Block a user