diff --git a/apps/thu-info-app/src/ui/home/home.tsx b/apps/thu-info-app/src/ui/home/home.tsx index 1a6b778fe..e49a2b4f1 100644 --- a/apps/thu-info-app/src/ui/home/home.tsx +++ b/apps/thu-info-app/src/ui/home/home.tsx @@ -1,23 +1,15 @@ -import { - Linking, - Platform, - ScrollView, - Text, - TouchableOpacity, - useColorScheme, - View, -} from "react-native"; -import {ReactElement, useEffect} from "react"; -import {RootNav} from "../../components/Root"; +import { Linking, Platform, ScrollView, Text, TouchableOpacity, useColorScheme, View } from "react-native"; +import { ReactElement, useEffect } from "react"; +import { RootNav } from "../../components/Root"; import IconReport from "../../assets/icons/IconReport"; -import {HomeIcon} from "../../components/home/icon"; +import { HomeIcon } from "../../components/home/icon"; import IconExpenditure from "../../assets/icons/IconExpenditure"; import IconFinance from "../../assets/icons/IconFinance"; import IconClassroom from "../../assets/icons/IconClassroom"; import IconEvaluation from "../../assets/icons/IconEvaluation"; import IconLibrary from "../../assets/icons/IconLibrary"; import zh from "../../assets/translations/zh"; -import {getLocale, getStr} from "../../utils/i18n"; +import { getLocale, getStr } from "../../utils/i18n"; import themedStyles from "../../utils/themedStyles"; import IconWasher from "../../assets/icons/IconWasher"; import IconWater from "../../assets/icons/IconWater"; @@ -28,52 +20,42 @@ import IconInvoice from "../../assets/icons/IconInvoice"; import IconEleRecharge from "../../assets/icons/IconEleRecharge"; import IconLibRoom from "../../assets/icons/IconLibRoom"; import themes from "../../assets/themes/themes"; -import {useDispatch, useSelector} from "react-redux"; -import {currState, helper, State} from "../../redux/store"; -import {top5Update} from "../../redux/slices/top5"; +import { useDispatch, useSelector } from "react-redux"; +import { currState, helper, State } from "../../redux/store"; +import { top5Update } from "../../redux/slices/top5"; import IconDormScore from "../../assets/icons/IconDormScore"; -import { - Schedule, - ScheduleType, -} from "@thu-info/lib/src/models/schedule/schedule"; +import { Schedule, ScheduleType } from "@thu-info/lib/src/models/schedule/schedule"; import dayjs from "dayjs"; import md5 from "md5"; -import {ScheduleDetailProps} from "../schedule/scheduleDetail"; -import {LibraryReservationCard} from "./library"; -import { - setActiveLibBookRecord, - setActiveSportsReservationRecord, -} from "../../redux/slices/reservation"; +import { ScheduleDetailProps } from "../schedule/scheduleDetail"; +import { LibraryReservationCard } from "./library"; +import { setActiveLibBookRecord, setActiveSportsReservationRecord } from "../../redux/slices/reservation"; import IconDorm from "../../assets/icons/IconDorm"; import IconCr from "../../assets/icons/IconCr"; import IconLocal from "../../assets/icons/IconLocal"; import IconReserve from "../../assets/icons/IconReserve"; import IconPhysicalExam from "../../assets/icons/IconPhysicalExam"; -import {configSet} from "../../redux/slices/config"; -import {SportsReservationCard} from "./sports"; -import {addUsageStat, FunctionType} from "../../utils/webApi"; -import {useNavigation} from "@react-navigation/native"; -import {setCrTimetable} from "../../redux/slices/timetable"; -import {getStatusBarHeight} from "react-native-safearea-height"; -import { - toggleReadStatus, - updateAnnouncements, -} from "../../redux/slices/announcement"; +import { configSet } from "../../redux/slices/config"; +import { SportsReservationCard } from "./sports"; +import { addUsageStat, FunctionType } from "../../utils/webApi"; +import { useNavigation } from "@react-navigation/native"; +import { setCrTimetable } from "../../redux/slices/timetable"; +import { getStatusBarHeight } from "react-native-safearea-height"; +import { toggleReadStatus, updateAnnouncements } from "../../redux/slices/announcement"; import IconNetwork from "../../assets/icons/IconNetwork"; import IconNetworkDetail from "../../assets/icons/IconNetworkDetail"; import IconNetworkOnlineDevices from "../../assets/icons/IconNetworkOnlineDevices"; -import IconCalendar from "../../assets/icons/IconCalendar"; -import {setBalance} from "../../redux/slices/campusCard"; -import {gt} from "semver"; +import { setBalance } from "../../redux/slices/campusCard"; +import { gt } from "semver"; import VersionNumber from "react-native-version-number"; -import {InfoHelper} from "@thu-info/lib"; +import { InfoHelper } from "@thu-info/lib"; const iconSize = 40; export const HomeFunctionSection = ({ - title, - children, -}: { + title, + children, + }: { title: keyof typeof zh; children: any; }) => { @@ -211,7 +193,7 @@ interface ScheduleViewModel { navProps?: ScheduleDetailProps; } -const HomeSchedule = ({schedule}: {schedule: ScheduleViewModel}) => { +const HomeSchedule = ({ schedule }: { schedule: ScheduleViewModel }) => { const themeName = useColorScheme(); const theme = themes(themeName); const navigation = useNavigation(); @@ -220,7 +202,7 @@ const HomeSchedule = ({schedule}: {schedule: ScheduleViewModel}) => { disabled={schedule.navProps === undefined} onPress={() => { schedule.navProps && - navigation.navigate("ScheduleDetail", schedule.navProps); + navigation.navigate("ScheduleDetail", schedule.navProps); }}> { marginLeft: 12, }} /> - + { borderRadius: 4, }} /> - - + + { }}> {schedule.from} - + { - + { }}> {schedule.to} - + { export const AnnouncementSection = () => { const themeName = useColorScheme(); - const {colors} = themes(themeName); + const { colors } = themes(themeName); const style = styles(themeName); const dispatch = useDispatch(); const announcements = useSelector((s: State) => s.announcement.announcements).filter( - ({visibleNotAfter, visibleExact}) => ( + ({ visibleNotAfter, visibleExact }) => ( visibleNotAfter === undefined || visibleExact === undefined || !gt(VersionNumber.appVersion, visibleNotAfter) || visibleExact.split(",").includes(VersionNumber.appVersion) - ) + ), ); if (announcements.length === 0) { return null; @@ -319,17 +301,17 @@ export const AnnouncementSection = () => { {getStr("announcements")} {announcements.map( - ({id, read, title, content}) => ( + ({ id, read, title, content }) => ( dispatch(toggleReadStatus(id))} - style={{marginVertical: 4, marginHorizontal: 12}} + style={{ marginVertical: 4, marginHorizontal: 12 }} key={id}> - + {title} {read ? "(已读)" : ""} - {!read && {content}} + {!read && {content}} - ) + ), )} @@ -343,7 +325,7 @@ export const HomeReservationSection = () => { {getStr("reservation")} - + ); @@ -372,7 +354,7 @@ export const HomeScheduleSection = () => { _week += 1; dayOfWeek = 1; } - const a: (ScheduleViewModel & {begin: number; end: number})[] = []; + const a: (ScheduleViewModel & { begin: number; end: number })[] = []; for (const s of schedules) { for (const ss of s.activeTime.base) { if (ss.activeWeeks.includes(_week)) { @@ -380,13 +362,13 @@ export const HomeScheduleSection = () => { const from = is24Hour ? beginTime24[ss.begin] : getStr("mark") === "CH" - ? beginTimeZh[ss.begin] - : beginTimeEn[ss.begin]; + ? beginTimeZh[ss.begin] + : beginTimeEn[ss.begin]; const to = is24Hour ? endTime24[ss.end] : getStr("mark") === "CH" - ? endTimeZh[ss.end] - : endTimeEn[ss.end]; + ? endTimeZh[ss.end] + : endTimeEn[ss.end]; if (s.type === ScheduleType.CUSTOM) { a.push({ @@ -459,7 +441,7 @@ export const HomeScheduleSection = () => { (!helper.graduate() && timetable.undergraduate), ); const activeEvents = activeTimetables - .flatMap(({events}) => events) + .flatMap(({ events }) => events) .filter((event) => { const begin = dayjs(event.begin); const end = dayjs(event.end); @@ -480,7 +462,7 @@ export const HomeScheduleSection = () => { )) ) : ( - + {getStr("noScheduleToday")} )} @@ -514,7 +496,7 @@ export const HomeScheduleSection = () => { )) ) : ( - + {getStr("noCountdown")} )} @@ -794,7 +776,7 @@ const getHomeFunctions = ( onPress={() => { addUsageStat(FunctionType.QZYQ); updateTop5("qzyq"); - navigation.navigate("Qzyq", {ticketNumber: 0}); + navigation.navigate("Qzyq", { ticketNumber: 0 }); }}> , @@ -864,19 +846,19 @@ const getHomeFunctions = ( }}> , - { - addUsageStat(FunctionType.SchoolCalendar); - updateTop5("schoolCalendar"); - navigation.navigate("SchoolCalendar"); - }}> - - , + // { + // addUsageStat(FunctionType.SchoolCalendar); + // updateTop5("schoolCalendar"); + // navigation.navigate("SchoolCalendar"); + // }}> + // + // , ]; -export const HomeScreen = ({navigation}: {navigation: RootNav}) => { +export const HomeScreen = ({ navigation }: { navigation: RootNav }) => { const themeName = useColorScheme(); const theme = themes(themeName); const dispatch = useDispatch(); @@ -887,21 +869,12 @@ export const HomeScreen = ({navigation}: {navigation: RootNav}) => { const disabledList: HomeFunction[] | undefined = useSelector( (state: State) => state.config.homeFunctionDisabled, ); - const sunsetFunctions: HomeFunction[] = ["expenditure"]; - if (!disabledList) { - dispatch(configSet({key: "homeFunctionDisabled", value: []})); - } else if (sunsetFunctions.some((f) => !disabledList.includes(f))) { - dispatch( - configSet({ - key: "homeFunctionDisabled", - value: disabledList.concat(sunsetFunctions), - }), - ); - } + const sunsetFunctions: HomeFunction[] = ["expenditure", "schoolCalendar"]; + const homeFunctions = getHomeFunctions(navigation, (func) => dispatch(top5Update(func)), ); - const top5 = top5Functions.map((x) => homeFunctions.find((y) => y.key === x)); + const top5 = top5Functions.map((x) => homeFunctions.find((y) => y.key === x && !sunsetFunctions.includes(x as HomeFunction))); let needToShowFunctionNames: HomeFunction[] = []; ["physicalExam", "teachingEvaluation", "report", "classroomState"].forEach( (i) => { @@ -966,31 +939,31 @@ export const HomeScreen = ({navigation}: {navigation: RootNav}) => { invalidHelper.password = helper.password; invalidHelper.fingerprint = String(undefined); invalidHelper.twoFactorMethodHook = async () => { - dispatch(configSet({key: "fingerprintSecure", value: true})); + dispatch(configSet({ key: "fingerprintSecure", value: true })); return undefined; - } + }; helper .appStartUp(Platform.OS) .then( ({ - bookingRecords, - sportsReservationRecords, - crTimetable, - balance, - latestVersion, - latestAnnounces, - }) => { + bookingRecords, + sportsReservationRecords, + crTimetable, + balance, + latestVersion, + latestAnnounces, + }) => { dispatch(setActiveLibBookRecord(bookingRecords)); dispatch(setActiveSportsReservationRecord(sportsReservationRecords)); dispatch(setCrTimetable(crTimetable)); dispatch( - configSet({key: "latestVersion", value: latestVersion.versionName}), + configSet({ key: "latestVersion", value: latestVersion.versionName }), ); dispatch(updateAnnouncements(latestAnnounces)); dispatch(setBalance(balance)); if (fingerprintSecure !== true && invalidHelper.userId !== "" && invalidHelper.password !== "") { invalidHelper.forgetDevice().then(() => { - dispatch(configSet({key: "fingerprintSecure", value: true})); + dispatch(configSet({ key: "fingerprintSecure", value: true })); }).catch(() => { // no-op }); @@ -1001,7 +974,7 @@ export const HomeScreen = ({navigation}: {navigation: RootNav}) => { }, []); return ( - + { key={String(darkModeHook)}> {top5Filtered.length === 0 ? ( - - + + {getStr("recentUseHint")} @@ -1024,7 +997,7 @@ export const HomeScreen = ({navigation}: {navigation: RootNav}) => { {needToShowFunctions} - + );