diff --git a/config/CN/.env.development b/config/CN/.env.development index 4dee48920dc..f69a1391312 100644 --- a/config/CN/.env.development +++ b/config/CN/.env.development @@ -4,6 +4,7 @@ GITHUB_CLIENT_ID=9821657775fbc74773f1 WECHAT_APP_ID=wx1133c2153a45e9b8 AGORA_OAUTH_CLIENT_ID=flat-dev GOOGLE_OAUTH_CLIENT_ID=273996094508-p97og69ojac5ja0khn1rvmi3tb7vgfgm.apps.googleusercontent.com +QQ_APP_ID= CLOUD_STORAGE_OSS_ALIBABA_ACCESS_KEY=LTAI5t9Gb6tzQzzLmB6cTVf7 CLOUD_STORAGE_OSS_ALIBABA_BUCKET=flat-storage diff --git a/config/CN/.env.production b/config/CN/.env.production index 29365132cb9..8994b124403 100644 --- a/config/CN/.env.production +++ b/config/CN/.env.production @@ -4,6 +4,7 @@ GITHUB_CLIENT_ID=71a29285a437998bdfe0 WECHAT_APP_ID=wx96d522d69d384cce AGORA_OAUTH_CLIENT_ID=flat GOOGLE_OAUTH_CLIENT_ID=273996094508-2rpraucen77a1o5dul5ftrua5k3og157.apps.googleusercontent.com +QQ_APP_ID= CLOUD_STORAGE_OSS_ALIBABA_ACCESS_KEY=LTAI5t9Gb6tzQzzLmB6cTVf7 CLOUD_STORAGE_OSS_ALIBABA_BUCKET=flat-storage diff --git a/config/US/.env.development b/config/US/.env.development index 1364f349022..989270e47df 100644 --- a/config/US/.env.development +++ b/config/US/.env.development @@ -4,6 +4,7 @@ GITHUB_CLIENT_ID=0ac608815326aead5db7 WECHAT_APP_ID=wx1133c2153a45e9b8 AGORA_OAUTH_CLIENT_ID=flat-dev GOOGLE_OAUTH_CLIENT_ID=273996094508-p97og69ojac5ja0khn1rvmi3tb7vgfgm.apps.googleusercontent.com +QQ_APP_ID= CLOUD_STORAGE_OSS_ALIBABA_ACCESS_KEY=LTAI5t9Gb6tzQzzLmB6cTVf7 CLOUD_STORAGE_OSS_ALIBABA_BUCKET=flat-storage diff --git a/config/US/.env.production b/config/US/.env.production index 4857ce0bda1..a8a7e6ec484 100644 --- a/config/US/.env.production +++ b/config/US/.env.production @@ -4,6 +4,7 @@ GITHUB_CLIENT_ID=da83d7e14217594fba46 WECHAT_APP_ID=wx96d522d69d384cce AGORA_OAUTH_CLIENT_ID=flat GOOGLE_OAUTH_CLIENT_ID=273996094508-2rpraucen77a1o5dul5ftrua5k3og157.apps.googleusercontent.com +QQ_APP_ID= CLOUD_STORAGE_OSS_ALIBABA_ACCESS_KEY=LTAI5t9Gb6tzQzzLmB6cTVf7 CLOUD_STORAGE_OSS_ALIBABA_BUCKET=flat-storage diff --git a/desktop/renderer-app/src/api-middleware/flatServer/index.ts b/desktop/renderer-app/src/api-middleware/flatServer/index.ts index b34e9b824ed..bc401d85436 100644 --- a/desktop/renderer-app/src/api-middleware/flatServer/index.ts +++ b/desktop/renderer-app/src/api-middleware/flatServer/index.ts @@ -666,6 +666,7 @@ export enum LoginPlatform { Agora = "Agora", Google = "Google", Phone = "Phone", + QQ = "QQ", } export interface RemoveBindingPayload { diff --git a/packages/flat-components/src/components/LoginPage/LoginButton/icons/qq.svg b/packages/flat-components/src/components/LoginPage/LoginButton/icons/qq.svg new file mode 100644 index 00000000000..9f1343d1004 --- /dev/null +++ b/packages/flat-components/src/components/LoginPage/LoginButton/icons/qq.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/flat-components/src/components/LoginPage/LoginButton/index.tsx b/packages/flat-components/src/components/LoginPage/LoginButton/index.tsx index a450129d000..22c1b5c0e55 100644 --- a/packages/flat-components/src/components/LoginPage/LoginButton/index.tsx +++ b/packages/flat-components/src/components/LoginPage/LoginButton/index.tsx @@ -2,11 +2,12 @@ import wechatSVG from "./icons/wechat.svg"; import agoraSVG from "./icons/agora.svg"; import githubSVG from "./icons/github.svg"; import googleSVG from "./icons/google.svg"; +import qqSVG from "./icons/qq.svg"; import "./index.less"; import React from "react"; -export type LoginButtonProviderType = "wechat" | "github" | "agora" | "google"; +export type LoginButtonProviderType = "wechat" | "github" | "agora" | "google" | "qq"; export interface LoginButtonProps { provider: LoginButtonProviderType; @@ -19,6 +20,7 @@ const svgDict: Record = { agora: agoraSVG, github: githubSVG, google: googleSVG, + qq: qqSVG, }; export const LoginButton: React.FC = ({ provider, text, onClick }) => { diff --git a/packages/flat-i18n/locales/en.json b/packages/flat-i18n/locales/en.json index 5932e8922b2..171e384e8e4 100644 --- a/packages/flat-i18n/locales/en.json +++ b/packages/flat-i18n/locales/en.json @@ -111,6 +111,7 @@ "begin-time": "Start time", "join-and-book-by-room-uuid": "Can join and book by room ID", "copy": "Copy", + "login-qq": "QQ", "login-github": "GitHub", "login-google": "Google", "login-wechat": "WeChat", diff --git a/packages/flat-i18n/locales/zh-CN.json b/packages/flat-i18n/locales/zh-CN.json index bfaf59f98a5..fd2fb6c665f 100644 --- a/packages/flat-i18n/locales/zh-CN.json +++ b/packages/flat-i18n/locales/zh-CN.json @@ -112,6 +112,7 @@ "room-type": "房间类型", "begin-time": "开始时间", "copy": "复制", + "login-qq": "QQ", "login-wechat": "微信", "login-github": "GitHub", "login-google": "Google", diff --git a/packages/flat-pages/src/LoginPage/index.tsx b/packages/flat-pages/src/LoginPage/index.tsx index b01753da117..962b9c91f62 100644 --- a/packages/flat-pages/src/LoginPage/index.tsx +++ b/packages/flat-pages/src/LoginPage/index.tsx @@ -9,6 +9,7 @@ import { githubLogin } from "./githubLogin"; import { WeChatLogin } from "./WeChatLogin"; import { agoraLogin } from "./agoraLogin"; import { googleLogin } from "./googleLogin"; +import { qqLogin } from "./qqLogin"; import { RouteNameType, usePushHistory, useURLParams } from "../utils/routes"; import { GlobalStoreContext, WindowsSystemBtnContext } from "../components/StoreProvider"; import { joinRoomHandler } from "../utils/join-room-handler"; @@ -113,6 +114,10 @@ export const LoginPage = observer(function LoginPage() { loginDisposer.current = googleLogin(onLoginResult, windowsBtn); return; } + case "qq": { + loginDisposer.current = qqLogin(onLoginResult, windowsBtn); + return; + } default: { return; } @@ -155,7 +160,11 @@ export const LoginPage = observer(function LoginPage() { bindingPhone={async (countryCode, phone, code) => wrap(bindingPhone(countryCode + phone, Number(code)).then(onBoundPhone)) } - buttons={[process.env.FLAT_REGION === "US" ? "google" : "wechat", "github"]} + buttons={ + process.env.FLAT_REGION === "US" + ? ["google", "github"] + : ["wechat", "qq", "github"] + } cancelBindingPhone={() => setLoginResult(null)} isBindingPhone={ NEED_BINDING_PHONE && (loginResult ? !loginResult.hasPhone : false) diff --git a/packages/flat-pages/src/LoginPage/qqLogin.ts b/packages/flat-pages/src/LoginPage/qqLogin.ts new file mode 100644 index 00000000000..de9494d0629 --- /dev/null +++ b/packages/flat-pages/src/LoginPage/qqLogin.ts @@ -0,0 +1,47 @@ +import { v4 as uuidv4 } from "uuid"; +import { LoginExecutor } from "./utils"; +import { QQ } from "../constants/process"; +import { errorTips } from "flat-components"; +import { FLAT_SERVER_LOGIN, setAuthUUID, loginProcess } from "@netless/flat-server-api"; + +export const qqLogin: LoginExecutor = (onSuccess, windowsBtn) => { + let timer = NaN; + const authUUID = uuidv4(); + + void (async () => { + try { + await setAuthUUID(authUUID); + } catch (err) { + errorTips(err); + } + + windowsBtn + ? windowsBtn.openExternalBrowser(getQqURL(authUUID, FLAT_SERVER_LOGIN.QQ_CALLBACK)) + : void window.open(getQqURL(authUUID, FLAT_SERVER_LOGIN.QQ_CALLBACK)); + + const qqLoginProcessRequest = async (): Promise => { + try { + const data = await loginProcess(authUUID); + if (!data.name) { + timer = window.setTimeout(qqLoginProcessRequest, 2000); + return; + } + + onSuccess(data); + } catch (err) { + errorTips(err); + } + }; + + void qqLoginProcessRequest(); + })(); + + return () => { + window.clearTimeout(timer); + }; +}; + +export function getQqURL(authUUID: string, redirect_uri: string): string { + const redirectURL = encodeURIComponent(redirect_uri); + return `https://graph.qq.com/oauth2.0/authorize?response_type=code&client_id=${QQ.CLIENT_ID}&redirect_uri=${redirectURL}&state=${authUUID}`; +} diff --git a/packages/flat-pages/src/UserSettingPage/GeneralSettingPage/binding/index.ts b/packages/flat-pages/src/UserSettingPage/GeneralSettingPage/binding/index.ts index 9caffde0867..3d13adfa634 100644 --- a/packages/flat-pages/src/UserSettingPage/GeneralSettingPage/binding/index.ts +++ b/packages/flat-pages/src/UserSettingPage/GeneralSettingPage/binding/index.ts @@ -10,6 +10,7 @@ const defaultBindings: ListBindingsResult = { apple: false, github: false, google: false, + qq: false, }; export function useBindingList(): { bindings: ListBindingsResult; refresh: () => void } { diff --git a/packages/flat-pages/src/constants/process.ts b/packages/flat-pages/src/constants/process.ts index 5ff5bc170e4..f6ea363d065 100644 --- a/packages/flat-pages/src/constants/process.ts +++ b/packages/flat-pages/src/constants/process.ts @@ -32,6 +32,10 @@ export const GOOGLE = Object.freeze({ CLIENT_ID: process.env.GOOGLE_OAUTH_CLIENT_ID, }); +export const QQ = Object.freeze({ + CLIENT_ID: process.env.QQ_APP_ID, +}); + export const FLAT_DOWNLOAD_URL = process.env.FLAT_DOWNLOAD_URL; export const PRIVACY_URL_CN = "https://flat.whiteboard.agora.io/privacy.html"; diff --git a/packages/flat-pages/src/typings/global.d.ts b/packages/flat-pages/src/typings/global.d.ts index 92980332eec..94a1ddfa8da 100644 --- a/packages/flat-pages/src/typings/global.d.ts +++ b/packages/flat-pages/src/typings/global.d.ts @@ -20,6 +20,7 @@ declare namespace NodeJS { GITHUB_CLIENT_ID: string; GOOGLE_OAUTH_CLIENT_ID: string; + QQ_APP_ID: string; WECHAT_APP_ID: string; FLAT_SERVER_DOMAIN: string; FLAT_WEB_DOMAIN: string; diff --git a/packages/flat-server-api/src/constants.ts b/packages/flat-server-api/src/constants.ts index d593f4cef4c..fa5ea3a192c 100644 --- a/packages/flat-server-api/src/constants.ts +++ b/packages/flat-server-api/src/constants.ts @@ -8,6 +8,7 @@ export const FLAT_SERVER_LOGIN = { GITHUB_CALLBACK: `https://${process.env.FLAT_SERVER_DOMAIN}/v1/login/github/callback?platform=web`, GOOGLE_CALLBACK: `https://${process.env.FLAT_SERVER_DOMAIN}/v1/login/google/callback`, WECHAT_CALLBACK: `https://${process.env.FLAT_SERVER_DOMAIN}/v1/login/weChat/web/callback`, + QQ_CALLBACK: `https://${process.env.FLAT_SERVER_DOMAIN}/v1/login/qq/callback?platform=web`, } as const; export const FLAT_SERVER_USER_BINDING = { diff --git a/packages/flat-server-api/src/login.ts b/packages/flat-server-api/src/login.ts index 0542747bb22..7f49f3bb584 100644 --- a/packages/flat-server-api/src/login.ts +++ b/packages/flat-server-api/src/login.ts @@ -131,6 +131,7 @@ export interface ListBindingsResult { apple: boolean; github: boolean; google: boolean; + qq: boolean; } export async function listBindings(): Promise { @@ -188,6 +189,7 @@ export enum LoginPlatform { Agora = "Agora", Google = "Google", Phone = "Phone", + QQ = "QQ", } export interface RemoveBindingPayload { diff --git a/web/flat-web/typings/global.d.ts b/web/flat-web/typings/global.d.ts index 92980332eec..94a1ddfa8da 100644 --- a/web/flat-web/typings/global.d.ts +++ b/web/flat-web/typings/global.d.ts @@ -20,6 +20,7 @@ declare namespace NodeJS { GITHUB_CLIENT_ID: string; GOOGLE_OAUTH_CLIENT_ID: string; + QQ_APP_ID: string; WECHAT_APP_ID: string; FLAT_SERVER_DOMAIN: string; FLAT_WEB_DOMAIN: string;