diff --git a/apps/desktop/layer/renderer/src/atoms/user.ts b/apps/desktop/layer/renderer/src/atoms/user.ts index ab259d966c..9010603468 100644 --- a/apps/desktop/layer/renderer/src/atoms/user.ts +++ b/apps/desktop/layer/renderer/src/atoms/user.ts @@ -1,19 +1,6 @@ -import type { UserRole } from "@follow/constants" -import type { AuthSession } from "@follow/shared/hono" import { atom } from "jotai" import { createAtomHooks } from "~/lib/jotai" -export const [, , useWhoami, , whoami, setWhoami] = createAtomHooks( - atom["user"]>>(null), -) - export const [, , useLoginModalShow, useSetLoginModalShow, getLoginModalShow, setLoginModalShow] = createAtomHooks(atom(false)) - -/** - * For public beta trial user - */ -export const [, , useUserRole, , getUserRole, setUserRole] = createAtomHooks( - atom>(null), -) diff --git a/apps/desktop/layer/renderer/src/hooks/biz/useEntryActions.tsx b/apps/desktop/layer/renderer/src/hooks/biz/useEntryActions.tsx index 14f0936eaa..efee52201f 100644 --- a/apps/desktop/layer/renderer/src/hooks/biz/useEntryActions.tsx +++ b/apps/desktop/layer/renderer/src/hooks/biz/useEntryActions.tsx @@ -8,6 +8,8 @@ import { entrySyncServices } from "@follow/store/entry/store" import type { EntryModel } from "@follow/store/entry/types" import { useFeedById } from "@follow/store/feed/hooks" import { useIsInbox } from "@follow/store/inbox/hooks" +import { whoami } from "@follow/store/user/getters" +import { useUserRole } from "@follow/store/user/hooks" import { doesTextContainHTML } from "@follow/utils/utils" import { useMemo } from "react" @@ -21,7 +23,6 @@ import { useEntryIsInReadability, } from "~/atoms/readability" import { useShowSourceContent } from "~/atoms/source-content" -import { useUserRole, whoami } from "~/atoms/user" import { ipcServices } from "~/lib/client" import { COMMAND_ID } from "~/modules/command/commands/id" import { getCommand, useRunCommandFn } from "~/modules/command/hooks/use-command" diff --git a/apps/desktop/layer/renderer/src/hooks/biz/useFeedActions.tsx b/apps/desktop/layer/renderer/src/hooks/biz/useFeedActions.tsx index 78bd8e856a..27e66b161d 100644 --- a/apps/desktop/layer/renderer/src/hooks/biz/useFeedActions.tsx +++ b/apps/desktop/layer/renderer/src/hooks/biz/useFeedActions.tsx @@ -12,6 +12,7 @@ import { useSubscriptionsByFeedIds, } from "@follow/store/subscription/hooks" import { unreadSyncService } from "@follow/store/unread/store" +import { whoami } from "@follow/store/user/getters" import { isBizId } from "@follow/utils/utils" import { useMutation } from "@tanstack/react-query" import { useMemo } from "react" @@ -21,7 +22,6 @@ import { toast } from "sonner" import type { FollowMenuItem, MenuItemInput } from "~/atoms/context-menu" import { MenuItemSeparator, MenuItemText } from "~/atoms/context-menu" import { useIsInMASReview } from "~/atoms/server-configs" -import { whoami } from "~/atoms/user" import { useModalStack } from "~/components/ui/modal/stacked/hooks" import { copyToClipboard } from "~/lib/clipboard" import { UrlBuilder } from "~/lib/url-builder" diff --git a/apps/desktop/layer/renderer/src/hooks/biz/useFollow.tsx b/apps/desktop/layer/renderer/src/hooks/biz/useFollow.tsx index 1cf1d224a9..ad4178cad6 100644 --- a/apps/desktop/layer/renderer/src/hooks/biz/useFollow.tsx +++ b/apps/desktop/layer/renderer/src/hooks/biz/useFollow.tsx @@ -5,13 +5,13 @@ import { useFeedSubscriptionCount, useListSubscriptionCount, } from "@follow/store/subscription/hooks" +import { useUserRole } from "@follow/store/user/hooks" import { t } from "i18next" import { useCallback } from "react" import { withoutTrailingSlash, withTrailingSlash } from "ufo" import { useEventCallback } from "usehooks-ts" import { useServerConfigs } from "~/atoms/server-configs" -import { useUserRole } from "~/atoms/user" import { useModalStack } from "~/components/ui/modal/stacked/hooks" import { CustomSafeError } from "~/errors/CustomSafeError" import { useActivationModal } from "~/modules/activation" diff --git a/apps/desktop/layer/renderer/src/initialize/sentry.ts b/apps/desktop/layer/renderer/src/initialize/sentry.ts index f72286d56b..ca53dd6f3c 100644 --- a/apps/desktop/layer/renderer/src/initialize/sentry.ts +++ b/apps/desktop/layer/renderer/src/initialize/sentry.ts @@ -1,13 +1,12 @@ import { ELECTRON_BUILD } from "@follow/shared/constants" import { env } from "@follow/shared/env.desktop" +import { whoami } from "@follow/store/user/getters" import { appSessionTraceId } from "@follow/utils/environment" import { version } from "@pkg" import { nanoid } from "nanoid" import { useEffect } from "react" import { createRoutesFromChildren, matchRoutes, useLocation, useNavigationType } from "react-router" -import { whoami } from "~/atoms/user" - import { SentryConfig } from "./sentry.config" Object.defineProperty(window.Error.prototype, "traceId", { diff --git a/apps/desktop/layer/renderer/src/modules/app-layout/subscription-column/MainDestopLayout.tsx b/apps/desktop/layer/renderer/src/modules/app-layout/subscription-column/MainDestopLayout.tsx index d21a7b1175..795346e0b4 100644 --- a/apps/desktop/layer/renderer/src/modules/app-layout/subscription-column/MainDestopLayout.tsx +++ b/apps/desktop/layer/renderer/src/modules/app-layout/subscription-column/MainDestopLayout.tsx @@ -1,5 +1,6 @@ import { RootPortal } from "@follow/components/ui/portal/index.jsx" import { DEV, IN_ELECTRON, PROD } from "@follow/shared/constants" +import { useWhoami } from "@follow/store/user/hooks" import { preventDefault } from "@follow/utils/dom" import type { PropsWithChildren } from "react" import * as React from "react" @@ -8,7 +9,7 @@ import { Outlet } from "react-router" import { setMainContainerElement, setRootContainerElement } from "~/atoms/dom" import { useUISettingKey } from "~/atoms/settings/ui" -import { useLoginModalShow, useWhoami } from "~/atoms/user" +import { useLoginModalShow } from "~/atoms/user" import { AppErrorBoundary } from "~/components/common/AppErrorBoundary" import { ErrorComponentType } from "~/components/errors/enum" import { PlainModal } from "~/components/ui/modal/stacked/custom-modal" diff --git a/apps/desktop/layer/renderer/src/modules/app-layout/subscription-column/components/NewUserGuide.tsx b/apps/desktop/layer/renderer/src/modules/app-layout/subscription-column/components/NewUserGuide.tsx index c50b3b39fb..8414f96ce8 100644 --- a/apps/desktop/layer/renderer/src/modules/app-layout/subscription-column/components/NewUserGuide.tsx +++ b/apps/desktop/layer/renderer/src/modules/app-layout/subscription-column/components/NewUserGuide.tsx @@ -1,6 +1,6 @@ +import { useWhoami } from "@follow/store/user/hooks" import { lazy, Suspense } from "react" -import { useWhoami } from "~/atoms/user" import { useAuthQuery } from "~/hooks/common/useBizQuery" import { settings } from "~/queries/settings" diff --git a/apps/desktop/layer/renderer/src/modules/app/EnvironmentIndicator.tsx b/apps/desktop/layer/renderer/src/modules/app/EnvironmentIndicator.tsx index f0596b6361..e35c8791d2 100644 --- a/apps/desktop/layer/renderer/src/modules/app/EnvironmentIndicator.tsx +++ b/apps/desktop/layer/renderer/src/modules/app/EnvironmentIndicator.tsx @@ -7,8 +7,8 @@ import { } from "@follow/components/ui/tooltip/index.jsx" import { DEV, MODE } from "@follow/shared/constants" import { env } from "@follow/shared/env.desktop" +import { useUserRole } from "@follow/store/user/hooks" -import { useUserRole } from "~/atoms/user" import { useModalStack } from "~/components/ui/modal/stacked/hooks" import { DebugRegistry } from "../debug/registry" diff --git a/apps/desktop/layer/renderer/src/modules/command/commands/entry.tsx b/apps/desktop/layer/renderer/src/modules/command/commands/entry.tsx index 9c66357d07..b1352cc4f9 100644 --- a/apps/desktop/layer/renderer/src/modules/command/commands/entry.tsx +++ b/apps/desktop/layer/renderer/src/modules/command/commands/entry.tsx @@ -6,6 +6,7 @@ import { collectionSyncService } from "@follow/store/collection/store" import { getEntry } from "@follow/store/entry/getter" import { entrySyncServices } from "@follow/store/entry/store" import { unreadSyncService } from "@follow/store/unread/store" +import { useUserRole } from "@follow/store/user/hooks" import { cn, resolveUrlWithBase } from "@follow/utils/utils" import { useMutation } from "@tanstack/react-query" import { useTranslation } from "react-i18next" @@ -22,7 +23,6 @@ import { toggleShowSourceContent, useSourceContentModal, } from "~/atoms/source-content" -import { useUserRole } from "~/atoms/user" import { SharePanel } from "~/components/common/SharePanel" import { toggleEntryReadability } from "~/hooks/biz/useEntryActions" import { navigateEntry } from "~/hooks/biz/useNavigateEntry" diff --git a/apps/desktop/layer/renderer/src/modules/discover/DiscoverInboxList.tsx b/apps/desktop/layer/renderer/src/modules/discover/DiscoverInboxList.tsx index 6e2bcf6d71..109da6fcec 100644 --- a/apps/desktop/layer/renderer/src/modules/discover/DiscoverInboxList.tsx +++ b/apps/desktop/layer/renderer/src/modules/discover/DiscoverInboxList.tsx @@ -1,10 +1,10 @@ import { Button } from "@follow/components/ui/button/index.js" import { UserRole } from "@follow/constants" +import { useUserRole } from "@follow/store/user/hooks" import { repository } from "@pkg" import { useTranslation } from "react-i18next" import { useEventCallback } from "usehooks-ts" -import { useUserRole } from "~/atoms/user" import { useModalStack } from "~/components/ui/modal/stacked/hooks" import { CustomSafeError } from "~/errors/CustomSafeError" diff --git a/apps/desktop/layer/renderer/src/modules/entry-column/layouts/EntryListHeader.tsx b/apps/desktop/layer/renderer/src/modules/entry-column/layouts/EntryListHeader.tsx index 5a5c1d4530..5639f7f3c0 100644 --- a/apps/desktop/layer/renderer/src/modules/entry-column/layouts/EntryListHeader.tsx +++ b/apps/desktop/layer/renderer/src/modules/entry-column/layouts/EntryListHeader.tsx @@ -6,6 +6,7 @@ import { FeedViewType, views } from "@follow/constants" import { useIsOnline } from "@follow/hooks" import { getFeedById } from "@follow/store/feed/getter" import { useFeedById } from "@follow/store/feed/hooks" +import { useWhoami } from "@follow/store/user/hooks" import { stopPropagation } from "@follow/utils/dom" import { cn, isBizId } from "@follow/utils/utils" import type { FC } from "react" @@ -15,7 +16,6 @@ import { useNavigate } from "react-router" import { previewBackPath } from "~/atoms/preview" import { useGeneralSettingKey } from "~/atoms/settings/general" import { useTimelineColumnShow } from "~/atoms/sidebar" -import { useWhoami } from "~/atoms/user" import { FEED_COLLECTION_LIST, ROUTE_ENTRY_PENDING } from "~/constants" import { useFollow } from "~/hooks/biz/useFollow" import { getRouteParams, useRouteParams } from "~/hooks/biz/useRouteParams" diff --git a/apps/desktop/layer/renderer/src/modules/entry-content/components/EntryTitle.tsx b/apps/desktop/layer/renderer/src/modules/entry-content/components/EntryTitle.tsx index 43b1ef9bec..872f43dde8 100644 --- a/apps/desktop/layer/renderer/src/modules/entry-content/components/EntryTitle.tsx +++ b/apps/desktop/layer/renderer/src/modules/entry-content/components/EntryTitle.tsx @@ -2,12 +2,12 @@ import { useEntry, useEntryReadHistory } from "@follow/store/entry/hooks" import { useFeedById } from "@follow/store/feed/hooks" import { useInboxById } from "@follow/store/inbox/hooks" import { useEntryTranslation } from "@follow/store/translation/hooks" +import { useWhoami } from "@follow/store/user/hooks" import { formatEstimatedMins, formatTimeToSeconds } from "@follow/utils" import { titleCase } from "title-case" import { useActionLanguage } from "~/atoms/settings/general" import { useUISettingKey } from "~/atoms/settings/ui" -import { useWhoami } from "~/atoms/user" import { RelativeTime } from "~/components/ui/datetime" import { useNavigateEntry } from "~/hooks/biz/useNavigateEntry" import { useFeedSafeUrl } from "~/hooks/common/useFeedSafeUrl" diff --git a/apps/desktop/layer/renderer/src/modules/entry-content/components/SupportCreator.tsx b/apps/desktop/layer/renderer/src/modules/entry-content/components/SupportCreator.tsx index 9c93bdf3d8..bc42517064 100644 --- a/apps/desktop/layer/renderer/src/modules/entry-content/components/SupportCreator.tsx +++ b/apps/desktop/layer/renderer/src/modules/entry-content/components/SupportCreator.tsx @@ -3,11 +3,11 @@ import { Divider } from "@follow/components/ui/divider/index.js" import { useEntry } from "@follow/store/entry/hooks" import { useFeedById } from "@follow/store/feed/hooks" import { getUserList } from "@follow/store/user/getters" +import { useWhoami } from "@follow/store/user/hooks" import { useMemo } from "react" import { useTranslation } from "react-i18next" import { useIsInMASReview } from "~/atoms/server-configs" -import { useWhoami } from "~/atoms/user" import { useBoostModal } from "~/modules/boost/hooks" import { useFeedBoostersQuery } from "~/modules/boost/query" import { FeedIcon } from "~/modules/feed/feed-icon" diff --git a/apps/desktop/layer/renderer/src/modules/entry-content/components/entry-read-history/EntryReadHistory.tsx b/apps/desktop/layer/renderer/src/modules/entry-content/components/entry-read-history/EntryReadHistory.tsx index 403ee0adde..d75a604301 100644 --- a/apps/desktop/layer/renderer/src/modules/entry-content/components/entry-read-history/EntryReadHistory.tsx +++ b/apps/desktop/layer/renderer/src/modules/entry-content/components/entry-read-history/EntryReadHistory.tsx @@ -1,8 +1,8 @@ import { AvatarGroup } from "@follow/components/ui/avatar-group/index.js" import { FeedViewType } from "@follow/constants" import { useEntryReadHistory } from "@follow/store/entry/hooks" +import { useWhoami } from "@follow/store/user/hooks" -import { useWhoami } from "~/atoms/user" import { getRouteParams } from "~/hooks/biz/useRouteParams" import { useAppLayoutGridContainerWidth } from "~/providers/app-grid-layout-container-provider" diff --git a/apps/desktop/layer/renderer/src/modules/feed/feed-certification.tsx b/apps/desktop/layer/renderer/src/modules/feed/feed-certification.tsx index 1deaa83a5e..4b53ddae50 100644 --- a/apps/desktop/layer/renderer/src/modules/feed/feed-certification.tsx +++ b/apps/desktop/layer/renderer/src/modules/feed/feed-certification.tsx @@ -6,10 +6,10 @@ import { TooltipTrigger, } from "@follow/components/ui/tooltip/index.jsx" import type { FeedOrListRespModel } from "@follow/models/types" +import { useWhoami } from "@follow/store/user/hooks" import { cn } from "@follow/utils/utils" import { useTranslation } from "react-i18next" -import { useWhoami } from "~/atoms/user" import { replaceImgUrlIfNeed } from "~/lib/img-proxy" import { usePresentUserProfileModal } from "~/modules/profile/hooks" diff --git a/apps/desktop/layer/renderer/src/modules/power/transaction-section/TransactionsSection.tsx b/apps/desktop/layer/renderer/src/modules/power/transaction-section/TransactionsSection.tsx index 9bc417e8cc..64b2915ff0 100644 --- a/apps/desktop/layer/renderer/src/modules/power/transaction-section/TransactionsSection.tsx +++ b/apps/desktop/layer/renderer/src/modules/power/transaction-section/TransactionsSection.tsx @@ -1,10 +1,10 @@ import { LoadingCircle } from "@follow/components/ui/loading/index.js" import { Tabs, TabsList, TabsTrigger } from "@follow/components/ui/tabs/index.jsx" import { TransactionTypes } from "@follow/models/types" +import { useWhoami } from "@follow/store/user/hooks" import { useState } from "react" import { useTranslation } from "react-i18next" -import { useWhoami } from "~/atoms/user" import { getBlockchainExplorerUrl } from "~/lib/utils" import { SettingSectionTitle } from "~/modules/settings/section" import { useWallet, useWalletTransactions } from "~/queries/wallet" diff --git a/apps/desktop/layer/renderer/src/modules/power/transaction-section/tx-table/TxTable.tsx b/apps/desktop/layer/renderer/src/modules/power/transaction-section/tx-table/TxTable.tsx index aa7884ae16..a142d8458f 100644 --- a/apps/desktop/layer/renderer/src/modules/power/transaction-section/tx-table/TxTable.tsx +++ b/apps/desktop/layer/renderer/src/modules/power/transaction-section/tx-table/TxTable.tsx @@ -14,10 +14,10 @@ import { } from "@follow/components/ui/tooltip/index.jsx" import { EllipsisHorizontalTextWithTooltip } from "@follow/components/ui/typography/index.js" import type { TransactionTypes } from "@follow/models" +import { useWhoami } from "@follow/store/user/hooks" import { cn } from "@follow/utils/utils" import { useTranslation } from "react-i18next" -import { useWhoami } from "~/atoms/user" import { RelativeTime } from "~/components/ui/datetime" import { getBlockchainExplorerUrl } from "~/lib/utils" import { useWalletTransactions } from "~/queries/wallet" diff --git a/apps/desktop/layer/renderer/src/modules/power/transaction-section/tx-table/components.tsx b/apps/desktop/layer/renderer/src/modules/power/transaction-section/tx-table/components.tsx index 142b65d530..7fa96b15df 100644 --- a/apps/desktop/layer/renderer/src/modules/power/transaction-section/tx-table/components.tsx +++ b/apps/desktop/layer/renderer/src/modules/power/transaction-section/tx-table/components.tsx @@ -1,10 +1,10 @@ import { Logo } from "@follow/components/icons/logo.jsx" import { MotionButtonBase } from "@follow/components/ui/button/index.js" import { EllipsisHorizontalTextWithTooltip } from "@follow/components/ui/typography/index.js" +import { useWhoami } from "@follow/store/user/hooks" import { cn } from "@follow/utils/utils" import { useTranslation } from "react-i18next" -import { useWhoami } from "~/atoms/user" import { usePresentUserProfileModal } from "~/modules/profile/hooks" import { UserAvatar } from "~/modules/user/UserAvatar" import { Balance } from "~/modules/wallet/balance" diff --git a/apps/desktop/layer/renderer/src/modules/profile/email-management.tsx b/apps/desktop/layer/renderer/src/modules/profile/email-management.tsx index 97328803c8..e19a008df0 100644 --- a/apps/desktop/layer/renderer/src/modules/profile/email-management.tsx +++ b/apps/desktop/layer/renderer/src/modules/profile/email-management.tsx @@ -9,6 +9,8 @@ import { } from "@follow/components/ui/form/index.js" import { Input } from "@follow/components/ui/input/Input.js" import { Label } from "@follow/components/ui/label/index.js" +import { useWhoami } from "@follow/store/user/hooks" +import { userActions } from "@follow/store/user/store" import { cn } from "@follow/utils/utils" import { zodResolver } from "@hookform/resolvers/zod" import { useMutation } from "@tanstack/react-query" @@ -18,7 +20,6 @@ import { useTranslation } from "react-i18next" import { toast } from "sonner" import { z } from "zod" -import { setWhoami, useWhoami } from "~/atoms/user" import { AnimatedCommandButton } from "~/components/ui/button/AnimatedCommandButton" import { CopyButton } from "~/components/ui/button/CopyButton" import { useModalStack } from "~/components/ui/modal/stacked/hooks" @@ -125,8 +126,7 @@ function EmailManagementForm() { toast.success(t("profile.email.changed_verification_sent")) } else { if (user) { - setWhoami({ - ...user, + userActions.updateWhoami({ email: variables.email, }) } diff --git a/apps/desktop/layer/renderer/src/modules/profile/hooks.ts b/apps/desktop/layer/renderer/src/modules/profile/hooks.ts index db7115833a..2fb8729ac9 100644 --- a/apps/desktop/layer/renderer/src/modules/profile/hooks.ts +++ b/apps/desktop/layer/renderer/src/modules/profile/hooks.ts @@ -1,12 +1,11 @@ import { isMobile } from "@follow/components/hooks/useMobile.js" -import { usePrefetchUser } from "@follow/store/user/hooks" +import { usePrefetchUser, useWhoami } from "@follow/store/user/hooks" import { capitalizeFirstLetter } from "@follow/utils/utils" import { createElement, lazy, useCallback } from "react" import { useTranslation } from "react-i18next" import { toast } from "sonner" import { parse } from "tldts" -import { useWhoami } from "~/atoms/user" import { useAsyncModal } from "~/components/ui/modal/helper/useAsyncModal" import { PlainModal } from "~/components/ui/modal/stacked/custom-modal" import { useModalStack } from "~/components/ui/modal/stacked/hooks" diff --git a/apps/desktop/layer/renderer/src/modules/profile/profile-setting-form.tsx b/apps/desktop/layer/renderer/src/modules/profile/profile-setting-form.tsx index d9f5fbfed2..6c2a8c52e2 100644 --- a/apps/desktop/layer/renderer/src/modules/profile/profile-setting-form.tsx +++ b/apps/desktop/layer/renderer/src/modules/profile/profile-setting-form.tsx @@ -10,6 +10,8 @@ import { FormMessage, } from "@follow/components/ui/form/index.jsx" import { Input, TextArea } from "@follow/components/ui/input/index.js" +import { useWhoami } from "@follow/store/user/hooks" +import { userActions } from "@follow/store/user/store" import { cn } from "@follow/utils/utils" import { zodResolver } from "@hookform/resolvers/zod" import { useMutation } from "@tanstack/react-query" @@ -18,7 +20,6 @@ import { useTranslation } from "react-i18next" import { toast } from "sonner" import { z } from "zod" -import { setWhoami, useWhoami } from "~/atoms/user" import { AvatarUploadModal } from "~/components/ui/crop/AvatarUploadModal" import { useModalStack } from "~/components/ui/modal/stacked/hooks" import { updateUser } from "~/lib/auth" @@ -113,7 +114,7 @@ export const ProfileSettingForm = ({ }, onSuccess: (_, variables) => { if (user && variables) { - setWhoami({ ...user, ...variables }) + userActions.updateWhoami({ ...variables }) } toast(t("profile.updateSuccess"), { duration: 3000, diff --git a/apps/desktop/layer/renderer/src/modules/profile/two-factor.tsx b/apps/desktop/layer/renderer/src/modules/profile/two-factor.tsx index 55c0e309f8..6144ff7fc5 100644 --- a/apps/desktop/layer/renderer/src/modules/profile/two-factor.tsx +++ b/apps/desktop/layer/renderer/src/modules/profile/two-factor.tsx @@ -9,6 +9,8 @@ import { } from "@follow/components/ui/form/index.jsx" import { Input, InputOTP, InputOTPGroup, InputOTPSlot } from "@follow/components/ui/input/index.js" import { Label } from "@follow/components/ui/label/index.js" +import { useWhoami } from "@follow/store/user/hooks" +import { userActions } from "@follow/store/user/store" import { zodResolver } from "@hookform/resolvers/zod" import { useMutation } from "@tanstack/react-query" import { m, useAnimation } from "motion/react" @@ -19,7 +21,6 @@ import QRCode from "react-qr-code" import { toast } from "sonner" import { z } from "zod" -import { setWhoami, useWhoami } from "~/atoms/user" import { useCurrentModal, useModalStack } from "~/components/ui/modal/stacked/hooks" import { twoFactor } from "~/lib/auth" import { getFetchErrorInfo } from "~/lib/error-parser" @@ -221,10 +222,7 @@ export const TwoFactorForm = () => { } toast.success(t("profile.two_factor.enabled")) modal.dismiss() - setWhoami((prev) => { - if (!prev) return prev - return { ...prev, twoFactorEnabled: true } - }) + userActions.updateWhoami({ twoFactorEnabled: true }) }} /> @@ -242,10 +240,7 @@ export const TwoFactorForm = () => { } else { toast.success(t("profile.two_factor.disabled")) modal.dismiss() - setWhoami((prev) => { - if (!prev) return prev - return { ...prev, twoFactorEnabled: false } - }) + userActions.updateWhoami({ twoFactorEnabled: false }) } }} /> diff --git a/apps/desktop/layer/renderer/src/modules/profile/user-profile-modal/UserProfileModalContent.tsx b/apps/desktop/layer/renderer/src/modules/profile/user-profile-modal/UserProfileModalContent.tsx index 2b61f79cc3..3733cc4240 100644 --- a/apps/desktop/layer/renderer/src/modules/profile/user-profile-modal/UserProfileModalContent.tsx +++ b/apps/desktop/layer/renderer/src/modules/profile/user-profile-modal/UserProfileModalContent.tsx @@ -6,7 +6,7 @@ import { LoadingCircle } from "@follow/components/ui/loading/index.jsx" import { ScrollArea } from "@follow/components/ui/scroll-area/index.js" import { Tooltip, TooltipContent, TooltipTrigger } from "@follow/components/ui/tooltip/index.js" import type { ExtractBizResponse } from "@follow/models" -import { usePrefetchUser, useUserById } from "@follow/store/user/hooks" +import { usePrefetchUser, useUserById, useWhoami } from "@follow/store/user/hooks" import { nextFrame, stopPropagation } from "@follow/utils/dom" import { getStorageNS } from "@follow/utils/ns" import { cn } from "@follow/utils/utils" @@ -18,7 +18,6 @@ import type { FC } from "react" import { Fragment, memo, useEffect, useMemo } from "react" import { useTranslation } from "react-i18next" -import { useWhoami } from "~/atoms/user" import { m } from "~/components/common/Motion" import { useCurrentModal } from "~/components/ui/modal/stacked/hooks" import { useFollow } from "~/hooks/biz/useFollow" diff --git a/apps/desktop/layer/renderer/src/modules/rsshub/add-modal-content.tsx b/apps/desktop/layer/renderer/src/modules/rsshub/add-modal-content.tsx index 1a6f92279f..9e72a2fde8 100644 --- a/apps/desktop/layer/renderer/src/modules/rsshub/add-modal-content.tsx +++ b/apps/desktop/layer/renderer/src/modules/rsshub/add-modal-content.tsx @@ -10,13 +10,13 @@ import { import { Input } from "@follow/components/ui/input/Input.js" import { LoadingCircle } from "@follow/components/ui/loading/index.jsx" import type { RSSHubModel } from "@follow/models" +import { whoami } from "@follow/store/user/getters" import { zodResolver } from "@hookform/resolvers/zod" import { useEffect } from "react" import { useForm } from "react-hook-form" import { useTranslation } from "react-i18next" import { z } from "zod" -import { whoami } from "~/atoms/user" import { ShikiHighLighter } from "~/components/ui/code-highlighter" import { useShikiDefaultTheme } from "~/components/ui/code-highlighter/shiki/hooks" import { useAuthQuery } from "~/hooks/common" diff --git a/apps/desktop/layer/renderer/src/modules/rsshub/set-modal-content.tsx b/apps/desktop/layer/renderer/src/modules/rsshub/set-modal-content.tsx index f8d126d0d7..050dff13c1 100644 --- a/apps/desktop/layer/renderer/src/modules/rsshub/set-modal-content.tsx +++ b/apps/desktop/layer/renderer/src/modules/rsshub/set-modal-content.tsx @@ -10,13 +10,13 @@ import { } from "@follow/components/ui/form/index.jsx" import { Input } from "@follow/components/ui/input/Input.js" import type { RSSHubModel } from "@follow/models" +import { whoami } from "@follow/store/user/getters" import { zodResolver } from "@hookform/resolvers/zod" import { useEffect } from "react" import { useForm } from "react-hook-form" import { Trans, useTranslation } from "react-i18next" import { z } from "zod" -import { whoami } from "~/atoms/user" import { useAuthQuery } from "~/hooks/common" import { UserAvatar } from "~/modules/user/UserAvatar" import { Queries } from "~/queries" diff --git a/apps/desktop/layer/renderer/src/modules/settings/hooks/use-setting-ctx.ts b/apps/desktop/layer/renderer/src/modules/settings/hooks/use-setting-ctx.ts index 4ada612cb5..11f12d31ed 100644 --- a/apps/desktop/layer/renderer/src/modules/settings/hooks/use-setting-ctx.ts +++ b/apps/desktop/layer/renderer/src/modules/settings/hooks/use-setting-ctx.ts @@ -1,7 +1,7 @@ +import { useUserRole } from "@follow/store/user/hooks" import { useMemo } from "react" import { useIsInMASReview, useServerConfigs } from "~/atoms/server-configs" -import { useUserRole } from "~/atoms/user" import { getMemoizedSettings } from "../settings-glob" import type { SettingPageContext } from "../utils" diff --git a/apps/desktop/layer/renderer/src/modules/subscription-column/subscription-list/ListHeader.tsx b/apps/desktop/layer/renderer/src/modules/subscription-column/subscription-list/ListHeader.tsx index 88678c498c..439ad3e38d 100644 --- a/apps/desktop/layer/renderer/src/modules/subscription-column/subscription-list/ListHeader.tsx +++ b/apps/desktop/layer/renderer/src/modules/subscription-column/subscription-list/ListHeader.tsx @@ -6,7 +6,6 @@ import { } from "@follow/store/subscription/hooks" import { subscriptionActions } from "@follow/store/subscription/store" import { usePrefetchUnread, useUnreadByView } from "@follow/store/unread/hooks" -import { usePrefetchSessionUser } from "@follow/store/user/hooks" import { stopPropagation } from "@follow/utils" import { useTranslation } from "react-i18next" @@ -17,7 +16,6 @@ import { SortButton } from "./SortButton" export const ListHeader = ({ view }: { view: FeedViewType }) => { usePrefetchSubscription() - usePrefetchSessionUser() usePrefetchUnread() const { t } = useTranslation() diff --git a/apps/desktop/layer/renderer/src/modules/user/ProfileButton.tsx b/apps/desktop/layer/renderer/src/modules/user/ProfileButton.tsx index 9669008c4d..8c07fd2ab6 100644 --- a/apps/desktop/layer/renderer/src/modules/user/ProfileButton.tsx +++ b/apps/desktop/layer/renderer/src/modules/user/ProfileButton.tsx @@ -4,6 +4,7 @@ import { RootPortal } from "@follow/components/ui/portal/index.js" import { EllipsisHorizontalTextWithTooltip } from "@follow/components/ui/typography/EllipsisWithTooltip.js" import { UserRole } from "@follow/constants" import { useMeasure } from "@follow/hooks" +import { useUserRole } from "@follow/store/user/hooks" import { cn } from "@follow/utils/utils" import { repository } from "@pkg" import type { FC } from "react" @@ -14,7 +15,6 @@ import { useNavigate } from "react-router" import rsshubLogoUrl from "~/assets/rsshub-icon.png?url" import { useIsInMASReview } from "~/atoms/server-configs" import { useIsZenMode, useSetZenMode } from "~/atoms/settings/ui" -import { useUserRole } from "~/atoms/user" import { DropdownMenu, DropdownMenuContent, @@ -62,7 +62,7 @@ export const ProfileButton: FC = memo((props) => { const shortcuts = useCommandShortcuts() - if (status !== "authenticated") { + if (status === "unauthenticated") { return } diff --git a/apps/desktop/layer/renderer/src/modules/user/UserAvatar.tsx b/apps/desktop/layer/renderer/src/modules/user/UserAvatar.tsx index 7525a5723e..aea3cad7e6 100644 --- a/apps/desktop/layer/renderer/src/modules/user/UserAvatar.tsx +++ b/apps/desktop/layer/renderer/src/modules/user/UserAvatar.tsx @@ -1,9 +1,8 @@ import { Avatar, AvatarFallback, AvatarImage } from "@follow/components/ui/avatar/index.jsx" -import { usePrefetchUser } from "@follow/store/user/hooks" +import { usePrefetchUser, useWhoami } from "@follow/store/user/hooks" import { getColorScheme, stringToHue } from "@follow/utils/color" import { cn } from "@follow/utils/utils" -import { useWhoami } from "~/atoms/user" import { replaceImgUrlIfNeed } from "~/lib/img-proxy" import { usePresentUserProfileModal } from "~/modules/profile/hooks" import { useSession } from "~/queries/auth" diff --git a/apps/desktop/layer/renderer/src/pages/(main)/(layer)/(subview)/discover/index.tsx b/apps/desktop/layer/renderer/src/pages/(main)/(layer)/(subview)/discover/index.tsx index c03890f740..2f5c0e03f4 100644 --- a/apps/desktop/layer/renderer/src/pages/(main)/(layer)/(subview)/discover/index.tsx +++ b/apps/desktop/layer/renderer/src/pages/(main)/(layer)/(subview)/discover/index.tsx @@ -3,12 +3,12 @@ import { useScrollElementUpdate } from "@follow/components/ui/scroll-area/hooks. import { ScrollArea } from "@follow/components/ui/scroll-area/index.js" import { Tabs, TabsContent, TabsList, TabsTrigger } from "@follow/components/ui/tabs/index.jsx" import { UserRole } from "@follow/constants" +import { useUserRole } from "@follow/store/user/hooks" import { cn } from "@follow/utils/utils" import { createElement } from "react" import { useTranslation } from "react-i18next" import { useSearchParams } from "react-router" -import { useUserRole } from "~/atoms/user" import { AppErrorBoundary } from "~/components/common/AppErrorBoundary" import { ErrorComponentType } from "~/components/errors/enum" import { useActivationModal } from "~/modules/activation" diff --git a/apps/desktop/layer/renderer/src/pages/(main)/(layer)/(subview)/rsshub/index.tsx b/apps/desktop/layer/renderer/src/pages/(main)/(layer)/(subview)/rsshub/index.tsx index c27740bf82..13c7c41dd4 100644 --- a/apps/desktop/layer/renderer/src/pages/(main)/(layer)/(subview)/rsshub/index.tsx +++ b/apps/desktop/layer/renderer/src/pages/(main)/(layer)/(subview)/rsshub/index.tsx @@ -1,12 +1,12 @@ import { Logo } from "@follow/components/icons/logo.jsx" import { Button } from "@follow/components/ui/button/index.js" import type { RSSHubModel } from "@follow/models" +import { whoami } from "@follow/store/user/getters" import { cn, formatNumber } from "@follow/utils/utils" import { memo, useCallback, useEffect } from "react" import { useTranslation } from "react-i18next" import RSSHubIconUrl from "~/assets/rsshub-icon.png?url" -import { whoami } from "~/atoms/user" import { ErrorTooltip } from "~/components/common/ErrorTooltip" import { HeaderActionButton, HeaderActionGroup } from "~/components/ui/button/HeaderActionButton" import { useModalStack } from "~/components/ui/modal/stacked/hooks" diff --git a/apps/desktop/layer/renderer/src/providers/user-provider.tsx b/apps/desktop/layer/renderer/src/providers/user-provider.tsx index 4908db84e4..f847b9cbad 100644 --- a/apps/desktop/layer/renderer/src/providers/user-provider.tsx +++ b/apps/desktop/layer/renderer/src/providers/user-provider.tsx @@ -1,7 +1,5 @@ -import type { UserRole } from "@follow/constants" import { useEffect } from "react" -import { setUserRole, setWhoami } from "~/atoms/user" import { setIntegrationIdentify } from "~/initialize/helper" import { useSession } from "~/queries/auth" @@ -10,10 +8,6 @@ export const UserProvider = () => { useEffect(() => { if (!session?.user) return - setWhoami(session.user) - if (session.role) { - setUserRole(session.role as UserRole) - } // @ts-expect-error FIXME setIntegrationIdentify(session.user) }, [session?.role, session?.user]) diff --git a/apps/desktop/layer/renderer/src/queries/auth.ts b/apps/desktop/layer/renderer/src/queries/auth.ts index 84f262307c..90400110b4 100644 --- a/apps/desktop/layer/renderer/src/queries/auth.ts +++ b/apps/desktop/layer/renderer/src/queries/auth.ts @@ -1,18 +1,19 @@ import type { AuthSession } from "@follow/shared/hono" +import { whoamiQueryKey } from "@follow/store/user/hooks" +import { userActions, userSyncService } from "@follow/store/user/store" import { tracker } from "@follow/tracker" import { clearStorage } from "@follow/utils/ns" import type { FetchError } from "ofetch" -import { setWhoami } from "~/atoms/user" import { QUERY_PERSIST_KEY } from "~/constants" import { useAuthQuery } from "~/hooks/common" -import { getAccountInfo, getSession, signOut as signOutFn } from "~/lib/auth" +import { getAccountInfo, signOut as signOutFn } from "~/lib/auth" import { ipcServices } from "~/lib/client" import { defineQuery } from "~/lib/defineQuery" import { clearLocalPersistStoreData } from "~/store/utils/clear" export const auth = { - getSession: () => defineQuery(["auth", "session"], () => getSession()), + getSession: () => defineQuery(whoamiQueryKey, () => userSyncService.whoami()), getAccounts: () => defineQuery(["auth", "accounts"], () => getAccountInfo()), } @@ -58,18 +59,18 @@ export const useSession = (options?: { enabled?: boolean }) => { const fetchError = error as FetchError return { - session: data?.data as AuthSession, + session: data as AuthSession, ...rest, status: isLoading ? "loading" - : data?.data + : data ? "authenticated" : fetchError ? "error" - : data?.data === null + : data === null ? "unauthenticated" : "unknown", - } + } as const } export const handleSessionChanges = () => { @@ -81,7 +82,7 @@ export const signOut = async () => { // Clear query cache localStorage.removeItem(QUERY_PERSIST_KEY) - setWhoami(null) + userActions.removeCurrentUser() // clear local store data await clearLocalPersistStoreData() diff --git a/apps/mobile/src/modules/settings/SettingsList.tsx b/apps/mobile/src/modules/settings/SettingsList.tsx index d5d6a51d22..2dbfcc8648 100644 --- a/apps/mobile/src/modules/settings/SettingsList.tsx +++ b/apps/mobile/src/modules/settings/SettingsList.tsx @@ -1,6 +1,6 @@ import { UserRole } from "@follow/constants" import type { ServerConfigs } from "@follow/models/types" -import { useRole, useWhoami } from "@follow/store/user/hooks" +import { useUserRole, useWhoami } from "@follow/store/user/hooks" import * as FileSystem from "expo-file-system" import type { ParseKeys } from "i18next" import type { FC } from "react" @@ -198,7 +198,7 @@ const NavigationLinkGroup: FC<{ links: GroupNavigationLink[] }> = ({ links }) => { const navigation = useNavigation() - const role = useRole() + const role = useUserRole() const { t } = useTranslation("settings") return ( diff --git a/packages/internal/store/src/user/hooks.ts b/packages/internal/store/src/user/hooks.ts index 9451eba677..4b77ebb457 100644 --- a/packages/internal/store/src/user/hooks.ts +++ b/packages/internal/store/src/user/hooks.ts @@ -17,7 +17,7 @@ export const usePrefetchSessionUser = () => { useEffect(() => { if (query.data) { - const user = query.data + const { user } = query.data tracker.identify(user) } }, [query.data]) @@ -38,7 +38,7 @@ export const useWhoami = () => { return useUserStore((state) => state.whoami) } -export const useRole = () => { +export const useUserRole = () => { return useUserStore((state) => state.role) } diff --git a/packages/internal/store/src/user/store.ts b/packages/internal/store/src/user/store.ts index 3b30cf935c..51f269d282 100644 --- a/packages/internal/store/src/user/store.ts +++ b/packages/internal/store/src/user/store.ts @@ -72,7 +72,7 @@ class UserSyncService { }) userActions.upsertMany([user]) - return res.user + return res } else { return null } @@ -213,6 +213,13 @@ class UserActions implements Hydratable { }) } + updateWhoami(data: Partial) { + immerSet((state) => { + if (!state.whoami) return + state.whoami = { ...state.whoami, ...data } + }) + } + async upsertMany(users: UserModel[]) { const tx = createTransaction() tx.store(() => this.upsertManyInSession(users))