Files
rn-app/hooks/useGameMenus.ts

156 lines
4.8 KiB
TypeScript
Raw Normal View History

2025-11-12 00:13:26 +08:00
import { useEffect, useState, useMemo, useCallback } from 'react';
2025-11-11 18:48:54 +08:00
import useGameStore from '@/stores/gameStore';
import { GameMainTypesEnum, defaultHomeGameTabMenus, gameMainTypesMap } from '@/constants/game';
import { ThemeEnum } from '@/constants/theme';
import { forEach, cloneDeep, map, filter } from 'lodash-es';
import { useIsLoggedIn } from '@/stores/userStore';
import { useShallow } from 'zustand/react/shallow';
2025-11-12 00:13:26 +08:00
import storageManager, { STORAGE_KEYS } from '@/utils/storageManager';
type GameMenu = {
name: string;
key: string;
icon?: string;
logo?: string;
children?: GameMenu[];
};
2025-11-11 18:48:54 +08:00
// 有子菜单的游戏类型
const hasSubGameMainTypes = [
GameMainTypesEnum.CHESS,
GameMainTypesEnum.ELECTRONIC,
GameMainTypesEnum.FISHING,
GameMainTypesEnum.BLOCK_THIRD,
];
export const useGameMainMenus = (theme: ThemeEnum) => {
// 在 hook 顶层调用 useIsLoggedIn
const isLogin = useIsLoggedIn();
// 从 store 获取必要的数据 - 直接获取,不使用 useShallow
const menuSort = useGameStore((state) => state.menuSort);
const gameBigClass = useGameStore((state) => state.gameBigClass);
if (__DEV__) {
console.log('🎮 useGameMainMenus - menuSort:', menuSort, 'length:', menuSort?.length);
}
// 使用 useMemo 缓存计算结果,避免每次都创建新对象
return useMemo(() => {
const defaultMenus = cloneDeep(defaultHomeGameTabMenus);
if (theme === ThemeEnum.DARK) {
forEach(defaultMenus, (item) => {
if (item.key === GameMainTypesEnum.RECENT) {
item.icon = 'clock-solid_dark';
}
});
}
const gameMenu = map(menuSort, (item: Record<string, any>) => {
const typeName = gameMainTypesMap[item.type as GameMainTypesEnum];
const children = hasSubGameMainTypes.includes(item.type)
? map(gameBigClass?.[typeName], (it) => {
return {
name: it.play_cname,
key: `${it.play_id}`,
play_sort: it.play_sort,
darkImgSrc: `/images/game/${typeName}/dark_${it.play_id}.png`,
lightImgSrc: `/images/game/${typeName}/light_${it.play_id}.png`,
colorImgSrc: it.logo3_img_url || `/images/game/${typeName}/color_${it.play_id}.png`,
};
})
: [];
return {
name: item.play_name,
key: `${item.type}`,
icon: typeName,
logo: item.logo_url1,
children,
};
});
if (__DEV__) {
console.log(gameMenu, 'gameMenu');
}
return map(
[
...filter(defaultMenus, (item) => [GameMainTypesEnum.RECOMMEND].includes(item.key)),
...(isLogin
? filter(gameMenu, (item) => Number(item.key) !== GameMainTypesEnum.TRIAL)
: gameMenu),
...filter(defaultMenus, (item) =>
[GameMainTypesEnum.COLLECT, GameMainTypesEnum.RECENT].includes(item.key)
),
],
(item) => ({
...item,
2025-11-12 00:13:26 +08:00
// 为了在 React Native 中正确加载本地图片,使用 require 的方式
// 这里保留原始的 icon 名称,在组件中使用 require 加载
icon: item.icon,
2025-11-11 18:48:54 +08:00
key: `${item.key}`,
})
2025-11-12 00:13:26 +08:00
) as GameMenu[];
2025-11-11 18:48:54 +08:00
}, [theme, isLogin, menuSort, gameBigClass]);
};
export const useMenuDataLoaded = () => useGameStore((state) => state.menuSort?.length > 0);
2025-11-12 00:13:26 +08:00
/**
* Hook
*
*
* - gameStore
* - session storage
* -
*
* @returns {Object} selectedCategory setSelectedCategory
*
* @example
* ```typescript
* const { selectedCategory, setSelectedCategory } = useSelectedCategory();
*
* // 获取当前选中分类
* console.log(selectedCategory); // '103'
*
* // 更新选中分类
* setSelectedCategory('1');
* ```
*/
export const useSelectedCategory = () => {
const selectedCategory = useGameStore((state) => state.selectedCategory);
const setSelectedCategoryInStore = useGameStore((state) => state.setSelectedCategory);
// 初始化时从 session storage 恢复选中分类
useEffect(() => {
const initializeSelectedCategory = async () => {
try {
const savedCategory = storageManager.session.getItem(STORAGE_KEYS.APP_ACTIVE_MAIN_MENU_TAB);
if (savedCategory) {
setSelectedCategoryInStore(savedCategory);
}
} catch (error) {
console.error('Failed to restore selected category:', error);
}
};
initializeSelectedCategory();
}, [setSelectedCategoryInStore]);
// 更新选中分类的回调函数
const setSelectedCategory = useCallback(
(categoryId: string) => {
setSelectedCategoryInStore(categoryId);
},
[setSelectedCategoryInStore]
);
return {
selectedCategory,
setSelectedCategory,
};
};