From d9ae1aeed4a05ea40ef62b153196e8e70bd90537 Mon Sep 17 00:00:00 2001 From: Frenkie Nguyen Date: Mon, 30 Dec 2024 15:01:17 +0700 Subject: [PATCH 1/8] [Issue-157][Mythical Telegram App] update time remaining --- .../extension-koni-ui/src/Popup/Home/LeaderboardTemp/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/extension-koni-ui/src/Popup/Home/LeaderboardTemp/index.tsx b/packages/extension-koni-ui/src/Popup/Home/LeaderboardTemp/index.tsx index b8e9c01b33..7d3b1163e5 100644 --- a/packages/extension-koni-ui/src/Popup/Home/LeaderboardTemp/index.tsx +++ b/packages/extension-koni-ui/src/Popup/Home/LeaderboardTemp/index.tsx @@ -127,7 +127,7 @@ const Component = ({ className }: Props): React.ReactElement => { const delayEndTime = delayStartTime + Number(leaderboardInfo.specialTimeDelayDuration) * 86400000; if (currentTime > delayStartTime) { - return getTimeRemaining(delayStartTime, new Date(delayEndTime).toString()); + return getTimeRemaining(currentTime, new Date(delayEndTime).toString()); } return undefined; From c538d7489dc39e9fe141947b65eefc65bc790857 Mon Sep 17 00:00:00 2001 From: Frenkie Nguyen Date: Tue, 31 Dec 2024 13:09:00 +0700 Subject: [PATCH 2/8] [Issue-157][Mythical Telegram App] update time remaining --- .../extension-koni-ui/src/Popup/Home/LeaderboardTemp/index.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/extension-koni-ui/src/Popup/Home/LeaderboardTemp/index.tsx b/packages/extension-koni-ui/src/Popup/Home/LeaderboardTemp/index.tsx index 7d3b1163e5..fd4f40dcd5 100644 --- a/packages/extension-koni-ui/src/Popup/Home/LeaderboardTemp/index.tsx +++ b/packages/extension-koni-ui/src/Popup/Home/LeaderboardTemp/index.tsx @@ -167,6 +167,7 @@ const Component = ({ className }: Props): React.ReactElement => { } From e63b34b1b32b3d717e1ff957720c5d62ce0a4cd5 Mon Sep 17 00:00:00 2001 From: Frenkie Nguyen Date: Tue, 31 Dec 2024 15:11:53 +0700 Subject: [PATCH 3/8] [Issue-253][Mythical Telegram App] Displays the number of MYTH received by TOP 3 on the Leaderboard --- .../Home/LeaderboardTemp/TopThreeArea.tsx | 33 +++++++++++++++++-- .../src/Popup/Home/LeaderboardTemp/index.tsx | 3 +- .../Mythical/Leaderboard/TopAccountItem.tsx | 9 ++--- 3 files changed, 38 insertions(+), 7 deletions(-) diff --git a/packages/extension-koni-ui/src/Popup/Home/LeaderboardTemp/TopThreeArea.tsx b/packages/extension-koni-ui/src/Popup/Home/LeaderboardTemp/TopThreeArea.tsx index 3c26437179..11e89414db 100644 --- a/packages/extension-koni-ui/src/Popup/Home/LeaderboardTemp/TopThreeArea.tsx +++ b/packages/extension-koni-ui/src/Popup/Home/LeaderboardTemp/TopThreeArea.tsx @@ -3,14 +3,16 @@ import { TopAccountItem } from '@subwallet/extension-koni-ui/components/Mythical'; import { TopAccountItemType } from '@subwallet/extension-koni-ui/components/Mythical/Leaderboard/TopAccountItem'; +import { BookaSdk } from '@subwallet/extension-koni-ui/connector/booka/sdk'; import { LeaderboardPerson } from '@subwallet/extension-koni-ui/connector/booka/types'; import { ThemeProps } from '@subwallet/extension-koni-ui/types'; -import React from 'react'; +import React, { useEffect, useMemo, useState } from 'react'; import styled from 'styled-components'; type Props = ThemeProps & { leaderboardPersonItems: LeaderboardPerson[]; isLoading: boolean; + customDateTimeHandler?: (currentTime?: number) => string | undefined; }; function getTopAccountItem (gameAccountItem: LeaderboardPerson | undefined, rank: number): TopAccountItemType { @@ -32,7 +34,31 @@ function getTopAccountItem (gameAccountItem: LeaderboardPerson | undefined, rank }; } -const Component = ({ className, isLoading, leaderboardPersonItems }: Props): React.ReactElement => { +const apiSDK = BookaSdk.instance; + +const Component = ({ className, customDateTimeHandler, isLoading, leaderboardPersonItems }: Props): React.ReactElement => { + const [serverTime, setServerTime] = useState(); + + useEffect(() => { + const serverTimeSubject = apiSDK.subscribeServerTime(); + + const updateDateTime = (value: number) => { + setServerTime(value); + }; + + updateDateTime(serverTimeSubject.value); + + const timeSub = serverTimeSubject.subscribe((value) => { + updateDateTime(value); + }); + + return () => { + timeSub.unsubscribe(); + }; + }, []); + + const isShowToken = useMemo(() => !!customDateTimeHandler?.(serverTime), [customDateTimeHandler, serverTime]); + return (
}
@@ -50,6 +77,7 @@ const Component = ({ className, isLoading, leaderboardPersonItems }: Props): Rea } @@ -58,6 +86,7 @@ const Component = ({ className, isLoading, leaderboardPersonItems }: Props): Rea } diff --git a/packages/extension-koni-ui/src/Popup/Home/LeaderboardTemp/index.tsx b/packages/extension-koni-ui/src/Popup/Home/LeaderboardTemp/index.tsx index fd4f40dcd5..9963bf5b93 100644 --- a/packages/extension-koni-ui/src/Popup/Home/LeaderboardTemp/index.tsx +++ b/packages/extension-koni-ui/src/Popup/Home/LeaderboardTemp/index.tsx @@ -126,7 +126,7 @@ const Component = ({ className }: Props): React.ReactElement => { const delayStartTime = leaderboardInfo?.endTimeTs; const delayEndTime = delayStartTime + Number(leaderboardInfo.specialTimeDelayDuration) * 86400000; - if (currentTime > delayStartTime) { + if (currentTime > delayStartTime && currentTime < delayEndTime) { return getTimeRemaining(currentTime, new Date(delayEndTime).toString()); } @@ -174,6 +174,7 @@ const Component = ({ className }: Props): React.ReactElement => {
diff --git a/packages/extension-koni-ui/src/components/Mythical/Leaderboard/TopAccountItem.tsx b/packages/extension-koni-ui/src/components/Mythical/Leaderboard/TopAccountItem.tsx index be52c887da..d368515766 100644 --- a/packages/extension-koni-ui/src/components/Mythical/Leaderboard/TopAccountItem.tsx +++ b/packages/extension-koni-ui/src/components/Mythical/Leaderboard/TopAccountItem.tsx @@ -19,10 +19,11 @@ export type TopAccountItemType = { } type Props = ThemeProps & TopAccountItemType & { - isLoading?: boolean + isLoading?: boolean, + isShowToken?: boolean }; -const Component = ({ avatarSrc, className, isFirst, isLoading, name = '---', point = 0, rank, tokenValue = 0 }: Props): React.ReactElement => { +const Component = ({ avatarSrc, className, isFirst, isLoading, isShowToken, name = '---', point = 0, rank, tokenValue = 0 }: Props): React.ReactElement => { return (
-
+ {isShowToken &&
{isLoading ? ( )} -
+
}
); From 87f3c1141d3ab68ec5c490b20beb465123d4a7ed Mon Sep 17 00:00:00 2001 From: Frenkie Nguyen Date: Thu, 2 Jan 2025 11:22:51 +0700 Subject: [PATCH 4/8] [Issue-253, 157][Mythical TeleApp] Handle token visibility and update the UI for delay time. --- .../Home/LeaderboardTemp/TopThreeArea.tsx | 37 +++------------ .../src/Popup/Home/LeaderboardTemp/index.tsx | 47 ++++++++++++------- .../Mythical/Common/TimeRemaining.tsx | 44 +++++------------ .../Mythical/Leaderboard/TopAccountItem.tsx | 6 +-- .../src/hooks/common/index.ts | 1 + .../src/hooks/common/useServerTime.ts | 35 ++++++++++++++ 6 files changed, 85 insertions(+), 85 deletions(-) create mode 100644 packages/extension-koni-ui/src/hooks/common/useServerTime.ts diff --git a/packages/extension-koni-ui/src/Popup/Home/LeaderboardTemp/TopThreeArea.tsx b/packages/extension-koni-ui/src/Popup/Home/LeaderboardTemp/TopThreeArea.tsx index 11e89414db..75f03c311a 100644 --- a/packages/extension-koni-ui/src/Popup/Home/LeaderboardTemp/TopThreeArea.tsx +++ b/packages/extension-koni-ui/src/Popup/Home/LeaderboardTemp/TopThreeArea.tsx @@ -3,16 +3,15 @@ import { TopAccountItem } from '@subwallet/extension-koni-ui/components/Mythical'; import { TopAccountItemType } from '@subwallet/extension-koni-ui/components/Mythical/Leaderboard/TopAccountItem'; -import { BookaSdk } from '@subwallet/extension-koni-ui/connector/booka/sdk'; import { LeaderboardPerson } from '@subwallet/extension-koni-ui/connector/booka/types'; import { ThemeProps } from '@subwallet/extension-koni-ui/types'; -import React, { useEffect, useMemo, useState } from 'react'; +import React from 'react'; import styled from 'styled-components'; type Props = ThemeProps & { leaderboardPersonItems: LeaderboardPerson[]; isLoading: boolean; - customDateTimeHandler?: (currentTime?: number) => string | undefined; + shouldShowToken?: boolean; }; function getTopAccountItem (gameAccountItem: LeaderboardPerson | undefined, rank: number): TopAccountItemType { @@ -34,31 +33,7 @@ function getTopAccountItem (gameAccountItem: LeaderboardPerson | undefined, rank }; } -const apiSDK = BookaSdk.instance; - -const Component = ({ className, customDateTimeHandler, isLoading, leaderboardPersonItems }: Props): React.ReactElement => { - const [serverTime, setServerTime] = useState(); - - useEffect(() => { - const serverTimeSubject = apiSDK.subscribeServerTime(); - - const updateDateTime = (value: number) => { - setServerTime(value); - }; - - updateDateTime(serverTimeSubject.value); - - const timeSub = serverTimeSubject.subscribe((value) => { - updateDateTime(value); - }); - - return () => { - timeSub.unsubscribe(); - }; - }, []); - - const isShowToken = useMemo(() => !!customDateTimeHandler?.(serverTime), [customDateTimeHandler, serverTime]); - +const Component = ({ className, isLoading, leaderboardPersonItems, shouldShowToken }: Props): React.ReactElement => { return (
}
@@ -77,7 +52,7 @@ const Component = ({ className, customDateTimeHandler, isLoading, leaderboardPer }
@@ -86,7 +61,7 @@ const Component = ({ className, customDateTimeHandler, isLoading, leaderboardPer } diff --git a/packages/extension-koni-ui/src/Popup/Home/LeaderboardTemp/index.tsx b/packages/extension-koni-ui/src/Popup/Home/LeaderboardTemp/index.tsx index 9963bf5b93..dd633ab300 100644 --- a/packages/extension-koni-ui/src/Popup/Home/LeaderboardTemp/index.tsx +++ b/packages/extension-koni-ui/src/Popup/Home/LeaderboardTemp/index.tsx @@ -6,7 +6,7 @@ import { BookaSdk } from '@subwallet/extension-koni-ui/connector/booka/sdk'; import { LeaderboardGroups, LeaderboardInfo, LeaderboardPerson } from '@subwallet/extension-koni-ui/connector/booka/types'; import { LINK_NFL_APP_DOWNLOAD } from '@subwallet/extension-koni-ui/constants'; import { HomeContext } from '@subwallet/extension-koni-ui/contexts/screen/HomeContext'; -import { useSetCurrentPage } from '@subwallet/extension-koni-ui/hooks'; +import { useServerTime, useSetCurrentPage } from '@subwallet/extension-koni-ui/hooks'; import { GameAccountListArea } from '@subwallet/extension-koni-ui/Popup/Home/LeaderboardTemp/GameAccountListArea'; import { LeaderboardMetadata, TERM_AND_CONDITION_MODAL_ID, TermAndConditionModal } from '@subwallet/extension-koni-ui/Popup/Home/LeaderboardTemp/TermAndConditionModal'; import { TopThreeArea } from '@subwallet/extension-koni-ui/Popup/Home/LeaderboardTemp/TopThreeArea'; @@ -32,6 +32,7 @@ const Component = ({ className }: Props): React.ReactElement => { const [isLoading, setIsLoading] = useState(true); const [leaderboardInfo, setLeaderboardInfo] = useState(undefined); const { activeModal, inactiveModal } = useContext(ModalContext); + const { serverTime } = useServerTime(); useEffect(() => { const subscriptionLeaderboard = apiSDK.subscribeLeaderboardConfig().subscribe((data) => { @@ -118,32 +119,41 @@ const Component = ({ className }: Props): React.ReactElement => { return !!(leaderboard && 'title' in leaderboard && 'content' in leaderboard); }, [leaderboardInfo]); - const timeRemainingDateTimeHandler = useCallback((currentTime?: number) => { - if (!leaderboardInfo?.endTimeTs || !currentTime) { + const specialTimeRemaining = useMemo(() => { + if (!leaderboardInfo?.endTimeTs || !serverTime) { return undefined; } const delayStartTime = leaderboardInfo?.endTimeTs; const delayEndTime = delayStartTime + Number(leaderboardInfo.specialTimeDelayDuration) * 86400000; - if (currentTime > delayStartTime && currentTime < delayEndTime) { - return getTimeRemaining(currentTime, new Date(delayEndTime).toString()); - } + const targetTime = serverTime > delayStartTime && serverTime < delayEndTime + ? delayEndTime + : delayStartTime; - return undefined; - }, [leaderboardInfo?.endTimeTs, leaderboardInfo?.specialTimeDelayDuration]); + return getTimeRemaining(serverTime, new Date(targetTime).toString()); + }, [leaderboardInfo?.endTimeTs, leaderboardInfo?.specialTimeDelayDuration, serverTime]); - const timeRemainingTitleHandler = useCallback((currentTime?: number) => { - if (!leaderboardInfo?.endTimeTs || !currentTime) { - return undefined; + const shouldShowToken = useMemo(() => { + if (!leaderboardInfo?.endTimeTs || !serverTime) { + return false; } - if (currentTime > leaderboardInfo?.endTimeTs) { - return t('New leaderboard in'); + const delayStartTime = leaderboardInfo?.endTimeTs; + const delayEndTime = delayStartTime + Number(leaderboardInfo.specialTimeDelayDuration) * 86400000; + + return serverTime > delayStartTime && serverTime < delayEndTime; + }, [leaderboardInfo?.endTimeTs, leaderboardInfo?.specialTimeDelayDuration, serverTime]); + + const specialTimeTitle = useMemo(() => { + if (!leaderboardInfo?.endTimeTs || !serverTime) { + return undefined; } - return undefined; - }, [leaderboardInfo?.endTimeTs, t]); + return serverTime > leaderboardInfo.endTimeTs + ? t('New leaderboard in') + : t('Time remaining'); + }, [leaderboardInfo?.endTimeTs, serverTime, t]); return (
@@ -165,18 +175,19 @@ const Component = ({ className }: Props): React.ReactElement => { {
}
{isLoading ? ( diff --git a/packages/extension-koni-ui/src/components/Mythical/Common/TimeRemaining.tsx b/packages/extension-koni-ui/src/components/Mythical/Common/TimeRemaining.tsx index 84a672328f..e1af4b3764 100644 --- a/packages/extension-koni-ui/src/components/Mythical/Common/TimeRemaining.tsx +++ b/packages/extension-koni-ui/src/components/Mythical/Common/TimeRemaining.tsx @@ -1,10 +1,9 @@ // Copyright 2019-2022 @subwallet/extension-ui authors & contributors // SPDX-License-Identifier: Apache-2.0 -import { BookaSdk } from '@subwallet/extension-koni-ui/connector/booka/sdk'; import { ThemeProps } from '@subwallet/extension-koni-ui/types'; import { getTimeRemaining } from '@subwallet/extension-koni-ui/utils'; -import React, { useEffect, useMemo, useState } from 'react'; +import React, { useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import styled from 'styled-components'; @@ -12,51 +11,30 @@ import { ClockIcon } from '../Icon'; type Props = ThemeProps & { endTime?: string; - customDateTimeHandler?: (currentTime?: number) => string | undefined; - customTitleHandler?: (currentTime?: number) => string | undefined; + specialTimeRemaining?: string; + specialTimeTitle?: string; + serverTime?: number; }; -const apiSDK = BookaSdk.instance; - -const Component = ({ className, customDateTimeHandler, customTitleHandler, endTime }: Props): React.ReactElement => { +const Component = ({ className, endTime, serverTime, specialTimeRemaining, specialTimeTitle }: Props): React.ReactElement => { const { t } = useTranslation(); - const [serverTime, setServerTime] = useState(); - - useEffect(() => { - const serverTimeSubject = apiSDK.subscribeServerTime(); - - const updateDateTime = (value: number) => { - setServerTime(value); - }; - - updateDateTime(serverTimeSubject.value); - - const timeSub = serverTimeSubject.subscribe((value) => { - updateDateTime(value); - }); - - return () => { - timeSub.unsubscribe(); - }; - }, []); - const timeRemainingTitle = useMemo(() => { - if (customTitleHandler && !!customTitleHandler(serverTime)) { - return customTitleHandler(serverTime); + if (specialTimeTitle) { + return specialTimeTitle; } return t('Time remaining'); - }, [customTitleHandler, serverTime, t]); + }, [specialTimeTitle, t]); const dateTime = useMemo(() => { - if (customDateTimeHandler && !!customDateTimeHandler(serverTime)) { - return customDateTimeHandler(serverTime); + if (specialTimeRemaining) { + return specialTimeRemaining; } else if (endTime) { return getTimeRemaining(serverTime, endTime); } return '---'; - }, [customDateTimeHandler, endTime, serverTime]); + }, [specialTimeRemaining, endTime, serverTime]); return (
{ +const Component = ({ avatarSrc, className, isFirst, isLoading, name = '---', point = 0, rank, shouldShowToken, tokenValue = 0 }: Props): React.ReactElement => { return (
- {isShowToken &&
+ {shouldShowToken &&
{isLoading ? ( { + const [serverTime, setServerTime] = useState(); + + useEffect(() => { + const serverTimeSubject = apiSDK.subscribeServerTime(); + + const updateDateTime = (value: number) => { + setServerTime(value); + }; + + updateDateTime(serverTimeSubject.value); + + const timeSub = serverTimeSubject.subscribe((value) => { + updateDateTime(value); + }); + + return () => { + timeSub.unsubscribe(); + }; + }, []); + + return { + serverTime + }; +}; + +export default useServerTime; From e6a82cec0b5d5c13e97cc2bc626dcdb61f3dce12 Mon Sep 17 00:00:00 2001 From: Frenkie Nguyen Date: Thu, 2 Jan 2025 12:29:48 +0700 Subject: [PATCH 5/8] [Issue-253, 157][Mythical TeleApp] Handle token visibility and update the UI for delay time. --- .../src/Popup/Home/LeaderboardTemp/index.tsx | 10 ++++------ .../src/Popup/Home/MissionTemp/index.tsx | 20 ++++++------------- 2 files changed, 10 insertions(+), 20 deletions(-) diff --git a/packages/extension-koni-ui/src/Popup/Home/LeaderboardTemp/index.tsx b/packages/extension-koni-ui/src/Popup/Home/LeaderboardTemp/index.tsx index dd633ab300..6b8bee71ea 100644 --- a/packages/extension-koni-ui/src/Popup/Home/LeaderboardTemp/index.tsx +++ b/packages/extension-koni-ui/src/Popup/Home/LeaderboardTemp/index.tsx @@ -119,7 +119,7 @@ const Component = ({ className }: Props): React.ReactElement => { return !!(leaderboard && 'title' in leaderboard && 'content' in leaderboard); }, [leaderboardInfo]); - const specialTimeRemaining = useMemo(() => { + const timeRemainingDateTime = useMemo(() => { if (!leaderboardInfo?.endTimeTs || !serverTime) { return undefined; } @@ -145,7 +145,7 @@ const Component = ({ className }: Props): React.ReactElement => { return serverTime > delayStartTime && serverTime < delayEndTime; }, [leaderboardInfo?.endTimeTs, leaderboardInfo?.specialTimeDelayDuration, serverTime]); - const specialTimeTitle = useMemo(() => { + const timeRemainingTitle = useMemo(() => { if (!leaderboardInfo?.endTimeTs || !serverTime) { return undefined; } @@ -175,10 +175,8 @@ const Component = ({ className }: Props): React.ReactElement => { {
} diff --git a/packages/extension-koni-ui/src/Popup/Home/MissionTemp/index.tsx b/packages/extension-koni-ui/src/Popup/Home/MissionTemp/index.tsx index 59fb709aa2..05e6b616bc 100644 --- a/packages/extension-koni-ui/src/Popup/Home/MissionTemp/index.tsx +++ b/packages/extension-koni-ui/src/Popup/Home/MissionTemp/index.tsx @@ -7,7 +7,7 @@ import { BookaSdk } from '@subwallet/extension-koni-ui/connector/booka/sdk'; import { Achievement, Task, TaskCategory, TaskCategoryType } from '@subwallet/extension-koni-ui/connector/booka/types'; import { LINK_NFL_APP_DOWNLOAD } from '@subwallet/extension-koni-ui/constants'; import { HomeContext } from '@subwallet/extension-koni-ui/contexts/screen/HomeContext'; -import { useSetCurrentPage } from '@subwallet/extension-koni-ui/hooks'; +import { useServerTime, useSetCurrentPage } from '@subwallet/extension-koni-ui/hooks'; import { ThemeProps } from '@subwallet/extension-koni-ui/types'; import { openInNewTab } from '@subwallet/extension-koni-ui/utils'; import React, { useCallback, useContext, useEffect, useMemo, useState } from 'react'; @@ -32,8 +32,7 @@ const Component = ({ className }: Props): React.ReactElement => { const [achievements, setAchievements] = useState(apiSDK.achievementList); const [selectedFilterTab, setSelectedFilterTab] = useState(TaskCategoryType.DAILY); const [metadata, setMetadata] = useState(apiSDK.getMetadata()); - const [serverTime, setServerTime] = useState(apiSDK.serverTime); - + const { serverTime } = useServerTime(); const filterTabItems = useMemo(() => { return [ { @@ -73,16 +72,6 @@ const Component = ({ className }: Props): React.ReactElement => { navigate('/invite'); }, [navigate]); - useEffect(() => { - const timeSub = apiSDK.subscribeServerTime().subscribe((time) => { - setServerTime(time); - }); - - return () => { - timeSub.unsubscribe(); - }; - }, []); - useEffect(() => { setBackgroundStyle('style-2'); @@ -151,7 +140,10 @@ const Component = ({ className }: Props): React.ReactElement => { /> {endTime &&
- +
} Date: Thu, 9 Jan 2025 10:54:13 +0700 Subject: [PATCH 6/8] [issue-257]: Use GA for some reports --- .../extension-koni-ui/src/Popup/Home/Cards/index.tsx | 2 ++ .../extension-koni-ui/src/Popup/Home/InviteNew/index.tsx | 2 ++ .../src/Popup/Home/LeaderboardTemp/index.tsx | 2 ++ .../src/Popup/Home/MissionTemp/index.tsx | 2 ++ .../extension-koni-ui/src/Popup/Home/MyProfile/index.tsx | 2 ++ .../components/Mythical/Modal/CardDetailModal/index.tsx | 2 ++ .../src/contexts/AuthenticationMythProvider.tsx | 2 ++ packages/extension-koni-ui/src/utils/googleAnalytics.ts | 9 +++++++++ 8 files changed, 23 insertions(+) create mode 100644 packages/extension-koni-ui/src/utils/googleAnalytics.ts diff --git a/packages/extension-koni-ui/src/Popup/Home/Cards/index.tsx b/packages/extension-koni-ui/src/Popup/Home/Cards/index.tsx index 3a3d482fda..f71e33cc71 100644 --- a/packages/extension-koni-ui/src/Popup/Home/Cards/index.tsx +++ b/packages/extension-koni-ui/src/Popup/Home/Cards/index.tsx @@ -7,6 +7,7 @@ import { NFLRivalCard } from '@subwallet/extension-koni-ui/connector/booka/types import { HomeContext } from '@subwallet/extension-koni-ui/contexts/screen/HomeContext'; import { ThemeProps } from '@subwallet/extension-koni-ui/types'; import { openInNewTab } from '@subwallet/extension-koni-ui/utils'; +import { sendEventGA } from '@subwallet/extension-koni-ui/utils/googleAnalytics'; import { ModalContext } from '@subwallet/react-ui'; import React, { useCallback, useContext, useEffect, useRef, useState } from 'react'; import { useTranslation } from 'react-i18next'; @@ -92,6 +93,7 @@ const Component = ({ className }: Props): React.ReactElement => { }, [setContainerClass]); const handleOpenMarket = useCallback(() => { + sendEventGA('mythical-marketplace-link-click'); openInNewTab(NFL_RIVALS_MARKET_LINK)(); }, []); diff --git a/packages/extension-koni-ui/src/Popup/Home/InviteNew/index.tsx b/packages/extension-koni-ui/src/Popup/Home/InviteNew/index.tsx index 285e8b9144..8545edff30 100644 --- a/packages/extension-koni-ui/src/Popup/Home/InviteNew/index.tsx +++ b/packages/extension-koni-ui/src/Popup/Home/InviteNew/index.tsx @@ -11,6 +11,7 @@ import { LINK_NFL_APP_DOWNLOAD } from '@subwallet/extension-koni-ui/constants'; import { useDefaultNavigate, useNotification, useSetCurrentPage, useTranslation } from '@subwallet/extension-koni-ui/hooks'; import { ThemeProps } from '@subwallet/extension-koni-ui/types'; import { copyToClipboard, openInNewTab } from '@subwallet/extension-koni-ui/utils'; +import { sendEventGA } from '@subwallet/extension-koni-ui/utils/googleAnalytics'; import CN from 'classnames'; import React, { useCallback, useEffect, useMemo, useState } from 'react'; import styled from 'styled-components'; @@ -57,6 +58,7 @@ const Component = ({ className }: Props): React.ReactElement => { }, [inviteURL]); const openAppStoreLink = useCallback(() => { + sendEventGA('nfl-rivals-download-link-click'); openInNewTab(LINK_NFL_APP_DOWNLOAD)(); }, []); diff --git a/packages/extension-koni-ui/src/Popup/Home/LeaderboardTemp/index.tsx b/packages/extension-koni-ui/src/Popup/Home/LeaderboardTemp/index.tsx index 6b8bee71ea..4e65333781 100644 --- a/packages/extension-koni-ui/src/Popup/Home/LeaderboardTemp/index.tsx +++ b/packages/extension-koni-ui/src/Popup/Home/LeaderboardTemp/index.tsx @@ -12,6 +12,7 @@ import { LeaderboardMetadata, TERM_AND_CONDITION_MODAL_ID, TermAndConditionModal import { TopThreeArea } from '@subwallet/extension-koni-ui/Popup/Home/LeaderboardTemp/TopThreeArea'; import { ThemeProps } from '@subwallet/extension-koni-ui/types'; import { getTimeRemaining, openInNewTab } from '@subwallet/extension-koni-ui/utils'; +import { sendEventGA } from '@subwallet/extension-koni-ui/utils/googleAnalytics'; import { ModalContext, Skeleton } from '@subwallet/react-ui'; import CN from 'classnames'; import React, { useCallback, useContext, useEffect, useMemo, useState } from 'react'; @@ -110,6 +111,7 @@ const Component = ({ className }: Props): React.ReactElement => { }, [inactiveModal]); const openAppStoreLink = useCallback(() => { + sendEventGA('nfl-rivals-download-link-click'); openInNewTab(LINK_NFL_APP_DOWNLOAD)(); }, []); diff --git a/packages/extension-koni-ui/src/Popup/Home/MissionTemp/index.tsx b/packages/extension-koni-ui/src/Popup/Home/MissionTemp/index.tsx index 05e6b616bc..3cd6c23eb6 100644 --- a/packages/extension-koni-ui/src/Popup/Home/MissionTemp/index.tsx +++ b/packages/extension-koni-ui/src/Popup/Home/MissionTemp/index.tsx @@ -10,6 +10,7 @@ import { HomeContext } from '@subwallet/extension-koni-ui/contexts/screen/HomeCo import { useServerTime, useSetCurrentPage } from '@subwallet/extension-koni-ui/hooks'; import { ThemeProps } from '@subwallet/extension-koni-ui/types'; import { openInNewTab } from '@subwallet/extension-koni-ui/utils'; +import { sendEventGA } from '@subwallet/extension-koni-ui/utils/googleAnalytics'; import React, { useCallback, useContext, useEffect, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useNavigate } from 'react-router-dom'; @@ -55,6 +56,7 @@ const Component = ({ className }: Props): React.ReactElement => { }, []); const openAppStoreLink = useCallback(() => { + sendEventGA('nfl-rivals-download-link-click'); openInNewTab(LINK_NFL_APP_DOWNLOAD)(); }, []); diff --git a/packages/extension-koni-ui/src/Popup/Home/MyProfile/index.tsx b/packages/extension-koni-ui/src/Popup/Home/MyProfile/index.tsx index 68a46ae9f0..662ee6d0af 100644 --- a/packages/extension-koni-ui/src/Popup/Home/MyProfile/index.tsx +++ b/packages/extension-koni-ui/src/Popup/Home/MyProfile/index.tsx @@ -10,6 +10,7 @@ import { useSetCurrentPage } from '@subwallet/extension-koni-ui/hooks'; import { RootState } from '@subwallet/extension-koni-ui/stores'; import { ThemeProps } from '@subwallet/extension-koni-ui/types'; import { openInNewTab } from '@subwallet/extension-koni-ui/utils'; +import { sendEventGA } from '@subwallet/extension-koni-ui/utils/googleAnalytics'; import React, { useCallback, useContext, useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useSelector } from 'react-redux'; @@ -35,6 +36,7 @@ const Component = ({ className }: Props): React.ReactElement => { }, [currentAccount?.address, linkMythAccount]); const openAppStoreLink = useCallback(() => { + sendEventGA('nfl-rivals-download-link-click'); openInNewTab(LINK_NFL_APP_DOWNLOAD)(); }, []); diff --git a/packages/extension-koni-ui/src/components/Mythical/Modal/CardDetailModal/index.tsx b/packages/extension-koni-ui/src/components/Mythical/Modal/CardDetailModal/index.tsx index 00b8cd85a7..6b51684cac 100644 --- a/packages/extension-koni-ui/src/components/Mythical/Modal/CardDetailModal/index.tsx +++ b/packages/extension-koni-ui/src/components/Mythical/Modal/CardDetailModal/index.tsx @@ -7,6 +7,7 @@ import { NFLRivalCard } from '@subwallet/extension-koni-ui/connector/booka/types import { eventStat } from '@subwallet/extension-koni-ui/constants'; import { ThemeProps } from '@subwallet/extension-koni-ui/types'; import { openInNewTab } from '@subwallet/extension-koni-ui/utils'; +import { sendEventGA } from '@subwallet/extension-koni-ui/utils/googleAnalytics'; import { SwModal } from '@subwallet/react-ui'; import CN from 'classnames'; import React, { useCallback } from 'react'; @@ -24,6 +25,7 @@ function Component ({ card, className = '', id, onCancel }: Props): React.ReactE const { t } = useTranslation(); const handleOpenMarket = useCallback(() => { + sendEventGA('mythical-marketplace-link-click'); openInNewTab(NFL_RIVALS_MARKET_LINK)(); }, []); diff --git a/packages/extension-koni-ui/src/contexts/AuthenticationMythProvider.tsx b/packages/extension-koni-ui/src/contexts/AuthenticationMythProvider.tsx index 2be5aa996f..7ba49c3a83 100644 --- a/packages/extension-koni-ui/src/contexts/AuthenticationMythProvider.tsx +++ b/packages/extension-koni-ui/src/contexts/AuthenticationMythProvider.tsx @@ -8,6 +8,7 @@ import { AccountPublicInfo, MythicalWallet } from '@subwallet/extension-koni-ui/ import { TelegramConnector } from '@subwallet/extension-koni-ui/connector/telegram'; import { AUTHENTICATE_LINKING_BOT, AUTHENTICATE_LINKING_SERVICE, AUTHENTICATE_LINKING_TOKEN, AUTHENTICATE_LINKING_URL } from '@subwallet/extension-koni-ui/constants'; import { RootState } from '@subwallet/extension-koni-ui/stores'; +import { sendEventGA } from '@subwallet/extension-koni-ui/utils/googleAnalytics'; import React, { createContext, ReactElement, useCallback, useContext, useEffect, useState } from 'react'; import { AuthContext } from 'react-oauth2-code-pkce'; import { useSelector } from 'react-redux'; @@ -82,6 +83,7 @@ export const AuthenticationMythProvider = ({ children }: AuthenticationMythProvi const onLoginWithMythAccount = useCallback(() => { localStorage.setItem(LOCAL_LOGGED_IN_PROMISE_KEY, 'login'); + sendEventGA('ink-mythical-account'); authContext.logIn(); }, [authContext]); diff --git a/packages/extension-koni-ui/src/utils/googleAnalytics.ts b/packages/extension-koni-ui/src/utils/googleAnalytics.ts new file mode 100644 index 0000000000..686540d3c6 --- /dev/null +++ b/packages/extension-koni-ui/src/utils/googleAnalytics.ts @@ -0,0 +1,9 @@ +// [object Object] +// SPDX-License-Identifier: Apache-2.0 + +// eslint-disable-next-line header/header +export const sendEventGA = (category: string): void => { + // @ts-ignore + // eslint-disable-next-line @typescript-eslint/no-unsafe-call + gtag('event', category); +}; From bfa130b400672161a3ca93a23a5471e5a0ff3ff3 Mon Sep 17 00:00:00 2001 From: lw Date: Thu, 9 Jan 2025 11:18:09 +0700 Subject: [PATCH 7/8] [Issue-261] Auto open T&C popup for the first time when the user visits leaderboard screen --- .../LeaderboardTemp/TermAndConditionModal.tsx | 15 +- .../src/Popup/Home/LeaderboardTemp/index.tsx | 134 ++++++++++-------- .../src/constants/localStorage.ts | 1 + 3 files changed, 79 insertions(+), 71 deletions(-) diff --git a/packages/extension-koni-ui/src/Popup/Home/LeaderboardTemp/TermAndConditionModal.tsx b/packages/extension-koni-ui/src/Popup/Home/LeaderboardTemp/TermAndConditionModal.tsx index d0bb4594f8..712a6f87da 100644 --- a/packages/extension-koni-ui/src/Popup/Home/LeaderboardTemp/TermAndConditionModal.tsx +++ b/packages/extension-koni-ui/src/Popup/Home/LeaderboardTemp/TermAndConditionModal.tsx @@ -96,24 +96,14 @@ export const TermAndConditionModal = styled(Component)(({ theme: { extend right: 0 }, - '&.ant-sw-modal.ant-sw-modal': { - justifyContent: 'flex-start', - alignItems: 'center', - - '&:before, &:after': { - content: '""', - display: 'block', - flex: 1 - } - }, - '.ant-sw-modal-content.ant-sw-modal-content': { borderRadius: 0, maxWidth: 370, maxHeight: 484, paddingTop: 24, width: '100%', - height: 'auto', + marginTop: 'auto', + marginBottom: 'auto', backgroundImage: 'url(/images/mythical/leaderboard-terms-conditions-bg.png)', backgroundSize: '100% 100%', backgroundRepeat: 'no-repeat', @@ -173,6 +163,7 @@ export const TermAndConditionModal = styled(Component)(({ theme: { extend lineHeight: '18px', letterSpacing: '0.32px', marginBottom: 20, + flex: 1, overflow: 'auto' }, diff --git a/packages/extension-koni-ui/src/Popup/Home/LeaderboardTemp/index.tsx b/packages/extension-koni-ui/src/Popup/Home/LeaderboardTemp/index.tsx index 6b8bee71ea..5bd07d6d1b 100644 --- a/packages/extension-koni-ui/src/Popup/Home/LeaderboardTemp/index.tsx +++ b/packages/extension-koni-ui/src/Popup/Home/LeaderboardTemp/index.tsx @@ -4,7 +4,7 @@ import { CallToAction, InfoIcon, MainScreenHeader, TimeRemaining } from '@subwallet/extension-koni-ui/components/Mythical'; import { BookaSdk } from '@subwallet/extension-koni-ui/connector/booka/sdk'; import { LeaderboardGroups, LeaderboardInfo, LeaderboardPerson } from '@subwallet/extension-koni-ui/connector/booka/types'; -import { LINK_NFL_APP_DOWNLOAD } from '@subwallet/extension-koni-ui/constants'; +import { LINK_NFL_APP_DOWNLOAD, TAC_READ_FLAG } from '@subwallet/extension-koni-ui/constants'; import { HomeContext } from '@subwallet/extension-koni-ui/contexts/screen/HomeContext'; import { useServerTime, useSetCurrentPage } from '@subwallet/extension-koni-ui/hooks'; import { GameAccountListArea } from '@subwallet/extension-koni-ui/Popup/Home/LeaderboardTemp/GameAccountListArea'; @@ -17,6 +17,7 @@ import CN from 'classnames'; import React, { useCallback, useContext, useEffect, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; import styled from 'styled-components'; +import { useLocalStorage } from 'usehooks-ts'; type Props = ThemeProps; @@ -33,6 +34,62 @@ const Component = ({ className }: Props): React.ReactElement => { const [leaderboardInfo, setLeaderboardInfo] = useState(undefined); const { activeModal, inactiveModal } = useContext(ModalContext); const { serverTime } = useServerTime(); + const [isTacRead, setIsTacRead] = useLocalStorage(TAC_READ_FLAG, false); + + const openTermAndConditionModal = useCallback(() => { + activeModal(TERM_AND_CONDITION_MODAL_ID); + }, [activeModal]); + + const closeTermAndConditionModal = useCallback(() => { + inactiveModal(TERM_AND_CONDITION_MODAL_ID); + setIsTacRead(true); + }, [inactiveModal, setIsTacRead]); + + const openAppStoreLink = useCallback(() => { + openInNewTab(LINK_NFL_APP_DOWNLOAD)(); + }, []); + + const shouldShowInfoButton = useMemo(() => { + const leaderboard = leaderboardInfo?.metadata as LeaderboardMetadata | undefined; + + return !!(leaderboard && 'title' in leaderboard && 'content' in leaderboard); + }, [leaderboardInfo]); + + const timeRemainingDateTime = useMemo(() => { + if (!leaderboardInfo?.endTimeTs || !serverTime) { + return undefined; + } + + const delayStartTime = leaderboardInfo?.endTimeTs; + const delayEndTime = delayStartTime + Number(leaderboardInfo.specialTimeDelayDuration) * 86400000; + + const targetTime = serverTime > delayStartTime && serverTime < delayEndTime + ? delayEndTime + : delayStartTime; + + return getTimeRemaining(serverTime, new Date(targetTime).toString()); + }, [leaderboardInfo?.endTimeTs, leaderboardInfo?.specialTimeDelayDuration, serverTime]); + + const shouldShowToken = useMemo(() => { + if (!leaderboardInfo?.endTimeTs || !serverTime) { + return false; + } + + const delayStartTime = leaderboardInfo?.endTimeTs; + const delayEndTime = delayStartTime + Number(leaderboardInfo.specialTimeDelayDuration) * 86400000; + + return serverTime > delayStartTime && serverTime < delayEndTime; + }, [leaderboardInfo?.endTimeTs, leaderboardInfo?.specialTimeDelayDuration, serverTime]); + + const timeRemainingTitle = useMemo(() => { + if (!leaderboardInfo?.endTimeTs || !serverTime) { + return undefined; + } + + return serverTime > leaderboardInfo.endTimeTs + ? t('New leaderboard in') + : t('Time remaining'); + }, [leaderboardInfo?.endTimeTs, serverTime, t]); useEffect(() => { const subscriptionLeaderboard = apiSDK.subscribeLeaderboardConfig().subscribe((data) => { @@ -101,59 +158,19 @@ const Component = ({ className }: Props): React.ReactElement => { }; }, [setContainerClass]); - const openTermAndConditionModal = useCallback(() => { - activeModal(TERM_AND_CONDITION_MODAL_ID); - }, [activeModal]); - - const closeTermAndConditionModal = useCallback(() => { - inactiveModal(TERM_AND_CONDITION_MODAL_ID); - }, [inactiveModal]); - - const openAppStoreLink = useCallback(() => { - openInNewTab(LINK_NFL_APP_DOWNLOAD)(); - }, []); - - const shouldShowInfoButton = useMemo(() => { - const leaderboard = leaderboardInfo?.metadata as LeaderboardMetadata | undefined; - - return !!(leaderboard && 'title' in leaderboard && 'content' in leaderboard); - }, [leaderboardInfo]); - - const timeRemainingDateTime = useMemo(() => { - if (!leaderboardInfo?.endTimeTs || !serverTime) { - return undefined; - } - - const delayStartTime = leaderboardInfo?.endTimeTs; - const delayEndTime = delayStartTime + Number(leaderboardInfo.specialTimeDelayDuration) * 86400000; - - const targetTime = serverTime > delayStartTime && serverTime < delayEndTime - ? delayEndTime - : delayStartTime; - - return getTimeRemaining(serverTime, new Date(targetTime).toString()); - }, [leaderboardInfo?.endTimeTs, leaderboardInfo?.specialTimeDelayDuration, serverTime]); - - const shouldShowToken = useMemo(() => { - if (!leaderboardInfo?.endTimeTs || !serverTime) { - return false; - } + const isTacContentReady = !!leaderboardInfo?.metadata; - const delayStartTime = leaderboardInfo?.endTimeTs; - const delayEndTime = delayStartTime + Number(leaderboardInfo.specialTimeDelayDuration) * 86400000; - - return serverTime > delayStartTime && serverTime < delayEndTime; - }, [leaderboardInfo?.endTimeTs, leaderboardInfo?.specialTimeDelayDuration, serverTime]); - - const timeRemainingTitle = useMemo(() => { - if (!leaderboardInfo?.endTimeTs || !serverTime) { - return undefined; - } + useEffect(() => { + const timeout = setTimeout(() => { + if (!isTacRead && isTacContentReady) { + activeModal(TERM_AND_CONDITION_MODAL_ID); + } + }, 500); - return serverTime > leaderboardInfo.endTimeTs - ? t('New leaderboard in') - : t('Time remaining'); - }, [leaderboardInfo?.endTimeTs, serverTime, t]); + return () => { + clearTimeout(timeout); + }; + }, [activeModal, isTacContentReady, isTacRead]); return (
@@ -172,13 +189,12 @@ const Component = ({ className }: Props): React.ReactElement => { title={currentLeaderboardInfo?.name || t('Leaderboard')} /> - { -
- -
} +
+ +
Date: Thu, 9 Jan 2025 11:31:52 +0700 Subject: [PATCH 8/8] [issue-257]: edit name event connect mythical --- .../src/contexts/AuthenticationMythProvider.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/extension-koni-ui/src/contexts/AuthenticationMythProvider.tsx b/packages/extension-koni-ui/src/contexts/AuthenticationMythProvider.tsx index 7ba49c3a83..a93b577a8a 100644 --- a/packages/extension-koni-ui/src/contexts/AuthenticationMythProvider.tsx +++ b/packages/extension-koni-ui/src/contexts/AuthenticationMythProvider.tsx @@ -83,7 +83,7 @@ export const AuthenticationMythProvider = ({ children }: AuthenticationMythProvi const onLoginWithMythAccount = useCallback(() => { localStorage.setItem(LOCAL_LOGGED_IN_PROMISE_KEY, 'login'); - sendEventGA('ink-mythical-account'); + sendEventGA('link-mythical-account'); authContext.logIn(); }, [authContext]);