Skip to content

Commit b031ce5

Browse files
committed
feat: dynamic auth providers
1 parent 9819591 commit b031ce5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+110
-136
lines changed

apps/renderer/src/modules/auth/LoginModalContent.tsx

Lines changed: 27 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { FollowIcon } from "@follow/components/icons/follow.jsx"
22
import { MotionButtonBase } from "@follow/components/ui/button/index.js"
33
import { LoadingCircle } from "@follow/components/ui/loading/index.jsx"
4+
import { authProvidersConfig } from "@follow/constants"
45
import { stopPropagation } from "@follow/utils/dom"
56
import clsx from "clsx"
67
import { AnimatePresence, m } from "framer-motion"
@@ -11,6 +12,7 @@ import { modalMontionConfig } from "~/components/ui/modal/stacked/constants"
1112
import { useCurrentModal } from "~/components/ui/modal/stacked/hooks"
1213
import type { LoginRuntime } from "~/lib/auth"
1314
import { loginHandler } from "~/lib/auth"
15+
import { useAuthProviders } from "~/queries/users"
1416

1517
interface LoginModalContentProps {
1618
runtime?: LoginRuntime
@@ -22,6 +24,7 @@ export const LoginModalContent = (props: LoginModalContentProps) => {
2224
const { canClose = true, runtime } = props
2325

2426
const { t } = useTranslation()
27+
const { data: authProviders } = useAuthProviders()
2528

2629
const [loadingLockSet, _setLoadingLockSet] = useState<string>("")
2730

@@ -60,46 +63,30 @@ export const LoginModalContent = (props: LoginModalContentProps) => {
6063
</span>
6164
</div>
6265
<div className="flex flex-col gap-4">
63-
<MotionButtonBase
64-
className={clsx(
65-
"center h-[48px] w-[320px] rounded-[8px] !bg-black font-sans text-base font-medium text-white hover:!bg-black/80 focus:!border-black/80 focus:!ring-black/80",
66-
disabled && "pointer-events-none opacity-50",
67-
"overflow-hidden",
68-
)}
69-
disabled={disabled}
70-
onClick={() => {
71-
loginHandler("github", runtime)
72-
setLoadingLockSet("github")
73-
window.analytics?.capture("login", {
74-
type: "github",
75-
})
76-
}}
77-
>
78-
<LoginButtonContent isLoading={loadingLockSet === "github"}>
79-
<i className="i-mgc-github-cute-fi mr-2 text-xl" />
80-
{t("signin.continue_with_github")}
81-
</LoginButtonContent>
82-
</MotionButtonBase>
83-
<MotionButtonBase
84-
disabled={disabled}
85-
className={clsx(
86-
"center h-[48px] w-[320px] rounded-[8px] bg-blue-500 font-sans text-base font-medium text-white hover:bg-blue-500/90 focus:!border-blue-500/80 focus:!ring-blue-500/80",
87-
disabled && "pointer-events-none opacity-50",
88-
"overflow-hidden",
89-
)}
90-
onClick={() => {
91-
loginHandler("google", runtime)
92-
setLoadingLockSet("google")
93-
window.analytics?.capture("login", {
94-
type: "google",
95-
})
96-
}}
97-
>
98-
<LoginButtonContent isLoading={loadingLockSet === "google"}>
99-
<i className="i-mgc-google-cute-fi mr-2 text-xl" />
100-
{t("signin.continue_with_google")}
101-
</LoginButtonContent>
102-
</MotionButtonBase>
66+
{Object.entries(authProviders || []).map(([key, provider]) => (
67+
<MotionButtonBase
68+
key={key}
69+
className={clsx(
70+
"center h-[48px] w-[320px] rounded-[8px] font-sans text-base font-medium text-white",
71+
disabled && "pointer-events-none opacity-50",
72+
"overflow-hidden",
73+
authProvidersConfig[key]?.buttonClassName,
74+
)}
75+
disabled={disabled}
76+
onClick={() => {
77+
loginHandler(key, runtime)
78+
setLoadingLockSet(key)
79+
window.analytics?.capture("login", {
80+
type: key,
81+
})
82+
}}
83+
>
84+
<LoginButtonContent isLoading={loadingLockSet === key}>
85+
<i className={clsx("mr-2 text-xl", authProvidersConfig[key].iconClassName)} />{" "}
86+
{t("signin.continue_with", { provider: provider.name })}
87+
</LoginButtonContent>
88+
</MotionButtonBase>
89+
))}
10390
</div>
10491
</m.div>
10592
</div>

apps/renderer/src/queries/users.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
import { getProviders } from "@hono/auth-js/react"
2+
import { useQuery } from "@tanstack/react-query"
3+
14
import { apiClient } from "~/lib/api-fetch"
25
import { defineQuery } from "~/lib/defineQuery"
36

@@ -10,3 +13,20 @@ export const users = {
1013
return res.data
1114
}),
1215
}
16+
17+
export const useAuthProviders = () => {
18+
return useQuery({
19+
queryKey: ["providers"],
20+
queryFn: () => getProviders(),
21+
placeholderData: {
22+
google: {
23+
id: "google",
24+
name: "Google",
25+
},
26+
github: {
27+
id: "github",
28+
name: "GitHub",
29+
},
30+
} as Awaited<ReturnType<typeof getProviders>>,
31+
})
32+
}

apps/server/client/pages/(login)/login.tsx

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
import { UserAvatar } from "@client/components/ui/user-avatar"
22
import { apiClient } from "@client/lib/api-fetch"
33
import { LOGIN_CALLBACK_URL, loginHandler } from "@client/lib/auth"
4+
import { useAuthProviders } from "@client/query/users"
45
import { Logo } from "@follow/components/icons/logo.jsx"
56
import { Button } from "@follow/components/ui/button/index.js"
7+
import { authProvidersConfig } from "@follow/constants"
68
import { DEEPLINK_SCHEME } from "@follow/shared/constants"
9+
import { cn } from "@follow/utils/utils"
710
import { SessionProvider, signIn, signOut, useSession } from "@hono/auth-js/react"
811
import { useCallback, useEffect, useRef, useState } from "react"
912
import { useTranslation } from "react-i18next"
@@ -25,6 +28,7 @@ function Login() {
2528
const location = useLocation()
2629
const urlParams = new URLSearchParams(location.search)
2730
const provider = urlParams.get("provider")
31+
const { data: authProviders } = useAuthProviders()
2832

2933
const isAuthenticated = status === "authenticated"
3034

@@ -106,22 +110,21 @@ function Login() {
106110
</div>
107111
) : (
108112
<>
109-
<Button
110-
buttonClassName="h-[48px] w-[320px] rounded-[8px] !bg-black font-sans text-base text-white hover:!bg-black/80 focus:!border-black/80 focus:!ring-black/80"
111-
onClick={() => {
112-
loginHandler("github")
113-
}}
114-
>
115-
<i className="i-mgc-github-cute-fi mr-2 text-xl" /> {t("login.continueWithGitHub")}
116-
</Button>
117-
<Button
118-
buttonClassName="h-[48px] w-[320px] rounded-[8px] bg-blue-500 font-sans text-base text-white hover:bg-blue-500/90 focus:!border-blue-500/80 focus:!ring-blue-500/80"
119-
onClick={() => {
120-
loginHandler("google")
121-
}}
122-
>
123-
<i className="i-mgc-google-cute-fi mr-2 text-xl" /> {t("login.continueWithGoogle")}
124-
</Button>
113+
{Object.entries(authProviders || []).map(([key, provider]) => (
114+
<Button
115+
key={key}
116+
buttonClassName={cn(
117+
"h-[48px] w-[320px] rounded-[8px] font-sans text-base text-white hover:!bg-black/80 focus:!border-black/80 focus:!ring-black/80",
118+
authProvidersConfig[key]?.buttonClassName,
119+
)}
120+
onClick={() => {
121+
loginHandler(key)
122+
}}
123+
>
124+
<i className={cn("mr-2 text-xl", authProvidersConfig[key].iconClassName)} />{" "}
125+
{t("login.continueWith", { provider: provider.name })}
126+
</Button>
127+
))}
125128
</>
126129
)}
127130
</div>

apps/server/client/query/users.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { apiClient } from "@client/lib/api-fetch"
22
import { getHydrateData } from "@client/lib/helper"
33
import { capitalizeFirstLetter, isBizId, parseUrl } from "@follow/utils/utils"
4+
import { getProviders } from "@hono/auth-js/react"
45
import { useQuery } from "@tanstack/react-query"
56

67
export const useUserSubscriptionsQuery = (userId: string | undefined) => {
@@ -55,3 +56,20 @@ export const useUserQuery = (handleOrId: string | undefined) => {
5556
initialData: getHydrateData(`profiles.$get,query:id=${handleOrId}`),
5657
})
5758
}
59+
60+
export const useAuthProviders = () => {
61+
return useQuery({
62+
queryKey: ["providers"],
63+
queryFn: () => getProviders(),
64+
placeholderData: {
65+
google: {
66+
id: "google",
67+
name: "Google",
68+
},
69+
github: {
70+
id: "github",
71+
name: "GitHub",
72+
},
73+
} as Awaited<ReturnType<typeof getProviders>>,
74+
})
75+
}

