Files
spark-store/src/composables/useAppState.ts
T
xiyidaiwa d7bdcf3680 fix: 标签策略启动初始化加固 + 已安装应用过滤/统计性能优化
- 标签优先显示策略 initTagPriorityStrategy 提到 App.vue onMounted 统一调用,
  消除组件挂载顺序导致先读内存默认 auto 的竞态窗口(AppDetailModal 移除重复调用)
- InstalledAppsModal 过滤逻辑合并为单次遍历(保留 hasOrigin 双来源语义)
- 统计 apm/spark/total 改为基于 searchFilteredApps 单次遍历
- canOpenDetail 补充业务含义注释与可读性变量
- 将 App.vue 重构的 9 个 composable 纳入版本管理
- 验证:vue-tsc 0 / eslint 0 / dpkg-buildpackage 打包 spark-store_5.2.1.24-test 成功
2026-08-12 23:16:17 +08:00

168 lines
6.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* useAppState —— 跨 composable 共享的全局原始响应式状态(单例)。
*
* 设计说明(避免循环依赖与重复实例化):
* App.vue 原文件中的逻辑被拆分到多个 composableuseCatalog / useRanking /
* useAppDetail / useInstalledApps / useFavorites / useAccountSync / useDownloads)。
* 这些 composable 之间存在大量共享状态(apps / currentApp / installedApps /
* favorite* / 各类弹窗开关等)。若各自持有会出现多实例与状态不同步,并引发循环依赖。
*
* 故把"贯穿整个应用生命周期的全局原始状态"集中在本模块以单例形式导出,
* 所有 composable 与 App.vue 均从本模块取用同一份 ref 实例。
* 这与现有 global/authState.ts、global/storeConfig.ts 的单例风格一致。
*
* 本模块**只持有状态与极少量纯派生 computed**,不含任何业务逻辑/副作用,
* 确保拆分前后运行时行为完全一致(7 维度审计:功能/状态一致)。
*
* 注意:currentApp / currentAppSparkInstalled / currentAppApmInstalled 同时在
* storeConfig 中导出(供其它模块直接引用)。本模块从 storeConfig 再导出以保持单一实例。
*/
import { ref, computed } from "vue";
import type { Ref } from "vue";
import type {
App,
AppJson,
CategoryInfo,
SidebarEntry,
HomeLink,
FavoriteFolder,
FavoriteItem,
InstalledAppInfo,
ResolvedFavoriteItem,
SystemInfo,
DownloadedAppRecord,
SyncedAppListItem,
AppReview,
ReviewUserProfile,
DownloadItem,
} from "../global/typedefinition";
// ===== 目录数据 =====
export const apps: Ref<App[]> = ref([]);
export const categories: Ref<Record<string, CategoryInfo>> = ref({});
export const tabCategories: Ref<Record<string, Record<string, CategoryInfo>>> =
ref({});
export const tabApps: Ref<Record<string, App[]>> = ref({});
export const loadingTabs = ref<Set<string>>(new Set());
export const homeListUrls = ref<
Record<string, { spark?: string; apm?: string }>
>({});
export const sidebarEntries: Ref<SidebarEntry[]> = ref([]);
export const sparkAvailable = ref(false);
export const apmAvailable = ref(false);
export const storeFilter = ref<"spark" | "apm" | "both">("both");
export const initialCatalogLoaded = ref(false);
export const loading = ref(true);
// ===== 首页 / 排行 =====
export const homeLinks = ref<HomeLink[]>([]);
export const homeLoading = ref(false);
export const homeError = ref("");
export const apmRanking = ref<App[]>([]);
export const sparkRanking = ref<App[]>([]);
export const rankingLoading = ref(false);
// ===== 导航 =====
export type MainView = "default" | "favorites";
export const currentView = ref<MainView>("default");
export const activeTab = ref("home");
export const selectedCategory = ref("all");
export const searchQuery = ref("");
export const isSidebarOpen = ref(false);
// ===== 详情弹窗 =====
export {
currentApp,
currentAppSparkInstalled,
currentAppApmInstalled,
} from "../global/storeConfig";
export const showModal = ref(false);
export const showPreview = ref(false);
export const currentScreenIndex = ref(0);
export const screenshots = ref<string[]>([]);
// ===== 已安装应用 =====
export const showInstalledModal = ref(false);
export const installedApps = ref<App[]>([]);
export const installedLoading = ref(false);
export const installedError = ref("");
export const installedWarning = ref("");
export const installedRefreshGeneration = ref(0);
export const installedSyncPromptShown = ref(false);
// ===== 收藏夹 =====
export const favoriteFolders = ref<FavoriteFolder[]>([]);
export const activeFavoriteFolderId = ref<number | null>(null);
export const favoriteItems = ref<FavoriteItem[]>([]);
export const favoriteItemsByFolder = ref<Record<number, FavoriteItem[]>>({});
export const showFavoriteSelector = ref(false);
export const favoriteTargetApp = ref<App | null>(null);
export const favoriteSelectorDraftFolderIds = ref<Array<
number | "default"
> | null>(null);
export const favoriteLoading = ref(false);
export const favoriteError = ref("");
export const favoriteRequestGeneration = ref(0);
// ===== 账号 / 下载历史 / 云端同步 / 恢复 =====
export const showUserManagementModal = ref(false);
export const downloadedApps = ref<DownloadedAppRecord[]>([]);
export const downloadedLoading = ref(false);
export const downloadedError = ref("");
export const downloadedRequestGeneration = ref(0);
export const syncLoading = ref(false);
export const syncStatusMessage = ref("");
export const syncRequestGeneration = ref(0);
export const syncCandidateApps = ref<App[]>([]);
export const restoreLoading = ref(false);
export const restoreError = ref("");
export const showRestoreModal = ref(false);
export const restoreItems = ref<SyncedAppListItem[]>([]);
export const restoreRequestGeneration = ref(0);
export const showLoginModal = ref(false);
export const loginLoading = ref(false);
export const loginError = ref("");
export const showLoginPrompt = ref(false);
export const loginPromptMessage = ref("请登录星火账号后继续操作。");
export const showLoginPromptMessage = loginPromptMessage;
export const showReviewUserProfileModal = ref(false);
export const selectedReviewUserProfile = ref<ReviewUserProfile | null>(null);
export const systemInfo = ref<SystemInfo>({ distro: "unknown" });
// ===== 下载队列 =====
export { downloads } from "../global/downloadStatus";
export const showDownloadDetailModal = ref(false);
export const currentDownload: Ref<DownloadItem | null> = ref(null);
// ===== 其它弹窗 / 卸载 / 更新中心编排 =====
export const showUninstallModal = ref(false);
export const uninstallTargetApp: Ref<App | null> = ref(null);
export const showAboutModal = ref(false);
export const showSettingsModal = ref(false);
export const showApmInstallDialog = ref(false);
// 可用来源 computed(供 storeFilter 相关判断复用)
export const availableSources = computed(() => ({
spark: sparkAvailable.value,
apm: apmAvailable.value,
}));
// 运算符别名(仅导出类型引用,避免重复定义)
export type {
App,
AppJson,
CategoryInfo,
SidebarEntry,
HomeLink,
FavoriteFolder,
FavoriteItem,
InstalledAppInfo,
ResolvedFavoriteItem,
SystemInfo,
DownloadedAppRecord,
SyncedAppListItem,
AppReview,
ReviewUserProfile,
DownloadItem,
};