({ onMobileMenuToggle, drawerOpen })
| 35 | import { useSidebarCollapsed } from '../../hooks/useSidebarCollapsed.js'; |
| 36 | |
| 37 | const HeaderBar = ({ onMobileMenuToggle, drawerOpen }) => { |
| 38 | const { t, i18n } = useTranslation(); |
| 39 | const [userState, userDispatch] = useContext(UserContext); |
| 40 | const [statusState, statusDispatch] = useContext(StatusContext); |
| 41 | const isMobile = useIsMobile(); |
| 42 | const [collapsed, toggleCollapsed] = useSidebarCollapsed(); |
| 43 | const [isLoading, setIsLoading] = useState(true); |
| 44 | let navigate = useNavigate(); |
| 45 | const [currentLang, setCurrentLang] = useState(i18n.language); |
| 46 | const [mobileMenuOpen, setMobileMenuOpen] = useState(false); |
| 47 | const location = useLocation(); |
| 48 | const [noticeVisible, setNoticeVisible] = useState(false); |
| 49 | const [unreadCount, setUnreadCount] = useState(0); |
| 50 | const loadingStartRef = useRef(Date.now()); |
| 51 | |
| 52 | const systemName = getSystemName(); |
| 53 | const logo = getLogo(); |
| 54 | const currentDate = new Date(); |
| 55 | const isNewYear = currentDate.getMonth() === 0 && currentDate.getDate() === 1; |
| 56 | |
| 57 | const isSelfUseMode = statusState?.status?.self_use_mode_enabled || false; |
| 58 | const docsLink = statusState?.status?.docs_link || ''; |
| 59 | const isDemoSiteMode = statusState?.status?.demo_site_enabled || false; |
| 60 | |
| 61 | const isConsoleRoute = location.pathname.startsWith('/console'); |
| 62 | |
| 63 | const theme = useTheme(); |
| 64 | const setTheme = useSetTheme(); |
| 65 | |
| 66 | const announcements = statusState?.status?.announcements || []; |
| 67 | |
| 68 | const getAnnouncementKey = (a) => `${a?.publishDate || ''}-${(a?.content || '').slice(0, 30)}`; |
| 69 | |
| 70 | const calculateUnreadCount = () => { |
| 71 | if (!announcements.length) return 0; |
| 72 | let readKeys = []; |
| 73 | try { |
| 74 | readKeys = JSON.parse(localStorage.getItem('notice_read_keys')) || []; |
| 75 | } catch (_) { |
| 76 | readKeys = []; |
| 77 | } |
| 78 | const readSet = new Set(readKeys); |
| 79 | return announcements.filter((a) => !readSet.has(getAnnouncementKey(a))).length; |
| 80 | }; |
| 81 | |
| 82 | const getUnreadKeys = () => { |
| 83 | if (!announcements.length) return []; |
| 84 | let readKeys = []; |
| 85 | try { |
| 86 | readKeys = JSON.parse(localStorage.getItem('notice_read_keys')) || []; |
| 87 | } catch (_) { |
| 88 | readKeys = []; |
| 89 | } |
| 90 | const readSet = new Set(readKeys); |
| 91 | return announcements.filter((a) => !readSet.has(getAnnouncementKey(a))).map(getAnnouncementKey); |
| 92 | }; |
| 93 | |
| 94 | useEffect(() => { |
nothing calls this directly
no test coverage detected