icons/mgc/apple_cute_fi.svg

Lines changed: 1 addition & 0 deletions
Loading

locales/app/ar-DZ.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,8 +154,6 @@
154154
"sidebar.feed_column.context_menu.mark_as_read": "تحديد كمقروء",
155155
"sidebar.feed_column.context_menu.rename_category": "إعادة تسمية الفئة",
156156
"sidebar.select_sort_method": "اختيار طريقة الترتيب",
157-
"signin.continue_with_github": "المتابعة باستخدام GitHub",
158-
"signin.continue_with_google": "المتابعة باستخدام Google",
159157
"signin.sign_in_to": "تسجيل الدخول إلى",
160158
"sync_indicator.disabled": "بسبب أسباب أمنية، تم تعطيل المزامنة.",
161159
"sync_indicator.offline": "غير متصل",

locales/app/ar-IQ.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,8 +158,6 @@
158158
"sidebar.feed_column.context_menu.mark_as_read": "تحديد كمقروء",
159159
"sidebar.feed_column.context_menu.rename_category": "إعادة تسمية الفئة",
160160
"sidebar.select_sort_method": "اختر طريقة الترتيب",
161-
"signin.continue_with_github": "متابعة باستخدام GitHub",
162-
"signin.continue_with_google": "متابعة باستخدام Google",
163161
"signin.sign_in_to": "تسجيل الدخول إلى",
164162
"sync_indicator.disabled": "نظرًا لأسباب أمنية، تم تعطيل المزامنة.",
165163
"sync_indicator.offline": "غير متصل",

