import { IStorage } from "./implement"; export class AndroidStorage extends IStorage { constructor() { super(); this.memoryCache = new Map(); // 内存缓存 } // 检查 Android 接口是否可用 isAvailable() { return typeof window.AndroidAsset !== "undefined"; } // 调用原生接口 async callNative(method, ...args) { if (!this.isAvailable()) { throw new Error("AndroidAsset not available"); } return window.AndroidAsset[method](...args); } // 基础操作 (使用 localStorage 作为后备) async get(key) { try { const value = await this.callNative("getItem", key); return value ? JSON.parse(value) : null; } catch { return this.memoryCache.get(key) || null; } } async set(key, value) { this.memoryCache.set(key, value); try { await this.callNative("setItem", key, JSON.stringify(value)); } catch { // 忽略原生存储失败 } } async remove(key) { this.memoryCache.delete(key); try { await this.callNative("removeItem", key); } catch {} } async clear() { this.memoryCache.clear(); try { await this.callNative("clear"); } catch {} } // 频道数据 (使用专用接口) async getChannels() { try { const data = await this.callNative("readChannelData"); if (data && !data.startsWith("ERROR:")) { // 解析频道数据并缓存 const channels = this.parseChannelData(data); this.memoryCache.set("channels", channels); return channels; } } catch {} return this.memoryCache.get("channels") || []; } async setChannels(channels) { this.memoryCache.set("channels", channels); // 原生端通过文件存储,这里只更新内存缓存 await this.setCacheMeta( "channels", new CacheMeta({ key: "channels", updatedAt: Date.now(), size: channels.length, }), ); } parseChannelData(text) { // 简单的 TXT 格式解析 const channels = []; const lines = text.split("\n"); let currentGroup = ""; for (const line of lines) { const trimmed = line.trim(); if (!trimmed) continue; if (trimmed.includes("#genre#")) { currentGroup = trimmed.split(",")[0]; } else if (trimmed.includes(",")) { const [name, url] = trimmed.split(",").map((s) => s.trim()); if (name && url) { const existing = channels.find( (c) => c.name === name && c.group === currentGroup, ); if (existing) { existing.urls.push(url); } else { channels.push( new Channel({ id: `${currentGroup}_${name}`, name, group: currentGroup, urls: [url], }), ); } } } } return channels; } async getGroups() { const channels = await this.getChannels(); const groups = new Set(channels.map((c) => c.group)); return Array.from(groups); } // 订阅源 async getSubscriptions() { return (await this.get("subscriptions")) || []; } async setSubscriptions(subs) { await this.set("subscriptions", subs); } // 线路有效性 (使用 SharedPreferences) async getValidity(url) { const all = await this.getAllValidity(); return all.find((v) => v.url === url); } async setValidity(url, validity) { const all = await this.getAllValidity(); const index = all.findIndex((v) => v.url === url); if (index >= 0) { all[index] = { ...validity, url }; } else { all.push({ ...validity, url }); } await this.set("validity", all); } async getAllValidity() { return (await this.get("validity")) || []; } // 用户偏好 async getPreferences() { return (await this.get("preferences")) || new Preferences(); } async setPreferences(prefs) { await this.set("preferences", prefs); } // 播放历史 async getHistory(limit = 50) { const all = (await this.get("history")) || []; return all.slice(-limit).reverse(); } async addHistory(item) { const all = (await this.get("history")) || []; all.push(item); // 保留最近 500 条 if (all.length > 500) { all.splice(0, all.length - 500); } await this.set("history", all); } async clearHistory() { await this.remove("history"); } // 缓存元数据 async getCacheMeta(key) { const all = (await this.get("cacheMeta")) || {}; return all[key]; } async setCacheMeta(key, meta) { const all = (await this.get("cacheMeta")) || {}; all[key] = { ...meta, key }; await this.set("cacheMeta", all); } async isCacheValid(key, ttl) { const meta = await this.getCacheMeta(key); if (!meta || !meta.updatedAt) return false; return Date.now() - meta.updatedAt < ttl; } }