Skip to content

Commit

Permalink
refactor(ui/auth): ensure compatibility with new client types
Browse files Browse the repository at this point in the history
- Bump to new Artalk client export types
- Add `AuthContext` type definition for improved clarity
- Replace `ContextApi` with `AuthContext` for reducing the scope of variables
- Bump version to 0.0.2 for release

(The prerequisite PR is #1007)
  • Loading branch information
qwqcode committed Oct 18, 2024
1 parent d3aacf0 commit 789f32a
Show file tree
Hide file tree
Showing 19 changed files with 112 additions and 67 deletions.
4 changes: 2 additions & 2 deletions ui/plugin-auth/DialogExample.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import type { ContextApi } from 'artalk'
import { createSignal } from 'solid-js'
import { Dialog } from './Dialog'
import type { AuthContext } from './types'

interface DialogExampleProps {
ctx: ContextApi
ctx: AuthContext
onClose: () => void
}

Expand Down
10 changes: 5 additions & 5 deletions ui/plugin-auth/DialogMain.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import type { ContextApi } from 'artalk'
import { Show, createResource, createSignal, onMount } from 'solid-js'
import { createResource, createSignal } from 'solid-js'
import { Dialog } from './Dialog'
import { DialogMethods } from './DialogMethods'
import { DialogPageLogin } from './DialogPageLogin'
import { DialogPageRegister } from './DialogPageRegister'
import { createLayer } from './lib/layer'
import { DialogMerge } from './merge/DialogMerge'
import { fetchMethods, LoginMethod } from './lib/methods'
import type { AuthContext } from './types'

interface DialogMainProps {
ctx: ContextApi
ctx: AuthContext
onClose: () => void
onSkip: () => void
}
Expand All @@ -18,7 +18,7 @@ export const DialogMain = (props: DialogMainProps) => {
const { ctx, onClose, onSkip, ...others } = props

const [methods] = createResource(async () => {
return fetchMethods(ctx)
return fetchMethods(ctx.getApi())
.then((m) =>
m.map<LoginMethod>((mm) => {
if (mm.name === 'email') mm.onClick = () => setPage('login')
Expand All @@ -43,7 +43,7 @@ export const DialogMain = (props: DialogMainProps) => {
const onComplete = () => {
onClose()

ctx.get('editor').getUI().$header.style.display = 'none'
ctx.getEditor().getUI().$header.style.display = 'none'

// Check need to merge
ctx
Expand Down
6 changes: 3 additions & 3 deletions ui/plugin-auth/DialogMethods.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { createEffect, createMemo, createSignal, For, Resource } from 'solid-js'
import type { ContextApi } from 'artalk'
import { startOAuthLogin } from './lib/oauth-login'
import { loginByToken } from './lib/token-login'
import { LoginMethod } from './lib/methods'
import type { AuthContext } from './types'

export interface DialogMethodsProps {
ctx: ContextApi
ctx: AuthContext
methods: Resource<LoginMethod[]>
changeTitle: (title: string) => void
onComplete: () => void
Expand All @@ -23,7 +23,7 @@ export const DialogMethods = (props: DialogMethodsProps) => {
(async () => {
const url = /^(http|https):\/\//.test(m.link!)
? m.link!
: `${ctx.getConf().server}${m.link}`
: `${ctx.getConf().get().server}${m.link}`
const { token } = await startOAuthLogin(ctx, url)
loginByToken(ctx, token)
props.onComplete()
Expand Down
4 changes: 2 additions & 2 deletions ui/plugin-auth/DialogPageLogin.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import type { ContextApi } from 'artalk'
import { createStore } from 'solid-js/store'
import { loginByApiRes } from './lib/token-login'
import type { AuthContext } from './types'

export interface DialogPageLoginProps {
ctx: ContextApi
ctx: AuthContext
onRegisterNowClick: () => void
changeTitle: (title: string) => void
onComplete: () => void
Expand Down
4 changes: 2 additions & 2 deletions ui/plugin-auth/DialogPageRegister.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import type { ContextApi } from 'artalk'
import { Show, createSignal, createEffect } from 'solid-js'
import { createStore, reconcile } from 'solid-js/store'
import { VerifyButton } from './VerifyButton'
import { loginByApiRes } from './lib/token-login'
import type { AuthContext } from './types'

export interface DialogPageRegisterProps {
ctx: ContextApi
ctx: AuthContext
onLoginNowClick: () => void
changeTitle: (title: string) => void
onComplete: () => void
Expand Down
16 changes: 8 additions & 8 deletions ui/plugin-auth/EditorUser.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import type { ContextApi } from 'artalk'
import { Show, onCleanup, createSignal } from 'solid-js'
import { render } from 'solid-js/web'
import { AuthContext } from './types'
import { createLayer } from './lib/layer'
import { UserProfileDialog } from './UserProfileDialog'

const EditorUser = ({ ctx }: { ctx: ContextApi }) => {
const EditorUser = ({ ctx }: { ctx: AuthContext }) => {
const logoutHandler = () => {
window.confirm(ctx.$t('logoutConfirm')) &&
ctx.get('user').update({
ctx.getUser().update({
token: '',
name: '',
email: '',
Expand All @@ -16,17 +16,17 @@ const EditorUser = ({ ctx }: { ctx: ContextApi }) => {
})
}

const getUser = () => ({ ...ctx.get('user').getData() }) // Must clone the object to avoid reactivity problem
const getUser = () => ({ ...ctx.getUser().getData() }) // Must clone the object to avoid reactivity problem

const [user, setUser] = createSignal(getUser())

const userChangedHandler = (u: any) => {
setUser(getUser())
}
ctx.on('user-changed', userChangedHandler)
ctx.getEvents().on('user-changed', userChangedHandler)

onCleanup(() => {
ctx.off('user-changed', userChangedHandler)
ctx.getEvents().off('user-changed', userChangedHandler)
})

const openUserProfileDialog = () => {
Expand Down Expand Up @@ -62,8 +62,8 @@ const EditorUser = ({ ctx }: { ctx: ContextApi }) => {
)
}

export const RenderEditorUser = (ctx: ContextApi) => {
const editor = ctx.get('editor')
export const RenderEditorUser = (ctx: AuthContext) => {
const editor = ctx.getEditor()
const findEl = () => editor.getEl().querySelector('.atk-editor-user-wrap')

if (!findEl()) {
Expand Down
15 changes: 8 additions & 7 deletions ui/plugin-auth/UserProfileDialog.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { ContextApi, LocalUser } from 'artalk'
import { LocalUser } from 'artalk'
import { createResource, createSignal, Resource, Show } from 'solid-js'
import { createStore } from 'solid-js/store'
import type { AuthContext } from './types'
import { Dialog } from './Dialog'
import { VerifyButton } from './VerifyButton'

export interface UserProfileDialogProps {
ctx: ContextApi
ctx: AuthContext
onClose: () => void
}

Expand All @@ -17,7 +18,7 @@ export const UserProfileDialog = (props: UserProfileDialogProps) => {
const [userInfo] = createResource<LocalUser>(async () => {
const { data } = await ctx.getApi().user.getUser()
if (!data.is_login) {
ctx.get('user').logout()
ctx.getUser().logout()
onClose()
throw new Error('No login')
}
Expand All @@ -43,7 +44,7 @@ export const UserProfileDialog = (props: UserProfileDialogProps) => {
}

const UserBasicProfileForm = (
ctx: ContextApi,
ctx: AuthContext,
onChangePassword: () => void,
setTitle: (t: string) => void,
user: Resource<LocalUser>,
Expand All @@ -69,7 +70,7 @@ const UserBasicProfileForm = (
...fields,
})
.then(({ data: { user } }) => {
ctx.get('user').update(user)
ctx.getUser().update(user)
onClose()
})
.catch((e) => {
Expand Down Expand Up @@ -136,7 +137,7 @@ const UserBasicProfileForm = (
}

const UserChangePasswordForm = (
ctx: ContextApi,
ctx: AuthContext,
setTitle: (t: string) => void,
user: Resource<LocalUser>,
onClose: () => void,
Expand Down Expand Up @@ -166,7 +167,7 @@ const UserChangePasswordForm = (
code: fields.code,
})
.then((res) => {
ctx.get('user').logout()
ctx.getUser().logout()
onClose()
})
.catch((err) => {
Expand Down
4 changes: 2 additions & 2 deletions ui/plugin-auth/VerifyButton.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import type { ContextApi } from 'artalk'
import { createSignal } from 'solid-js'
import type { AuthContext } from './types'

interface VerifyButtonProps {
ctx: ContextApi
ctx: AuthContext
getEmail: () => string
onSend?: () => void
}
Expand Down
7 changes: 4 additions & 3 deletions ui/plugin-auth/lib/layer.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import type { ContextApi, Layer } from 'artalk'
import { JSX } from 'solid-js'
import { render } from 'solid-js/web'
import type { Layer } from 'artalk'
import type { AuthContext } from '../types'

export const createLayer = (ctx: ContextApi) => {
const layer = ctx.get('layerManager').create('login')
export const createLayer = (ctx: AuthContext) => {
const layer = ctx.getLayers().create('login')
const show = (el: (l: Layer) => JSX.Element) => {
const $el = document.createElement('div')
render(() => el(layer), $el)
Expand Down
6 changes: 3 additions & 3 deletions ui/plugin-auth/lib/methods.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ContextApi } from 'artalk'
import type { Api } from 'artalk'

export interface LoginMethod {
name: string
Expand All @@ -8,8 +8,8 @@ export interface LoginMethod {
onClick?: () => void
}

export const fetchMethods = async (ctx: ContextApi) => {
const { data } = await ctx.getApi().conf.getSocialLoginProviders()
export const fetchMethods = async (api: Api) => {
const { data } = await api.conf.getSocialLoginProviders()
return data.providers
.map<LoginMethod>(({ name, label, icon, path }) => {
return { name, label, icon, link: path }
Expand Down
4 changes: 2 additions & 2 deletions ui/plugin-auth/lib/oauth-login.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { ContextApi } from 'artalk'
import type { AuthContext } from '../types'

let watchTimer: any = null
let messageHandler: ((evt: MessageEvent) => void) | null = null
Expand All @@ -8,7 +8,7 @@ const clearListener = () => {
messageHandler && window.removeEventListener('message', messageHandler)
}

export const startOAuthLogin = (ctx: ContextApi, url: string) => {
export const startOAuthLogin = (ctx: AuthContext, url: string) => {
clearListener()

const width = 1020
Expand Down
13 changes: 7 additions & 6 deletions ui/plugin-auth/lib/token-login.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,26 @@
import type { ContextApi, LocalUser } from 'artalk'
import type { LocalUser } from 'artalk'
import type { AuthContext } from '../types'

interface ResponseLoginData {
user: Omit<LocalUser, 'token'>
token: string
}

export const loginByApiRes = (ctx: ContextApi, { user, token }: ResponseLoginData) => {
ctx.get('user').update({
export const loginByApiRes = (ctx: AuthContext, { user, token }: ResponseLoginData) => {
ctx.getUser().update({
...user,
token,
})
}

export const loginByToken = (ctx: ContextApi, token: string) => {
ctx.get('user').update({ token })
export const loginByToken = (ctx: AuthContext, token: string) => {
ctx.getUser().update({ token })
ctx
.getApi()
.user.getUser()
.then((res) => {
const { user } = res.data
ctx.get('user').update({
ctx.getUser().update({
name: user.name,
email: user.email,
link: user.link,
Expand Down
50 changes: 35 additions & 15 deletions ui/plugin-auth/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,33 +4,53 @@ import type { ArtalkPlugin } from 'artalk'
import { DialogMain } from './DialogMain'
import { createLayer } from './lib/layer'
import { RenderEditorUser } from './EditorUser'
import type { AuthContext } from './types'

export const ArtalkAuthPlugin: ArtalkPlugin = (ctx) => {
ctx.getApiHandlers().add('need_auth_login', () => {
const editor = ctx.inject('editor')
const api = ctx.inject('api')
const apiHandlers = ctx.inject('apiHandlers')
const user = ctx.inject('user')
const events = ctx.inject('events')
const config = ctx.inject('config')
const layers = ctx.inject('layers')

const authCtx: AuthContext = {
getEditor: () => editor,
getApi: () => api,
getApiHandlers: () => apiHandlers,
getUser: () => user,
getEvents: () => events,
getConf: () => config,
getLayers: () => layers,
$t: (key, args) => ctx.$t(key, args),
}

apiHandlers.add('need_auth_login', () => {
openAuthDialog()
throw new Error('Login required')
})

let anonymous = false
const refreshBtn = () => {
ctx.get('editor').getUI().$submitBtn.innerText =
ctx.get('user').getData().token || anonymous
? ctx.conf.sendBtn || ctx.$t('send')
: ctx.$t('signIn')
editor.getUI().$submitBtn.innerText =
user.getData().token || anonymous
? authCtx.getConf().get().sendBtn || authCtx.$t('send')
: authCtx.$t('signIn')
}

ctx.watchConf(['locale', 'sendBtn'], () => refreshBtn())
ctx.on('user-changed', () => refreshBtn())
authCtx.getConf().watchConf(['locale', 'sendBtn'], () => refreshBtn())
authCtx.getEvents().on('user-changed', () => refreshBtn())

ctx.on('mounted', () => {
ctx.get('editor').getUI().$header.style.display = 'none'
authCtx.getEvents().on('mounted', () => {
editor.getUI().$header.style.display = 'none'

RenderEditorUser(ctx)
RenderEditorUser(authCtx)
})

const onSkip = () => {
ctx.get('editor').getUI().$header.style.display = ''
ctx.get('editor').getUI().$name.focus()
editor.getUI().$header.style.display = ''
editor.getUI().$name.focus()
ctx.updateConf({
beforeSubmit: undefined,
})
Expand All @@ -40,14 +60,14 @@ export const ArtalkAuthPlugin: ArtalkPlugin = (ctx) => {
}

const openAuthDialog = () => {
createLayer(ctx).show((layer) => (
<DialogMain ctx={ctx} onClose={() => layer.destroy()} onSkip={onSkip} />
createLayer(authCtx).show((layer) => (
<DialogMain ctx={authCtx} onClose={() => layer.destroy()} onSkip={onSkip} />
))
}

ctx.updateConf({
beforeSubmit: (editor, next) => {
if (!ctx.get('user').getData().token) {
if (!user.getData().token) {
openAuthDialog()
} else {
next()
Expand Down
4 changes: 2 additions & 2 deletions ui/plugin-auth/merge/DialogMerge.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import type { ContextApi } from 'artalk'
import { createSignal } from 'solid-js'
import { Dialog } from '../Dialog'
import type { AuthContext } from '../types'
import { DialogMergePageConfirm } from './DialogMergePageConfirm'

interface DialogMergeProps {
ctx: ContextApi
ctx: AuthContext
usernames: string[]
onClose: () => void
}
Expand Down
Loading

0 comments on commit 789f32a

Please sign in to comment.