Skip to content

Commit

Permalink
Enable toggle recent search tab in RouteBoard
Browse files Browse the repository at this point in the history
  • Loading branch information
chunlaw committed Oct 8, 2023
1 parent 8ecb453 commit 141f51d
Show file tree
Hide file tree
Showing 11 changed files with 100 additions and 57 deletions.
25 changes: 25 additions & 0 deletions src/AppContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ export interface AppState {
* Annotate scheduled bus
*/
annotateScheduled: boolean;
/**
* Show recently searched
*/
isRecentSearchShown: boolean;
}

interface AppContextValue
Expand Down Expand Up @@ -106,6 +110,7 @@ interface AppContextValue
toggleAnalytics: () => void; // not
updateRefreshInterval: (interval: number) => void;
toggleAnnotateScheduled: () => void;
toggleIsRecentSearchShown: () => void;
changeLanguage: (lang: Language) => void;
importAppState: (appState: AppState) => void;
workbox?: Workbox;
Expand Down Expand Up @@ -196,6 +201,8 @@ export const AppContextProvider = ({
: "dark",
energyMode: !!JSON.parse(localStorage.getItem("energyMode")) || false,
vibrateDuration: JSON.parse(localStorage.getItem("vibrateDuration")) ?? 1,
isRecentSearchShown:
JSON.parse(localStorage.getItem("isRecentSearchShown")) || true,
isVisible: true,
analytics:
iOSRNWebView() && !iOSTracking()
Expand Down Expand Up @@ -475,6 +482,15 @@ export const AppContextProvider = ({
);
}, []);

const toggleIsRecentSearchShown = useCallback(() => {
setStateRaw(
produce((state: State) => {
const prev = state.isRecentSearchShown;
state.isRecentSearchShown = !prev;
})
);
}, []);

const changeLanguage = useCallback(
(lang: Language) => {
i18n.changeLanguage(lang);
Expand Down Expand Up @@ -535,6 +551,13 @@ export const AppContextProvider = ({
localStorage.setItem("energyMode", JSON.stringify(state.energyMode));
}, [state.energyMode]);

useEffect(() => {
localStorage.setItem(
"isRecentSearchShown",
JSON.stringify(state.isRecentSearchShown)
);
}, [state.isRecentSearchShown]);

useEffect(() => {
localStorage.setItem("analytics", JSON.stringify(state.analytics));
}, [state.analytics]);
Expand Down Expand Up @@ -595,6 +618,7 @@ export const AppContextProvider = ({
toggleAnalytics,
updateRefreshInterval,
toggleAnnotateScheduled,
toggleIsRecentSearchShown,
changeLanguage,
importAppState,
workbox,
Expand Down Expand Up @@ -622,6 +646,7 @@ export const AppContextProvider = ({
toggleAnalytics,
updateRefreshInterval,
toggleAnnotateScheduled,
toggleIsRecentSearchShown,
changeLanguage,
importAppState,
workbox,
Expand Down
28 changes: 14 additions & 14 deletions src/components/route-board/BoardTabbar.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import React from "react";
import React, { useContext } from "react";
import { Box, Tabs, Tab, SxProps, Theme } from "@mui/material";
import { useTranslation } from "react-i18next";

import { TRANSPORT_SEARCH_OPTIONS } from "../../constants";
import AppContext from "../../AppContext";
import { BoardTabType } from "../../typing";

interface BoardTabbarProps {
boardTab: BoardTabType;
Expand All @@ -11,6 +13,7 @@ interface BoardTabbarProps {

const BoardTabbar = ({ boardTab, onChangeTab }: BoardTabbarProps) => {
const { t } = useTranslation();
const { isRecentSearchShown } = useContext(AppContext);

return (
<Box sx={rootSx}>
Expand All @@ -19,27 +22,24 @@ const BoardTabbar = ({ boardTab, onChangeTab }: BoardTabbarProps) => {
onChange={(e, v) => onChangeTab(v, true)}
sx={tabbarSx}
>
{Object.keys(TRANSPORT_SEARCH_OPTIONS).map((option) => (
<Tab key={option} label={t(option)} value={option} disableRipple />
))}
{Object.keys(TRANSPORT_SEARCH_OPTIONS)
.filter((option) => isRecentSearchShown || option !== "recent")
.map((option) => (
<Tab key={option} label={t(option)} value={option} disableRipple />
))}
</Tabs>
</Box>
);
};

export default BoardTabbar;

export type BoardTabType =
| "recent"
| "all"
| "bus"
| "minibus"
| "lightRail"
| "mtr";

export const isBoardTab = (input: unknown): input is BoardTabType => {
export const isBoardTab = (
input: unknown,
isRecentSearchShown: boolean
): input is BoardTabType => {
return (
input === "recent" ||
(isRecentSearchShown && input === "recent") ||
input === "all" ||
input === "bus" ||
input === "minibus" ||
Expand Down
2 changes: 1 addition & 1 deletion src/components/route-board/RouteInputPad.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Box, Button, Grid, SxProps, Theme } from "@mui/material";
import BackspaceOutlinedIcon from "@mui/icons-material/BackspaceOutlined";
import DoNotDisturbOnOutlinedIcon from "@mui/icons-material/DoNotDisturbOnOutlined";
import AppContext from "../../AppContext";
import { BoardTabType } from "./BoardTabbar";
import { type BoardTabType } from "../../typing";
import { TRANSPORT_SEARCH_OPTIONS } from "../../constants";

const KeyButton = ({ k, handleClick, disabled = false, sx }) => {
Expand Down
9 changes: 6 additions & 3 deletions src/components/route-board/SwipeableRoutesBoard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { Box, SxProps, Theme, Typography } from "@mui/material";

import AppContext from "../../AppContext";
import { isHoliday, isRouteAvaliable } from "../../timetable";
import type { BoardTabType } from "./BoardTabbar";
import type { BoardTabType } from "../../typing";
import { TRANSPORT_SEARCH_OPTIONS, TRANSPORT_ORDER } from "../../constants";
import RouteRowList from "./RouteRowList";
import { routeSortFunc } from "../../utils";
Expand All @@ -31,6 +31,7 @@ const SwipeableRoutesBoard = ({
busSortOrder,
routeSearchHistory,
vibrateDuration,
isRecentSearchShown,
} = useContext(AppContext);
const isTodayHoliday = useMemo(
() => isHoliday(holidays, new Date()),
Expand Down Expand Up @@ -137,7 +138,9 @@ const SwipeableRoutesBoard = ({
</Box>
) : (
<VirtualizeSwipeableViews
index={BOARD_TAB.indexOf(boardTab)}
index={BOARD_TAB.filter(
(tab) => isRecentSearchShown || tab !== "recent"
).indexOf(boardTab)}
onChangeIndex={(idx) => {
onChangeTab(BOARD_TAB[idx]);
}}
Expand All @@ -152,7 +155,7 @@ const SwipeableRoutesBoard = ({
)}
</>
),
[ListRenderer, coItemDataList, onChangeTab, boardTab]
[ListRenderer, coItemDataList, onChangeTab, boardTab, isRecentSearchShown]
);
};

Expand Down
20 changes: 20 additions & 0 deletions src/components/settings/OptionsList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ import {
Sort as SortIcon,
HourglassTop as HourglassTopIcon,
PushPin as PinIcon,
Update as UpdateIcon,
UpdateDisabled as UpdateDisabledIcon,
} from "@mui/icons-material";
import { ETA_FORMAT_STR } from "../../constants";
import AppContext from "../../AppContext";
Expand Down Expand Up @@ -59,6 +61,8 @@ const OptionsList = ({ goToTab }: OptionsListProps) => {
updateRefreshInterval,
annotateScheduled,
toggleAnnotateScheduled,
isRecentSearchShown,
toggleIsRecentSearchShown,
} = useContext(AppContext);
const { t } = useTranslation();

Expand Down Expand Up @@ -205,6 +209,22 @@ const OptionsList = ({ goToTab }: OptionsListProps) => {
secondary={t(!energyMode ? "開啟地圖功能" : "關閉地圖功能")}
/>
</ListItemButton>
<ListItemButton
onClick={() => {
vibrate(vibrateDuration ^ 1); // tricky, vibrate when switch on and vice versa
toggleIsRecentSearchShown();
}}
>
<ListItemAvatar>
<Avatar>
{isRecentSearchShown ? <UpdateIcon /> : <UpdateDisabledIcon />}
</Avatar>
</ListItemAvatar>
<ListItemText
primary={t("搜尋記錄")}
secondary={t(isRecentSearchShown ? "開啟" : "關閉")}
/>
</ListItemButton>
<ListItemButton
onClick={() => {
vibrate(vibrateDuration ^ 1); // tricky, vibrate when switch on and vice versa
Expand Down
33 changes: 9 additions & 24 deletions src/constants.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import { Company } from "hk-bus-eta";
import { BoardTabType } from "./typing";

export const ETA_FORMAT_NEXT_TYPES: {
[format: string]: "diff" | "exact" | "mixed";
} = {
Expand All @@ -12,34 +15,16 @@ export const ETA_FORMAT_STR = {
mixed: "到站時間(到站時差)",
};

export const TRANSPORT_SEARCH_OPTIONS = {
recent: ["kmb", "ctb", "nwfb", "lrtfeeder", "nlb", "gmb", "lightRail", "mtr"],
all: ["kmb", "ctb", "nwfb", "lrtfeeder", "nlb", "gmb", "lightRail", "mtr"],
bus: ["kmb", "ctb", "nwfb", "lrtfeeder", "nlb"],
export const TRANSPORT_SEARCH_OPTIONS: Record<BoardTabType, Company[]> = {
recent: ["kmb", "ctb", "lrtfeeder", "nlb", "gmb", "lightRail", "mtr"],
all: ["kmb", "ctb", "lrtfeeder", "nlb", "gmb", "lightRail", "mtr"],
bus: ["kmb", "ctb", "lrtfeeder", "nlb"],
minibus: ["gmb"],
lightRail: ["lightRail"],
mtr: ["mtr"],
};

export const TRANSPORT_ORDER = {
"KMB first": [
"kmb",
"ctb",
"nwfb",
"lrtfeeder",
"nlb",
"gmb",
"lightRail",
"mtr",
],
"CTB-NWFB first": [
"ctb",
"nwfb",
"kmb",
"lrtfeeder",
"nlb",
"gmb",
"lightRail",
"mtr",
],
"KMB first": ["kmb", "ctb", "lrtfeeder", "nlb", "gmb", "lightRail", "mtr"],
"CTB first": ["ctb", "kmb", "lrtfeeder", "nlb", "gmb", "lightRail", "mtr"],
};
19 changes: 9 additions & 10 deletions src/i18n/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
"點對點路線搜尋": "Point to point route search",
"kmb": "KMB",
"ctb": "CTB",
"nwfb": "NWFB",
"nlb": "NLB",
"lrtfeeder": "MTR",
"gmb": "GMB",
Expand Down Expand Up @@ -56,10 +55,10 @@
"車費": "Fare",
"假日車費": "Holiday fare",
"特別班": "Special",
"home-page-description": "Ad-free mobile application for checking bus routes, stops, estimated time of arrival(ETA) of Kowloon Motor Bus Co. (KMB), Long Win Bus (LWB), CityBus (CTB), New World First Bus (NWFB), New Lantao Bus (NLB) and Green Minibus (GMB) - HK Bus ETA App",
"route-board-page-description": "Simple & clean route searching interface to search over 1800 routes and 8800 stops among Kowloon Motor Bus Co. (KMB), Long Win Bus (LWB), CityBus (CTB), New World First Bus (NWFB), New Lantao Bus (NLB) and Green Minibus (GMB), covering Hong Kong Island, Kowloon, New Territories and Lantau Island - HK Bus ETA App",
"home-page-description": "Ad-free mobile application for checking bus routes, stops, estimated time of arrival(ETA) of Kowloon Motor Bus Co. (KMB), Long Win Bus (LWB), CityBus (CTB), New Lantao Bus (NLB) and Green Minibus (GMB) - HK Bus ETA App",
"route-board-page-description": "Simple & clean route searching interface to search over 1800 routes and 8800 stops among Kowloon Motor Bus Co. (KMB), Long Win Bus (LWB), CityBus (CTB), New Lantao Bus (NLB) and Green Minibus (GMB), covering Hong Kong Island, Kowloon, New Territories and Lantau Island - HK Bus ETA App",
"setting-page-description": "Update the database, clean up usage record, check out the source code, join the telegram group and donate - HK Bus ETA App",
"route-search-page-description": "Point-to-Point route search across Kowloon Motor Bus Co. (KMB), Long Win Bus (LWB), CityBus (CTB), New World First Bus (NWFB), New Lantao Bus (NLB), Green Minibus (GMB) - HK Bus ETA App",
"route-search-page-description": "Point-to-Point route search across Kowloon Motor Bus Co. (KMB), Long Win Bus (LWB), CityBus (CTB), New Lantao Bus (NLB), Green Minibus (GMB) - HK Bus ETA App",
"圖示來源": "Icons from",
"安裝": "Install the App",
"安裝巴士預報 App 到裝置": "Install HK BUS ETA",
Expand Down Expand Up @@ -147,7 +146,8 @@
"複制匯出網址": "Copy URL with data implanted",
"請按下圖指示增加": "Follow below steps to bookmark stops",
"通告": "Notice",
"注釋預定班次": "Annotate Scheduled Bus"
"注釋預定班次": "Annotate Scheduled Bus",
"搜尋記錄": "Search history"
}
},
"zh": {
Expand All @@ -157,15 +157,14 @@
"db-renew-text": "路線資料已有 28 天沒更新,按此手動更新",
"kmb": "九巴",
"ctb": "城巴",
"nwfb": "新巴",
"nlb": "新大嶼山巴士",
"gmb": "專線小巴",
"lrtfeeder": "港鐵",
"Dashboard": "儀表板",
"home-page-description": "無廣告手機應用程式查閱巴士線、車站、預計到達時間,路線盡包九龍巴士(九巴)、龍運巴士、新世界第一巴士(新巴)、城巴、新大嶼山巴士、專線小巴 - 巴士到站預報 App",
"route-board-page-description": "透過簡潔清晣的搜尋介面,輕鬆查找九巴、龍運、新巴、城巴、新大嶼山巴士、專線小巴合共超過 1800 條巴士路線,8800 個車站,路線覆蓋港島、九龍、新界、大嶼山 - 巴士到站預報 App",
"home-page-description": "無廣告手機應用程式查閱巴士線、車站、預計到達時間,路線盡包九龍巴士(九巴)、龍運巴士、城巴、新大嶼山巴士、專線小巴 - 巴士到站預報 App",
"route-board-page-description": "透過簡潔清晣的搜尋介面,輕鬆查找九巴、龍運、城巴、新大嶼山巴士、專線小巴合共超過 1800 條巴士路線,8800 個車站,路線覆蓋港島、九龍、新界、大嶼山 - 巴士到站預報 App",
"setting-page-description": "重置巴士路線資料,刪除使用記錄,查看原始碼,加入 Telegram 交流群組,亦可捐款支持 - 巴士到站預報 App",
"route-search-page-description": "點對點搜尋可行巴士線,合理步距下,橫誇九巴、龍運、新巴、城巴、新大嶼山巴士、專線小巴的巴士線 - 巴士到站預報 App",
"route-search-page-description": "點對點搜尋可行巴士線,合理步距下,橫誇九巴、龍運、城巴、新大嶼山巴士、專線小巴的巴士線 - 巴士到站預報 App",
"Route Search header": "點對點巴士路線搜尋",
"Route Search description": "搜尋由起點到終點的路線",
"Route Search constraint": "條件如下:",
Expand All @@ -179,7 +178,7 @@
"lightRail": "輕鐵",
"mtr": "港鐵",
"KMB first": "九巴優先",
"CTB-NWFB first": "新巴城巴優先",
"CTB first": "城巴優先",
"route-search-no-result": "沒有結果",
"no-recent-search": "沒有記錄",
"Source code": "原始碼",
Expand Down
3 changes: 3 additions & 0 deletions src/pages/DataExport.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ const DataExport = () => {
isRouteFilter,
busSortOrder,
analytics,
isRecentSearchShown,
} = useContext(AppContext);

const exportUrl = useMemo<string>(
Expand All @@ -54,6 +55,7 @@ const DataExport = () => {
isRouteFilter,
busSortOrder,
analytics,
isRecentSearchShown,
},
null,
0
Expand All @@ -76,6 +78,7 @@ const DataExport = () => {
busSortOrder,
language,
analytics,
isRecentSearchShown,
]
);
const [isCopied, setIsCopied] = useState<boolean>(false);
Expand Down
1 change: 1 addition & 0 deletions src/pages/DataImport.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ const DataImport = () => {
analytics: obj.analytics ?? true,
refreshInterval: obj.refreshInterval ?? 30,
annotateScheduled: obj.annotateScheduled ?? true,
isRecentSearchShown: obj.isRecentSearchShown ?? true,
});

navigate("/");
Expand Down
9 changes: 4 additions & 5 deletions src/pages/RouteBoard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,9 @@ import { Box } from "@mui/material";
import RouteInputPad from "../components/route-board/RouteInputPad";
import { useTranslation } from "react-i18next";
import { setSeoHeader } from "../utils";
import BoardTabbar, {
BoardTabType,
isBoardTab,
} from "../components/route-board/BoardTabbar";
import BoardTabbar, { isBoardTab } from "../components/route-board/BoardTabbar";
import SwipeableRoutesBoard from "../components/route-board/SwipeableRoutesBoard";
import { BoardTabType } from "../typing";

interface RouteListProps {
boardTab: BoardTabType;
Expand Down Expand Up @@ -46,9 +44,10 @@ const RouteList = ({ boardTab, setBoardTab }: RouteListProps) => {
};

const RouteBoard = () => {
const { isRecentSearchShown } = useContext(AppContext);
const _boardTab = localStorage.getItem("boardTab");
const [boardTab, setBoardTab] = useState<BoardTabType>(
isBoardTab(_boardTab) ? _boardTab : "all"
isBoardTab(_boardTab, isRecentSearchShown) ? _boardTab : "all"
);

return (
Expand Down
8 changes: 8 additions & 0 deletions src/typing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,11 @@ export const DEFAULT_ROUTE_COLLECTION: RouteCollection = {
day: idx,
})),
};

export type BoardTabType =
| "recent"
| "all"
| "bus"
| "minibus"
| "lightRail"
| "mtr";

0 comments on commit 141f51d

Please sign in to comment.