(null);
-
- const onViewAvatar = ({ props: { avatarID } }: ItemParams) => {
- if (avatarID.startsWith("*")) {
- toast.warning(t("notAvatarViewFault"));
- } else {
- to(
- `/qwilight/avatar/${encodeURIComponent("#")}${getDefaultAvatarID(
- avatarID,
- )}`,
- );
- }
- };
-
- useEffect(() => {
- window.Notification?.requestPermission();
- }, []);
-
- const onViewsModified = useCallback(() => {
- setSiteYellsViewHeight(
- `${
- document.documentElement.clientHeight -
- (titleComponent.current?.clientHeight ?? 0) -
- (siteViewsView.current?.clientHeight ?? 0) -
- (inputComponent.current?.clientHeight ?? 0) -
- (isFirefox ? 1 : 0)
- }px`,
- );
- }, [titleComponent]);
-
- useEffect(() => {
- onViewsModified();
- }, [onViewsModified, isLoading, avatars, lastPendingSiteYell]);
-
- useEffect(() => {
- const onModified = () => {
- onViewsModified();
- siteYellsViewMove(siteYellsView);
- };
-
- window.addEventListener("resize", onModified);
-
- return () => {
- window.removeEventListener("resize", onModified);
- };
- }, [onViewsModified, siteYellsView, siteYellsViewMove]);
-
- const onSiteYellsViewMove = useCallback(() => {
- const { current } = siteYellsView;
- if (current) {
- const siteYellID = siteYells[0]?.siteYellID;
- if (siteYellID && siteYellID > 0 && !current.scrollTop) {
- SiteComponent.send({
- eventID: EventPB.Event.EventID.GET_SITE_YELLS,
- text: JSON.stringify({
- siteID: targetSiteID,
- siteYellID: siteYellID,
- }),
- });
- }
-
- const isSiteYellsViewLowest =
- current.scrollTop + current.clientHeight >= current.scrollHeight;
- setSiteYellsViewLowest(isSiteYellsViewLowest);
- if (isSiteYellsViewLowest) {
- setPendingSiteYellOpened(false);
- }
- }
- }, [
- setPendingSiteYellOpened,
- setSiteYellsViewLowest,
- siteYells,
- siteYellsView,
- targetSiteID,
- ]);
-
- useEffect(() => {
- const { current } = siteYellsView;
-
- if (current) {
- current.addEventListener("scroll", onSiteYellsViewMove);
-
- return () => {
- current.removeEventListener("scroll", onSiteYellsViewMove);
- };
- }
- }, [onSiteYellsViewMove, isLoading, siteYellsView]);
-
- const isSiteHand = useMemo(
- () => getSiteView(targetSiteID)?.siteHand === siteAvatarID,
- [getSiteView, siteAvatarID, targetSiteID],
- );
-
- const queryClient = useQueryClient();
-
- if (isLoading) {
- return ;
- }
-
- const onSiteYellInput: OnSiteYellInput = (event, avatarID) => {
- viewSiteYellInput({ event, props: { avatarID } });
- };
-
- return (
- <>
-
-
- {siteViews.map(({ siteID, siteName, isNew }) => {
- return (
-
-
-
- );
- })}
-
-
-
- {targetSiteID && (
-
-
-
- )}
-
-
-
-
-
-
- {siteNotify}
-
-
-
-
-
-
- {
- siteYellsViewMove(siteYellsView);
- }}
- >
- {lastPendingSiteYell && (
-
- )}
-
-
-
-
-
-
-
-
- setAvatarsOpened(false)}
- >
- setAvatarsOpened(false)}>
- {sprintf(t("avatarCountText"), avatars.length)}
-
-
- {
- viewAvatarInput({ event, props: { avatarID } });
- }}
- />
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- >
- );
-});
diff --git a/qwilight-fe/src/site/SiteWindow.module.scss b/qwilight-fe/src/site/SiteWindow.module.scss
deleted file mode 100644
index 5aad382..0000000
--- a/qwilight-fe/src/site/SiteWindow.module.scss
+++ /dev/null
@@ -1,5 +0,0 @@
-img {
- &.sc {
- height: 1.5rem;
- }
-}
diff --git a/qwilight-fe/src/site/SiteWindow.tsx b/qwilight-fe/src/site/SiteWindow.tsx
index 4179e80..22b184c 100644
--- a/qwilight-fe/src/site/SiteWindow.tsx
+++ b/qwilight-fe/src/site/SiteWindow.tsx
@@ -1,22 +1,22 @@
import { useState } from "react";
import { observer } from "mobx-react-lite";
-import { useTranslation } from "react-i18next";
import { Button, Col, Modal, Row } from "reactstrap";
import { sprintf } from "sprintf-js";
-import { useSiteStore } from "src/Stores";
-import NewSiteWindow from "src/site/NewSiteWindow";
-import SiteComponent from "src/site/SiteComponent";
-import SiteCipherWindow from "src/site/SiteCipherWindow";
+import { useSiteStore } from "@/Stores";
+import NewSiteWindow from "@/site/NewSiteWindow";
+import SiteComponent from "@/site/SiteComponent";
+import SiteCipherWindow from "@/site/SiteCipherWindow";
-import sc0 from "src/assets/sc0.png";
-import sc2 from "src/assets/sc2.png";
-import sc from "src/assets/sc.png";
+import sc0 from "@/assets/sc0.png";
+import sc2 from "@/assets/sc2.png";
+import sc from "@/assets/sc.png";
-import scss from "src/site/SiteWindow.module.scss";
-import useGetSites from "src/site/useGetSites";
+import useGetSites from "@/site/useGetSites";
+import { useTranslations } from "next-intl";
+import Image from "next/image";
-const EventPB = require("src/Event_pb");
+const EventPB = require("@/Event_pb");
const scs = [sc0, "", sc2];
@@ -29,7 +29,7 @@
targetSiteID,
setNewSiteWindowOpened,
} = useSiteStore();
- const { t } = useTranslation();
+ const t = useTranslations();
const [siteID, setSiteID] = useState("");
const [siteName, setSiteName] = useState("");
@@ -52,7 +52,7 @@
>
{scs[siteConfigure] && (
-
+
)}{" "}
{" "}
-
+
>
)}
diff --git a/qwilight-fe/src/site/SiteYellItem.tsx b/qwilight-fe/src/site/SiteYellItem.tsx
index 0694dc3..ff7b980 100644
--- a/qwilight-fe/src/site/SiteYellItem.tsx
+++ b/qwilight-fe/src/site/SiteYellItem.tsx
@@ -1,10 +1,9 @@
import { observer } from "mobx-react-lite";
import { Col, Row } from "reactstrap";
-import { useTranslation } from "react-i18next";
import { sprintf } from "sprintf-js";
import { sanitize } from "dompurify";
-import { useSiteStore } from "src/Stores";
+import { useSiteStore } from "@/Stores";
import {
AbilitySiteYell,
CommentSiteYell,
@@ -13,22 +12,24 @@
OnSiteYellInput,
SiteYell,
TVSiteYell,
-} from "src/site/Site";
+} from "@/site/Site";
import {
formatText,
getAbilityUpText,
getGenreText,
getHitPointsClass,
-} from "src/Utility";
-import AvatarDrawing from "src/AvatarDrawing";
-import AvatarTitle from "src/AvatarTitle";
+} from "@/Utility";
+import AvatarDrawing from "@/AvatarDrawing";
+import AvatarTitle from "@/AvatarTitle";
-import { ReactComponent } from "src/assets/tv0.svg";
-import tv1 from "src/assets/tv1.png";
-import scss from "src/site/SiteYellItem.module.scss";
-import SiteComponent from "src/site/SiteComponent";
+import TV0 from "@/assets/tv0.svg";
+import tv1 from "@/assets/tv1.png";
+import scss from "@/site/SiteYellItem.module.scss";
+import SiteComponent from "@/site/SiteComponent";
+import { useTranslations } from "next-intl";
+import Image from "next/image";
-const EventPB = require("src/Event_pb");
+const EventPB = require("@/Event_pb");
export default observer(
({
@@ -40,7 +41,7 @@
}) => {
const { siteYellVariety, date, avatarID, avatarName, siteYell } = data;
const { saveTraffic } = useSiteStore();
- const { t } = useTranslation();
+ const t = useTranslations();
const doSiteYell = (siteYell: string) => {
siteYell = siteYell.replace(" ", " ");
@@ -183,7 +184,7 @@
return (
- {t("siteYellTaehui")}{" "}
+ {t("siteYellTaehu")}{" "}
{date}
{href.startsWith("https://www.twitch.tv") && (
-
+
)}
{href.startsWith("https://chzzk.naver.com") && (
-
+
)}
diff --git a/qwilight-fe/src/site/SiteYellItems.tsx b/qwilight-fe/src/site/SiteYellItems.tsx
index 00e5404..5ac7470 100644
--- a/qwilight-fe/src/site/SiteYellItems.tsx
+++ b/qwilight-fe/src/site/SiteYellItems.tsx
@@ -1,8 +1,8 @@
import { observer } from "mobx-react-lite";
-import SiteYellItem from "src/site/SiteYellItem";
-import { useSiteStore } from "src/Stores";
-import { OnSiteYellInput } from "src/site/Site";
+import SiteYellItem from "@/site/SiteYellItem";
+import { useSiteStore } from "@/Stores";
+import { OnSiteYellInput } from "@/site/Site";
export default observer(
({ onSiteYellInput }: { onSiteYellInput: OnSiteYellInput }) => {
diff --git a/qwilight-fe/src/site/setSiteStore.ts b/qwilight-fe/src/site/setSiteStore.ts
index 0af1d5e..979c611 100644
--- a/qwilight-fe/src/site/setSiteStore.ts
+++ b/qwilight-fe/src/site/setSiteStore.ts
@@ -1,22 +1,22 @@
-import { MutableRefObject } from "react";
+import { RefObject } from "react";
import { toast } from "react-toastify";
import { runInAction } from "mobx";
import { sprintf } from "sprintf-js";
import CryptoJS from "crypto-js";
-import { TFunction } from "i18next";
-import SiteComponent from "src/site/SiteComponent";
-import { AbilitySiteYell, Avatar, SiteView, SiteYell } from "src/site/Site";
+import SiteComponent from "@/site/SiteComponent";
+import { AbilitySiteYell, Avatar, SiteView, SiteYell } from "@/site/Site";
import {
formatText,
getAbilityUpText,
getDefaultAvatarID,
getGenreText,
getSiteName,
-} from "src/Utility";
-import { wwwAPI } from "src/Www";
+} from "@/Utility";
+import { wwwAPI } from "@/Www";
+import { useTranslations } from "next-intl";
-const EventPB = require("src/Event_pb");
+const EventPB = require("@/Event_pb");
const getSiteYellItem = ({
avatarID,
@@ -113,6 +113,8 @@
export default function setSiteStore() {
return {
+ titleComponent: undefined as RefObject | undefined,
+ siteYellsView: undefined as RefObject | undefined,
avatars: [] as Avatar[],
siteYells: [] as SiteYell[],
isSignInOpened: false,
@@ -122,11 +124,17 @@
isConfigureOpened: false,
targetSiteID: "",
siteNotify: "",
- saveTraffic: window.localStorage.getItem("saveTraffic") === "true",
- autoEnterNotify: window.localStorage.getItem("autoEnterNotify") !== "false",
+ saveTraffic:
+ typeof window === "object" &&
+ window.localStorage.getItem("saveTraffic") === "true",
+ autoEnterNotify:
+ typeof window === "object" &&
+ window.localStorage.getItem("autoEnterNotify") !== "false",
autoEnterDefault:
+ typeof window === "object" &&
window.localStorage.getItem("autoEnterDefault") !== "false",
autoEnterPlatform:
+ typeof window === "object" &&
window.localStorage.getItem("autoEnterPlatform") !== "false",
isEditable: true,
input: "",
@@ -141,10 +149,15 @@
isPendingSiteYellOpened: false,
isAvatarsOpened: false,
- setEventHandler(
- siteYellsView: MutableRefObject,
- t: TFunction,
+ setComponents(
+ titleComponent: RefObject,
+ siteYellsView: RefObject,
) {
+ this.titleComponent = titleComponent;
+ this.siteYellsView = siteYellsView;
+ },
+
+ setEventHandler(t: ReturnType>) {
const autoEnter = () => {
SiteComponent.send({
eventID: EventPB.Event.EventID.ENTER_SITE,
@@ -286,7 +299,7 @@
avatarID === this.siteAvatarID ||
this.isSiteYellsViewLowest
) {
- this.siteYellsViewMove(siteYellsView);
+ this.siteYellsViewMove();
} else {
runInAction(() => {
this.lastPendingSiteYell = siteYellItem;
@@ -392,28 +405,30 @@
break;
case EventPB.Event.EventID.GET_SITE_YELLS:
if (text) {
- const { current } = siteYellsView;
- if (current) {
- const lastPosition1BeforeCalled =
- current.scrollHeight - current.clientHeight;
- const { siteID, data } = JSON.parse(text);
+ if (this.siteYellsView) {
+ const { current } = this.siteYellsView;
+ if (current) {
+ const lastPosition1BeforeCalled =
+ current.scrollHeight - current.clientHeight;
+ const { siteID, data } = JSON.parse(text);
- data
- .reverse()
- .map(getSiteYellItem)
- .forEach((siteYellItem: SiteYell) => {
- this.putSiteYell(siteID, siteYellItem, true);
- if (this.targetSiteID === siteID) {
- this.putTargetSiteYell(siteYellItem, true);
- }
- });
+ data
+ .reverse()
+ .map(getSiteYellItem)
+ .forEach((siteYellItem: SiteYell) => {
+ this.putSiteYell(siteID, siteYellItem, true);
+ if (this.targetSiteID === siteID) {
+ this.putTargetSiteYell(siteYellItem, true);
+ }
+ });
- setTimeout(() => {
- current.scrollTop =
- current.scrollHeight -
- current.clientHeight -
- lastPosition1BeforeCalled;
- }, 0);
+ setTimeout(() => {
+ current.scrollTop =
+ current.scrollHeight -
+ current.clientHeight -
+ lastPosition1BeforeCalled;
+ }, 0);
+ }
}
}
break;
@@ -474,7 +489,7 @@
avatars: [],
siteYells: data.map(getSiteYellItem),
});
- this.onSiteIDModified(siteID, siteYellsView);
+ this.onSiteIDModified(siteID);
}
break;
case EventPB.Event.EventID.QUIT_SITE:
@@ -482,7 +497,6 @@
this.quitSiteView(text);
this.onSiteIDModified(
this.siteViews[this.siteViews.length - 1]?.siteID,
- siteYellsView,
);
}
break;
@@ -504,13 +518,11 @@
});
},
- setEventCloseHandler(
- siteYellsView: MutableRefObject,
- ) {
+ setEventCloseHandler() {
SiteComponent.setEventCloseHandler(() => {
this.setSiteAvatar("", "");
this.setSignedIn(false);
- this.onSiteIDModified("", siteYellsView);
+ this.onSiteIDModified("");
this.wipeSiteViews();
this.setLoading(true);
});
@@ -656,10 +668,7 @@
return this.siteViews.find(({ siteID }) => siteID === targetSiteID);
},
- onSiteIDModified(
- siteID: string,
- siteYellsView: MutableRefObject,
- ) {
+ onSiteIDModified(siteID: string) {
this.targetSiteID = siteID;
const siteView = this.getSiteView(siteID);
if (siteView) {
@@ -673,7 +682,7 @@
this.siteNotify = siteView.siteNotify;
this.avatars = [...siteView.avatars];
this.siteYells = [...siteView.siteYells];
- this.siteYellsViewMove(siteYellsView);
+ this.siteYellsViewMove();
} else {
this.isEditable = false;
this.siteNotify = "";
@@ -686,11 +695,13 @@
return (this.isVisible = document.visibilityState === "visible");
},
- siteYellsViewMove(siteYellsView: MutableRefObject) {
+ siteYellsViewMove() {
setTimeout(() => {
- const { current } = siteYellsView;
- if (current) {
- current.scrollTop = current.scrollHeight;
+ if (this.siteYellsView) {
+ const { current } = this.siteYellsView;
+ if (current) {
+ current.scrollTop = current.scrollHeight;
+ }
}
}, 0);
},
diff --git a/qwilight-fe/src/site/useGetSites.ts b/qwilight-fe/src/site/useGetSites.ts
index cc280bc..ca504c1 100644
--- a/qwilight-fe/src/site/useGetSites.ts
+++ b/qwilight-fe/src/site/useGetSites.ts
@@ -1,21 +1,21 @@
import { useQuery } from "@tanstack/react-query";
-import { useLocation } from "react-router-dom";
-import { useTranslation } from "react-i18next";
-import { wwwAXIOS } from "src/Www";
-import { GetSitesAPI } from "src/wwwAPI";
-import { useSiteStore } from "src/Stores";
-import { getSiteName } from "src/Utility";
+import { wwwAXIOS } from "@/Www";
+import { GetSitesAPI } from "@/wwwAPI";
+import { useSiteStore } from "@/Stores";
+import { getSiteName } from "@/Utility";
+import { useTranslations } from "next-intl";
+import { useIsPath } from "taehui-ts/fe-utility";
export default function useGetSites() {
const { isSiteWindowOpened } = useSiteStore();
- const { t } = useTranslation();
+ const t = useTranslations();
- const { pathname } = useLocation();
+ const isPath = useIsPath();
return useQuery({
- enabled: isSiteWindowOpened && pathname.startsWith("/qwilight/site"),
+ enabled: isSiteWindowOpened && isPath("/site"),
queryKey: ["sites"],
queryFn: async () => {
const { data } = await wwwAXIOS.get("/sites");
diff --git a/qwilight-fe/src/site/useSiteComponent.tsx b/qwilight-fe/src/site/useSiteComponent.tsx
index 8c42f89..5c46f34 100644
--- a/qwilight-fe/src/site/useSiteComponent.tsx
+++ b/qwilight-fe/src/site/useSiteComponent.tsx
@@ -1,11 +1,9 @@
import { MutableRefObject, useEffect } from "react";
-import { useTranslation } from "react-i18next";
-import { useSiteStore } from "src/Stores";
-import SiteComponent from "src/site/SiteComponent";
+import { useSiteStore } from "@/Stores";
+import SiteComponent from "@/site/SiteComponent";
+import { useTranslations } from "next-intl";
-export default function useSiteComponent(
- siteYellsView: MutableRefObject,
-) {
+export default function useSiteComponent() {
const {
targetSiteID,
getSiteView,
@@ -13,7 +11,7 @@
setEventHandler,
setEventCloseHandler,
} = useSiteStore();
- const { t } = useTranslation();
+ const t = useTranslations();
useEffect(() => {
const onVisibilityModified = () => {
@@ -34,9 +32,9 @@
useEffect(() => {
setVisible();
- setEventHandler(siteYellsView, t);
- setEventCloseHandler(siteYellsView);
- }, [setEventCloseHandler, setEventHandler, setVisible, siteYellsView, t]);
+ setEventHandler(t);
+ setEventCloseHandler();
+ }, [setEventCloseHandler, setEventHandler, setVisible, t]);
useEffect(() => {
SiteComponent.connect();
diff --git a/qwilight-fe/src/useGetTitle.ts b/qwilight-fe/src/useGetTitle.ts
index dab4891..905bd35 100644
--- a/qwilight-fe/src/useGetTitle.ts
+++ b/qwilight-fe/src/useGetTitle.ts
@@ -1,8 +1,8 @@
import { useQuery } from "@tanstack/react-query";
import { getLanguage } from "taehui-ts/language";
-import { wwwAXIOS } from "src/Www";
-import { GetTitleAPI } from "src/wwwAPI";
+import { wwwAXIOS } from "@/Www";
+import { GetTitleAPI } from "@/wwwAPI";
export default function useGetTitle(avatarID: string) {
const language = getLanguage();
diff --git a/qwilight-fe/tsconfig.json b/qwilight-fe/tsconfig.json
index a2fa134..002d44f 100644
--- a/qwilight-fe/tsconfig.json
+++ b/qwilight-fe/tsconfig.json
@@ -4,17 +4,24 @@
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
- "esModuleInterop": true,
- "allowSyntheticDefaultImports": true,
"strict": true,
- "forceConsistentCasingInFileNames": true,
- "noFallthroughCasesInSwitch": true,
+ "noEmit": true,
+ "esModuleInterop": true,
"module": "esnext",
- "moduleResolution": "node",
+ "moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
- "noEmit": true,
- "jsx": "react-jsx",
- "baseUrl": "."
- }
+ "jsx": "preserve",
+ "incremental": true,
+ "plugins": [
+ {
+ "name": "next"
+ }
+ ],
+ "paths": {
+ "@/*": ["./src/*"]
+ }
+ },
+ "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
+ "exclude": ["node_modules"],
}
diff --git a/taehui-ts/.eslintrc.json b/taehui-ts/.eslintrc.json
new file mode 100644
index 0000000..bffb357
--- /dev/null
+++ b/taehui-ts/.eslintrc.json
@@ -0,0 +1,3 @@
+{
+ "extends": "next/core-web-vitals"
+}
diff --git a/taehui-ts/package.json b/taehui-ts/package.json
index 4392a7a..f69e86e 100644
--- a/taehui-ts/package.json
+++ b/taehui-ts/package.json
@@ -25,30 +25,37 @@
"@types/qs": "^6.9.12",
"@types/react": "^18.2.65",
"dayjs": "^1.11.10",
+ "eslint-config-next": "^14.1.3",
+ "next": "^14.1.3",
+ "next-intl": "^3.9.5",
"qs": "^6.12.0",
"react": "^18.2.0",
- "react-router-dom": "^6.22.3",
"rollup": "^4.13.0",
- "tslib": "^2.6.2"
+ "tslib": "^2.6.2",
+ "urlcat": "^3.1.0"
},
"peerDependencies": {
"dayjs": "^1.11.10",
+ "next": "^14.1.3",
+ "next-intl": "^3.9.5",
"qs": "^6.11.2",
- "react": "^18.2.0",
- "react-router-dom": "^6.18.0"
+ "react": "^18.2.0"
},
"peerDependenciesMeta": {
"dayjs": {
"optional": true
},
+ "next": {
+ "optional": true
+ },
+ "next-intl": {
+ "optional": true
+ },
"qs": {
"optional": true
},
"react": {
"optional": true
- },
- "react-router-dom": {
- "optional": true
}
},
"scripts": {
diff --git a/taehui-ts/rollup.config.mjs b/taehui-ts/rollup.config.mjs
index 5407976..f4756f2 100644
--- a/taehui-ts/rollup.config.mjs
+++ b/taehui-ts/rollup.config.mjs
@@ -2,7 +2,7 @@
import typescript from "@rollup/plugin-typescript";
export default defineConfig({
- external: ["dayjs", "qs", "react", "react-router-dom"],
+ external: ["dayjs", "next", "next-intl", "qs", "react"],
input: ["src/date.ts", "src/language.ts", "src/fe-utility.ts"],
plugins: [
typescript({
diff --git a/taehui-ts/src/fe-utility.ts b/taehui-ts/src/fe-utility.ts
index f32d2e9..0bcf9cd 100644
--- a/taehui-ts/src/fe-utility.ts
+++ b/taehui-ts/src/fe-utility.ts
@@ -1,9 +1,21 @@
+import {
+ useParams,
+ usePathname,
+ useRouter,
+ useSearchParams,
+} from "next/navigation";
import { useCallback, useEffect, useState } from "react";
-import { useNavigate, useParams, useSearchParams } from "react-router-dom";
+import { parse, stringify } from "qs";
+import urlcat from "urlcat";
+import { useLocale } from "next-intl";
export function useWindowArea() {
- const [windowLength, setWindowLength] = useState(window.innerWidth);
- const [windowHeight, setWindowHeight] = useState(window.innerHeight);
+ const [windowLength, setWindowLength] = useState(
+ typeof window === "object" ? window.innerWidth : 0,
+ );
+ const [windowHeight, setWindowHeight] = useState(
+ typeof window === "object" ? window.innerHeight : 0,
+ );
useEffect(() => {
const onModified = () => {
@@ -22,24 +34,28 @@
}
export function useTo() {
- const navigate = useNavigate();
+ const { push } = useRouter();
- return (pathname: string, search: string = window.location.search) =>
- navigate({ ...window.location, pathname, search });
+ return useCallback(
+ (pathname: string, search = "") => push(urlcat(pathname, parse(search))),
+ [push],
+ );
}
export function useParam(text: string, defaultValue: string) {
- const [searchParams, setSearchParams] = useSearchParams();
+ const to = useTo();
+ const searchParams = useSearchParams();
const param = searchParams.get(text) ?? defaultValue;
+ const pathname = usePathname();
+
return {
param,
setParam: useCallback(
(param: string) => {
- searchParams.set(text, param.toString());
- setSearchParams(searchParams);
+ to(pathname, stringify({ ...searchParams.entries(), [text]: param }));
},
- [searchParams, setSearchParams],
+ [pathname, searchParams, text, to],
),
};
}
@@ -60,10 +76,10 @@
export function useWant(route: string) {
const to = useTo();
- const { want = "" } = useParams<{ want: string }>();
+ const { want = [] } = useParams();
return {
- want,
+ want: Array.isArray(want) ? want[0] : want,
setWant: useCallback(
(want: string) => {
to(route + "/" + want);
@@ -72,3 +88,13 @@
),
};
}
+
+export function useIsPath() {
+ const pathname = usePathname();
+ const locale = useLocale();
+
+ return useCallback(
+ (route: string) => pathname.startsWith(`/${locale}${route}`),
+ [locale, pathname],
+ );
+}
diff --git a/taehui-ts/src/language.ts b/taehui-ts/src/language.ts
index d1381b3..2bc117b 100644
--- a/taehui-ts/src/language.ts
+++ b/taehui-ts/src/language.ts
@@ -1,14 +1,17 @@
import { parse } from "qs";
export const getLanguage = () => {
- let { language } = parse(window.location.search, {
- ignoreQueryPrefix: true,
- });
- language = (language && String(language)) ?? window.navigator.language;
- if (language.startsWith("ko")) {
- return "ko-KR";
+ if (typeof window === "object") {
+ let { language } = parse(window.location.search, {
+ ignoreQueryPrefix: true,
+ });
+ language = (language && String(language)) ?? window.navigator.language;
+ if (language.startsWith("ko")) {
+ return "ko-KR";
+ } else {
+ return "en-US";
+ }
} else {
return "en-US";
}
};
-