mobile download

This commit is contained in:
Macbook
2026-05-28 14:44:19 +09:00
parent e2816b037f
commit 3503ef33f5
152 changed files with 11021 additions and 687 deletions
+19 -36
View File
@@ -1,50 +1,36 @@
/**
* 관심종목(즐겨찾기) / 보유종목 관리
* - DB(gc_watchlist)가 기준 저장소
* - localStorage(gc_favorites)는 오프라인 미러·UI 동기화용
* - DB(gc_watchlist / gc_holdings)가 기준 저장소
* - 메모리 캐시만 사용 (localStorage 미사용)
*/
import { addWatchlistItem, removeWatchlistItem } from './backendApi';
const FAV_KEY = 'gc_favorites';
const LEGACY_FAV_KEY = 'upbit_market_favorites';
const HOLD_KEY = 'gc_holdings';
/** 관심종목 변경 시 MarketSearchPanel·App 등이 동기화하도록 발행 */
export const FAVORITES_CHANGED_EVENT = 'gc-favorites-changed';
// ── 즐겨찾기 (관심종목) ─────────────────────────────────────────────────────
let favoritesCache: string[] | null = null;
let holdingsCache: string[] | null = null;
/** 구버전 MarketSearchPanel 키 → gc_favorites 로 1회 마이그레이션 */
function migrateLegacyFavorites(): void {
try {
const raw = localStorage.getItem(FAV_KEY);
if (raw) {
const current = JSON.parse(raw) as string[];
if (Array.isArray(current) && current.length > 0) return;
}
const legacy = localStorage.getItem(LEGACY_FAV_KEY);
if (!legacy) return;
const parsed = JSON.parse(legacy) as string[];
if (Array.isArray(parsed) && parsed.length > 0) {
saveFavorites(parsed, false);
}
} catch { /* ignore */ }
/** DB 로드 후 App·워크스페이스 훅에서 호출 */
export function initFavoritesFromDb(symbols: string[]): void {
favoritesCache = [...symbols];
window.dispatchEvent(new CustomEvent(FAVORITES_CHANGED_EVENT, { detail: favoritesCache }));
}
export function initHoldingsFromDb(symbols: string[]): void {
holdingsCache = [...symbols];
}
export function getFavorites(): string[] {
migrateLegacyFavorites();
try { return JSON.parse(localStorage.getItem(FAV_KEY) ?? '[]'); }
catch { return []; }
return favoritesCache ?? [];
}
export function saveFavorites(markets: string[], notify = true): void {
try {
localStorage.setItem(FAV_KEY, JSON.stringify(markets));
if (notify) {
window.dispatchEvent(new CustomEvent(FAVORITES_CHANGED_EVENT, { detail: markets }));
}
} catch { /* ignore */ }
favoritesCache = [...markets];
if (notify) {
window.dispatchEvent(new CustomEvent(FAVORITES_CHANGED_EVENT, { detail: markets }));
}
}
/**
@@ -76,15 +62,12 @@ export function isFavorite(market: string): boolean {
return getFavorites().includes(market);
}
// ── 보유종목 ─────────────────────────────────────────────────────────────────
export function getHoldings(): string[] {
try { return JSON.parse(localStorage.getItem(HOLD_KEY) ?? '[]'); }
catch { return []; }
return holdingsCache ?? [];
}
export function saveHoldings(markets: string[]): void {
try { localStorage.setItem(HOLD_KEY, JSON.stringify(markets)); } catch { /* ignore */ }
holdingsCache = [...markets];
}
/** 추가 → 변경 후 전체 목록 반환 (중복 무시) */