Skip to content

Commit 60be490

Browse files
committed
feat: add user list
1 parent 708af1d commit 60be490

File tree

13 files changed

+651
-255
lines changed

13 files changed

+651
-255
lines changed

package.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@
2323
"title": "Post",
2424
"description": "Create a new post",
2525
"mode": "view"
26+
},
27+
{
28+
"name": "user-list",
29+
"title": "User List",
30+
"description": "List all users",
31+
"mode": "view"
2632
}
2733
],
2834
"scripts": {
@@ -37,7 +43,7 @@
3743
},
3844
"dependencies": {
3945
"@raycast/api": "^1.35.1",
40-
"jike-sdk": "^0.19.0"
46+
"jike-sdk": "^0.19.1"
4147
},
4248
"devDependencies": {
4349
"@sxzz/eslint-config-prettier": "^2.2.1",

pnpm-lock.yaml

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/login.tsx

Lines changed: 2 additions & 189 deletions
Original file line numberDiff line numberDiff line change
@@ -1,190 +1,3 @@
1-
import {
2-
Action,
3-
ActionPanel,
4-
Form,
5-
Toast,
6-
popToRoot,
7-
showToast,
8-
useNavigation,
9-
} from '@raycast/api'
10-
import { useState } from 'react'
11-
import { JikeClient } from 'jike-sdk'
12-
import { updateConfig } from './utils/config'
13-
import { isSameUser } from './utils/user'
14-
import { handleError } from './utils/errors'
1+
import { Login } from './views/login'
152

16-
interface EndpointInfo {
17-
userAgent: string
18-
bundleId: string
19-
appVersion: string
20-
endpointUrl: string
21-
buildNo: string
22-
endpointId: string
23-
}
24-
25-
export default function Command() {
26-
const { push } = useNavigation()
27-
28-
const login = (info: EndpointInfo) => {
29-
push(<Authentication endpointInfo={info} />)
30-
}
31-
32-
return (
33-
<Form
34-
navigationTitle="配置 Endpoint 信息"
35-
actions={
36-
<ActionPanel>
37-
<Action.SubmitForm title="Submit" onSubmit={login} />
38-
</ActionPanel>
39-
}
40-
>
41-
<Form.Description
42-
title="Tips"
43-
text="自行在 GitHub 搜索「jike endpoint」探索配置"
44-
/>
45-
46-
<Form.TextField
47-
id="endpointId"
48-
title="Endpoint ID"
49-
storeValue
50-
placeholder="jike"
51-
autoFocus
52-
/>
53-
54-
<Form.TextField id="endpointUrl" title="Endpoint URL" storeValue />
55-
<Form.TextField id="bundleId" title="Bundle ID" storeValue />
56-
<Form.TextField id="appVersion" title="APP Version" storeValue />
57-
<Form.TextField id="buildNo" title="Build Number" storeValue />
58-
<Form.TextField id="userAgent" title="User Agent" storeValue />
59-
</Form>
60-
)
61-
}
62-
63-
interface AuthenticationProps {
64-
endpointInfo: EndpointInfo
65-
}
66-
67-
interface AuthenticationForm {
68-
areaCode: string
69-
mobile: string
70-
password: string
71-
smsCode: string
72-
}
73-
74-
function Authentication(props: AuthenticationProps) {
75-
const [loginMethod, setLoginMethod] = useState<'password' | 'smsCode'>(
76-
'password'
77-
)
78-
const [isSentSMS, setIsSentSMS] = useState(false)
79-
const [isLoading, setIsLoading] = useState(false)
80-
81-
const buildClient = () => new JikeClient(props.endpointInfo)
82-
83-
const sendSMS = async (form: AuthenticationForm) => {
84-
setIsLoading(true)
85-
86-
try {
87-
await buildClient().sendSmsCode(form.areaCode, form.mobile)
88-
} catch (err) {
89-
handleError(err)
90-
return
91-
} finally {
92-
setIsLoading(false)
93-
}
94-
95-
setIsSentSMS(true)
96-
await showToast({
97-
title: '短信已发送',
98-
style: Toast.Style.Success,
99-
})
100-
}
101-
102-
const login = async (form: AuthenticationForm) => {
103-
setIsLoading(true)
104-
105-
const client = buildClient()
106-
try {
107-
// TODO: validate form
108-
if (loginMethod === 'password') {
109-
await client.loginWithPassword(
110-
form.areaCode,
111-
form.mobile,
112-
form.password
113-
)
114-
} else {
115-
await client.loginWithSmsCode(form.areaCode, form.mobile, form.smsCode)
116-
}
117-
} catch (err) {
118-
handleError(err)
119-
return
120-
} finally {
121-
setIsLoading(false)
122-
}
123-
124-
await showToast({
125-
title: '登录成功',
126-
message: `Hi, ${await client.getSelf().getScreenName()}`,
127-
style: Toast.Style.Success,
128-
})
129-
130-
// Save
131-
await updateConfig(async (cfg) => {
132-
const user = await client.toJSON()
133-
const index = cfg.users.findIndex((_auth) => isSameUser(user, _auth))
134-
if (index > -1) {
135-
cfg.users[index] = user
136-
} else {
137-
cfg.users.push(user)
138-
}
139-
})
140-
141-
popToRoot()
142-
}
143-
144-
const actions = [
145-
<Action.SubmitForm key="login" title="Login" onSubmit={login} />,
146-
]
147-
if (loginMethod === 'smsCode') {
148-
actions[isSentSMS ? 'push' : 'unshift'](
149-
<Action.SubmitForm
150-
key="sendSMS"
151-
title={isSentSMS ? 'Resend SMS' : 'Send SMS'}
152-
onSubmit={sendSMS}
153-
/>
154-
)
155-
}
156-
return (
157-
<Form
158-
navigationTitle="认证信息"
159-
isLoading={isLoading}
160-
actions={<ActionPanel>{...actions}</ActionPanel>}
161-
>
162-
<Form.TextField
163-
id="areaCode"
164-
title="区号"
165-
placeholder="86"
166-
defaultValue="86"
167-
/>
168-
<Form.TextField id="mobile" title="手机号" autoFocus />
169-
170-
<Form.Separator />
171-
172-
<Form.Dropdown
173-
id="loginMethod"
174-
title="认证方式"
175-
value={loginMethod}
176-
onChange={setLoginMethod as any}
177-
>
178-
<Form.Dropdown.Item value="password" title="登录密码" icon="🔑" />
179-
<Form.Dropdown.Item value="smsCode" title="短信验证码" icon="📲" />
180-
</Form.Dropdown>
181-
182-
{loginMethod === 'password' && (
183-
<Form.PasswordField id="password" title="密码" />
184-
)}
185-
{loginMethod === 'smsCode' && (
186-
<Form.TextField id="smsCode" title="短信验证码" />
187-
)}
188-
</Form>
189-
)
190-
}
3+
export default Login

src/post.tsx

Lines changed: 2 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,3 @@
1-
import {
2-
Action,
3-
ActionPanel,
4-
Form,
5-
Toast,
6-
showToast,
7-
useNavigation,
8-
} from '@raycast/api'
9-
import { ApiOptions, JikeClient } from 'jike-sdk'
10-
import { useState } from 'react'
11-
import { getConfig } from './utils/config'
12-
import { handleError } from './utils/errors'
1+
import { Post } from './views/post'
132

14-
export default function Command() {
15-
const { pop } = useNavigation()
16-
const [content, setContent] = useState('')
17-
18-
const submit = async () => {
19-
if (content.trim().length === 0) {
20-
await showToast({
21-
title: '内容不能为空',
22-
style: Toast.Style.Failure,
23-
})
24-
return
25-
}
26-
27-
const client = JikeClient.fromJSON((await getConfig()).users[0])
28-
try {
29-
await client.createPost(ApiOptions.PostType.ORIGINAL, content)
30-
} catch (err) {
31-
handleError(err)
32-
return
33-
}
34-
35-
await showToast({
36-
title: '发送成功',
37-
style: Toast.Style.Success,
38-
})
39-
pop()
40-
}
41-
42-
return (
43-
<Form
44-
navigationTitle="发布动态"
45-
actions={
46-
<ActionPanel>
47-
<Action.SubmitForm title="Submit" onSubmit={submit} />
48-
</ActionPanel>
49-
}
50-
>
51-
<Form.TextArea
52-
id="content"
53-
title="内容"
54-
placeholder="请输入要发送的内容"
55-
autoFocus
56-
value={content}
57-
onChange={setContent}
58-
/>
59-
</Form>
60-
)
61-
}
3+
export default Post

src/user-list.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { UserList } from './views/user-list'
2+
3+
export default UserList

src/utils/errors.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,13 @@ import { RequestFailureError } from 'jike-sdk'
33

44
export const handleError = async (err: any) => {
55
if (err instanceof RequestFailureError) {
6+
console.error(err.response.data)
67
await showToast({
78
title: err.message,
89
style: Toast.Style.Failure,
910
})
10-
} else throw err
11+
} else {
12+
console.error(err)
13+
throw err
14+
}
1115
}

src/utils/user.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,8 @@ import type { ConfigUser } from './config'
33
export const isSameUser = (left: ConfigUser, right: ConfigUser) =>
44
// left.endpointUrl === right.endpointUrl &&
55
left.userId === right.userId
6+
7+
export const findUser = (users: ConfigUser[], user: ConfigUser) => {
8+
const index = users.findIndex((u) => isSameUser(user, u))
9+
return [users[index], index] as const
10+
}

0 commit comments

Comments
 (0)