105 lines
2.6 KiB
TypeScript
105 lines
2.6 KiB
TypeScript
import { useState, useCallback } from 'react'
|
|
import { ImagePickerAsset, launchImageLibraryAsync, MediaTypeOptions } from 'expo-image-picker'
|
|
import Toast from '@/components/ui/Toast'
|
|
import { updateUser } from '@/lib/auth'
|
|
import { uploadFile } from '@/lib/uploadFile'
|
|
import { type ApiError } from '@/lib/types'
|
|
|
|
export interface UpdateProfileParams {
|
|
name?: string
|
|
image?: ImagePickerAsset
|
|
}
|
|
|
|
export function useUpdateProfile() {
|
|
const [loading, setLoading] = useState(false)
|
|
const [error, setError] = useState<ApiError | null>(null)
|
|
|
|
/**
|
|
* 选择图片
|
|
*/
|
|
const pickImage = useCallback(async (): Promise<ImagePickerAsset | null> => {
|
|
try {
|
|
const result = await launchImageLibraryAsync({
|
|
mediaTypes: MediaTypeOptions.Images,
|
|
allowsEditing: true,
|
|
aspect: [1, 1],
|
|
quality: 0.8,
|
|
})
|
|
|
|
if (result.canceled) {
|
|
return null
|
|
}
|
|
|
|
return result.assets[0] || null
|
|
} catch (err) {
|
|
console.error('选择图片失败:', err)
|
|
Toast.show('选择图片失败')
|
|
return null
|
|
}
|
|
}, [])
|
|
|
|
/**
|
|
* 更新用户资料
|
|
*/
|
|
const updateProfile = useCallback(async (params: UpdateProfileParams) => {
|
|
setLoading(true)
|
|
setError(null)
|
|
|
|
try {
|
|
const updateData: Record<string, any> = {}
|
|
|
|
// 如果有新头像,先上传图片
|
|
if (params.image) {
|
|
Toast.showLoading({ title: '上传头像中...' })
|
|
try {
|
|
const imageUrl = await uploadFile({
|
|
uri: params.image.uri,
|
|
mimeType: params.image.mimeType || 'image/jpeg',
|
|
fileName: `avatar_${Date.now()}.jpg`,
|
|
})
|
|
updateData.image = imageUrl
|
|
Toast.hideLoading()
|
|
} catch (err) {
|
|
Toast.hideLoading()
|
|
throw new Error('头像上传失败')
|
|
}
|
|
}
|
|
|
|
// 更新用户名
|
|
if (params.name) {
|
|
updateData.name = params.name
|
|
}
|
|
|
|
// 如果有数据需要更新
|
|
if (Object.keys(updateData).length > 0) {
|
|
Toast.showLoading({ title: '保存中...' })
|
|
const result = await updateUser(updateData)
|
|
Toast.hideLoading()
|
|
|
|
if (result.error) {
|
|
throw result.error
|
|
}
|
|
|
|
Toast.show('保存成功')
|
|
return { data: result.data, error: null }
|
|
}
|
|
|
|
return { data: null, error: null }
|
|
} catch (err) {
|
|
const errorObj = err as ApiError
|
|
setError(errorObj)
|
|
Toast.show(errorObj.message || '保存失败,请稍后重试')
|
|
return { data: null, error: errorObj }
|
|
} finally {
|
|
setLoading(false)
|
|
}
|
|
}, [])
|
|
|
|
return {
|
|
loading,
|
|
error,
|
|
pickImage,
|
|
updateProfile,
|
|
}
|
|
}
|