desktop 앱 적용
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
import { isDesktop } from './platform';
|
||||
|
||||
export interface DesktopBridge {
|
||||
openWidgetWindow: (instance: import('../types/floatingWidget').FloatingWidgetInstance) => Promise<void>;
|
||||
closeWidgetWindow: (id: string) => Promise<void>;
|
||||
focusWidgetWindow: (id: string) => Promise<void>;
|
||||
showNativeNotification: (title: string, body: string) => Promise<void>;
|
||||
checkForUpdates: () => Promise<{ available: boolean; version?: string; message?: string }>;
|
||||
getAppVersion: () => Promise<string>;
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
__goldenDesktopBridge?: DesktopBridge;
|
||||
}
|
||||
}
|
||||
|
||||
export function getDesktopBridge(): DesktopBridge | null {
|
||||
if (!isDesktop()) return null;
|
||||
return window.__goldenDesktopBridge ?? null;
|
||||
}
|
||||
|
||||
export async function showDesktopNativeNotification(title: string, body: string): Promise<void> {
|
||||
const bridge = getDesktopBridge();
|
||||
if (!bridge) return;
|
||||
try {
|
||||
await bridge.showNativeNotification(title, body);
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
}
|
||||
|
||||
export async function checkDesktopUpdates(): Promise<{ available: boolean; version?: string; message?: string }> {
|
||||
const bridge = getDesktopBridge();
|
||||
if (!bridge) return { available: false, message: '데스크톱 앱에서만 사용 가능합니다.' };
|
||||
return bridge.checkForUpdates();
|
||||
}
|
||||
|
||||
export async function getDesktopAppVersion(): Promise<string | null> {
|
||||
const bridge = getDesktopBridge();
|
||||
if (!bridge) return null;
|
||||
try {
|
||||
return await bridge.getAppVersion();
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/** 데스크톱 메인↔위젯 창 상태 동기화 (localStorage) */
|
||||
export const DESKTOP_SYNC_KEY = 'gc_desktop_sync';
|
||||
|
||||
export interface DesktopSyncState {
|
||||
selectedMarket?: string;
|
||||
selectedStrategyId?: number | null;
|
||||
theme?: string;
|
||||
updatedAt: number;
|
||||
}
|
||||
|
||||
export function readDesktopSync(): DesktopSyncState | null {
|
||||
try {
|
||||
const raw = localStorage.getItem(DESKTOP_SYNC_KEY);
|
||||
if (!raw) return null;
|
||||
return JSON.parse(raw) as DesktopSyncState;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export function writeDesktopSync(partial: Omit<DesktopSyncState, 'updatedAt'>): void {
|
||||
const prev = readDesktopSync() ?? { updatedAt: 0 };
|
||||
const next: DesktopSyncState = {
|
||||
...prev,
|
||||
...partial,
|
||||
updatedAt: Date.now(),
|
||||
};
|
||||
try {
|
||||
localStorage.setItem(DESKTOP_SYNC_KEY, JSON.stringify(next));
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
}
|
||||
|
||||
export function subscribeDesktopSync(cb: (state: DesktopSyncState) => void): () => void {
|
||||
const onStorage = (e: StorageEvent) => {
|
||||
if (e.key !== DESKTOP_SYNC_KEY) return;
|
||||
const state = readDesktopSync();
|
||||
if (state) cb(state);
|
||||
};
|
||||
window.addEventListener('storage', onStorage);
|
||||
return () => window.removeEventListener('storage', onStorage);
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/** 런타임 플랫폼 — web · desktop(Tauri) · mobile */
|
||||
export type RuntimePlatform = 'web' | 'desktop' | 'mobile';
|
||||
|
||||
export function isDesktop(): boolean {
|
||||
return typeof window !== 'undefined' && '__TAURI__' in window;
|
||||
}
|
||||
|
||||
export function isMobileCapacitor(): boolean {
|
||||
if (typeof window === 'undefined') return false;
|
||||
try {
|
||||
const cap = (window as Window & { Capacitor?: { isNativePlatform?: () => boolean } }).Capacitor;
|
||||
return cap?.isNativePlatform?.() === true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export function getRuntimePlatform(): RuntimePlatform {
|
||||
if (isDesktop()) return 'desktop';
|
||||
if (isMobileCapacitor()) return 'mobile';
|
||||
return 'web';
|
||||
}
|
||||
|
||||
export function isWeb(): boolean {
|
||||
return getRuntimePlatform() === 'web';
|
||||
}
|
||||
Reference in New Issue
Block a user