locales/app/ar-KW.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,8 +158,6 @@
158158
"sidebar.feed_column.context_menu.mark_as_read": "وضع علامة كمقروء",
159159
"sidebar.feed_column.context_menu.rename_category": "إعادة تسمية الفئة",
160160
"sidebar.select_sort_method": "اختر طريقة الفرز",
161-
"signin.continue_with_github": "متابعة باستخدام GitHub",
162-
"signin.continue_with_google": "متابعة باستخدام Google",
163161
"signin.sign_in_to": "تسجيل الدخول إلى",
164162
"sync_indicator.disabled": "بسبب أسباب أمنية، تم تعطيل المزامنة.",
165163
"sync_indicator.offline": "غير متصل",

locales/app/ar-MA.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,8 +154,6 @@
154154
"sidebar.feed_column.context_menu.mark_as_read": "وضع علامة كمقروء",
155155
"sidebar.feed_column.context_menu.rename_category": "إعادة تسمية الفئة",
156156
"sidebar.select_sort_method": "اختر طريقة الترتيب",
157-
"signin.continue_with_github": "متابعة باستخدام GitHub",
158-
"signin.continue_with_google": "متابعة باستخدام Google",
159157
"signin.sign_in_to": "تسجيل الدخول إلى",
160158
"sync_indicator.disabled": "بسبب الأسباب الأمنية، تم تعطيل المزامنة.",
161159
"sync_indicator.offline": "غير متصل",

locales/app/ar-SA.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,8 +151,6 @@
151151
"sidebar.feed_column.context_menu.mark_as_read": "تمييز كمقروء",
152152
"sidebar.feed_column.context_menu.rename_category": "إعادة تسمية الفئة",
153153
"sidebar.select_sort_method": "اختر طريقة الفرز",
154-
"signin.continue_with_github": "المتابعة مع GitHub",
155-
"signin.continue_with_google": "المتابعة مع Google",
156154
"signin.sign_in_to": "تسجيل الدخول إلى",
157155
"sync_indicator.disabled": "لأسباب أمنية، تم تعطيل المزامنة.",
158156
"sync_indicator.offline": "غير متصل",

0 commit comments

Comments
 (0)