feat: 更新图片选择器逻辑,增强 BLE 监控错误处理;更新应用版本号;添加 Figma 服务器配置
This commit is contained in:
parent
5b721ae274
commit
e08061fa21
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"servers": {
|
||||
"Figma": {
|
||||
"url": "https://mcp.figma.com/mcp",
|
||||
"type": "http"
|
||||
}
|
||||
},
|
||||
"inputs": []
|
||||
}
|
||||
|
|
@ -1,9 +1,13 @@
|
|||
import * as ImagePicker from 'expo-image-picker'
|
||||
|
||||
import Toast from '../components/Toast'
|
||||
|
||||
// 定义图片项类型
|
||||
|
||||
type PickerBaseParams = Omit<ImagePicker.ImagePickerOptions, 'mediaTypes' | 'allowsMultipleSelection' | 'selectionLimit'> & {
|
||||
type PickerBaseParams = Omit<
|
||||
ImagePicker.ImagePickerOptions,
|
||||
'mediaTypes' | 'allowsMultipleSelection' | 'selectionLimit'
|
||||
> & {
|
||||
maxImages?: number
|
||||
type?: ImagePicker.MediaTypeOptions
|
||||
}
|
||||
|
|
@ -28,7 +32,7 @@ export async function imgPicker(params: PickerUriParams | PickerAssetParams) {
|
|||
|
||||
const result = await ImagePicker.launchImageLibraryAsync({
|
||||
mediaTypes: type,
|
||||
allowsEditing: false,
|
||||
// allowsEditing: true,
|
||||
quality: 0.9,
|
||||
allowsMultipleSelection: isMultiple,
|
||||
selectionLimit: maxImages,
|
||||
|
|
|
|||
|
|
@ -8,6 +8,6 @@ export const ANDROID_ID = 'com.duomi.duooomi'
|
|||
export const IOS_ID = ANDROID_ID
|
||||
export const IOS_UNIVERSAL_LINK = 'duooomi.bowong.cn'
|
||||
export const OWNER_ID = 'x3xbTCWf7dbtWu4gGU2TeI054L77xtkt'
|
||||
export const APP_VERSION = 'dev202601082028'
|
||||
export const APP_VERSION = 'dev202601121337'
|
||||
export const ALIPAY_SCHEMA = 'alipay2021006119657394'
|
||||
export const ALIPAY_SCHEMA_SANDBOX = '9021000158673972'
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ const navItems = [
|
|||
{ id: 'index', label: '探索', iconName: 'compass-outline' },
|
||||
{ id: 'generate', label: '生成', iconName: 'image-outline' },
|
||||
{ id: 'sync', label: '同步', iconName: 'refresh' },
|
||||
// { id: 'explore', label: '蓝牙调试', iconName: 'person-outline' },
|
||||
{ id: 'explore', label: '蓝牙调试', iconName: 'person-outline' },
|
||||
]
|
||||
|
||||
function renderNavItem(item: (typeof navItems)[0], isActive: boolean, onRouteChange: (route: string) => void) {
|
||||
|
|
|
|||
|
|
@ -42,9 +42,6 @@ const Index = observer(function Index() {
|
|||
const { execute: loadFavorites } = useFavoriteTemplates()
|
||||
const { runTemplate } = useTemplateActions()
|
||||
|
||||
// 使用MobX Store中的余额信息
|
||||
const { balance } = userBalanceStore
|
||||
|
||||
/** ================= 状态 ================= */
|
||||
|
||||
const [activeTab, setActiveTab] = useState<ActiveTab>('')
|
||||
|
|
@ -113,6 +110,7 @@ const Index = observer(function Index() {
|
|||
let newItems: MediaItem[] = []
|
||||
|
||||
if (tab === 'like') {
|
||||
console.log('加载收藏列表,isAuthenticated=', isAuthenticated)
|
||||
if (!isAuthenticated) {
|
||||
setHasMore(false)
|
||||
newItems = []
|
||||
|
|
@ -160,7 +158,10 @@ const Index = observer(function Index() {
|
|||
|
||||
/** ================= tab 切换(抽象后的重点) ================= */
|
||||
|
||||
const changeTab = useCallback((tab: ActiveTab) => {
|
||||
const changeTab = useCallback(
|
||||
(tab: ActiveTab) => {
|
||||
// 重置加载状态,确保新的tab切换不会被旧的加载状态阻挡
|
||||
loadingRef.current = false
|
||||
queryRef.current = {
|
||||
...queryRef.current,
|
||||
tab,
|
||||
|
|
@ -169,7 +170,9 @@ const Index = observer(function Index() {
|
|||
setHasMore(true)
|
||||
firstLoadDoneRef.current = false
|
||||
fetchList('init')
|
||||
}, [])
|
||||
},
|
||||
[isAuthenticated],
|
||||
)
|
||||
|
||||
/** ================= 搜索 ================= */
|
||||
|
||||
|
|
|
|||
|
|
@ -282,8 +282,14 @@ class BleManager {
|
|||
this.setError(null)
|
||||
console.log('Starting scan...')
|
||||
const hasPerms = await this.requestBluetoothPermissions()
|
||||
if (!hasPerms) return
|
||||
console.log('Bluetooth permissions:', hasPerms)
|
||||
if (!hasPerms) {
|
||||
console.log('Permissions denied, stopping scan')
|
||||
bleStore.setState((prev) => ({ ...prev, isScanning: false }))
|
||||
return
|
||||
}
|
||||
|
||||
console.log('Setting isScanning to true')
|
||||
bleStore.setState((prev) => ({ ...prev, isScanning: true, discoveredDevices: [] }))
|
||||
|
||||
try {
|
||||
|
|
@ -320,6 +326,7 @@ class BleManager {
|
|||
console.warn('Failed to check connected devices', e)
|
||||
}
|
||||
|
||||
console.log('Starting BLE scan with service UUID:', BLE_UUIDS.SERVICE)
|
||||
await this.bleClient.startScan(
|
||||
[BLE_UUIDS.SERVICE],
|
||||
{ scanMode: ScanMode.Balanced, allowDuplicates: false },
|
||||
|
|
@ -337,7 +344,9 @@ class BleManager {
|
|||
this.queueDevice(device)
|
||||
},
|
||||
)
|
||||
console.log('BLE scan started successfully')
|
||||
} catch (e: any) {
|
||||
console.error('Start scan error:', e)
|
||||
this.setError(`Start scan failed: ${e.message}`)
|
||||
bleStore.setState((prev) => ({ ...prev, isScanning: false, discoveredDevices: [] }))
|
||||
Alert.alert(
|
||||
|
|
|
|||
|
|
@ -51,35 +51,25 @@ export class BleProtocolService {
|
|||
this.clearFragments(deviceId)
|
||||
|
||||
try {
|
||||
console.log('Initializing BLE protocol service for device:', deviceId)
|
||||
|
||||
this.subscription = await this.client.monitor(
|
||||
deviceId,
|
||||
BLE_UUIDS.SERVICE,
|
||||
BLE_UUIDS.READ_CHARACTERISTIC,
|
||||
(error, value) => {
|
||||
if (error) {
|
||||
// ✅ 修复:增强错误处理,避免崩溃
|
||||
const errorMsg = error.message || 'Unknown monitor error'
|
||||
|
||||
// 忽略预期的断开连接错误
|
||||
if (this.isExpectedDisconnectionError(error)) {
|
||||
console.debug('Device disconnected during monitoring:', errorMsg)
|
||||
// Check for known native crash error and ignore/log as debug
|
||||
if (
|
||||
error.errorCode === 0 &&
|
||||
error.message.includes('Unknown error') &&
|
||||
error.reason?.includes('PromiseImpl.reject')
|
||||
) {
|
||||
console.debug('Ignored native monitor error', error)
|
||||
return
|
||||
}
|
||||
|
||||
// 忽略已知的原生崩溃错误
|
||||
if (this.isKnownNativeCrashError(error)) {
|
||||
console.debug('Ignored known native monitor error:', errorMsg)
|
||||
console.warn('Monitor error', error)
|
||||
return
|
||||
}
|
||||
|
||||
console.warn('BLE monitor error:', errorMsg)
|
||||
return
|
||||
}
|
||||
|
||||
if (value) {
|
||||
try {
|
||||
const buffer = Buffer.from(value, 'base64')
|
||||
const hexString =
|
||||
buffer
|
||||
|
|
@ -90,16 +80,11 @@ export class BleProtocolService {
|
|||
|
||||
console.log(`[BleProtocol] Received ${buffer.byteLength} bytes:`, hexString)
|
||||
this.handleRawData(deviceId, buffer)
|
||||
} catch (parseError: any) {
|
||||
console.warn('Failed to parse received data:', parseError.message)
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
console.log('BLE protocol service initialized successfully')
|
||||
} catch (error: any) {
|
||||
console.error('Failed to initialize protocol service:', error.message)
|
||||
} catch (error) {
|
||||
console.error('Failed to initialize protocol service:', error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
|
@ -107,24 +92,14 @@ export class BleProtocolService {
|
|||
public disconnect() {
|
||||
if (this.subscription) {
|
||||
try {
|
||||
console.log('Cleaning up BLE protocol subscription...')
|
||||
this.subscription.remove()
|
||||
console.log('BLE protocol subscription removed successfully')
|
||||
} catch (e: any) {
|
||||
// ✅ 修复:安全处理订阅清理错误,避免崩溃
|
||||
const errorMsg = e?.message || String(e)
|
||||
console.debug('Subscription cleanup completed with warning:', errorMsg)
|
||||
} finally {
|
||||
// ✅ 确保订阅引用被清理
|
||||
} catch (e) {
|
||||
console.warn('Failed to remove subscription', e)
|
||||
}
|
||||
this.subscription = null
|
||||
}
|
||||
}
|
||||
|
||||
// ✅ 清理分片缓存
|
||||
this.fragments.clear()
|
||||
console.log('BLE protocol service disconnected')
|
||||
}
|
||||
|
||||
private handleRawData(deviceId: string, data: Buffer) {
|
||||
const frame = ProtocolManager.parseFrame(data.buffer)
|
||||
if (!frame) return
|
||||
|
|
@ -234,28 +209,4 @@ export class BleProtocolService {
|
|||
// console.debug("Wrote frame", result);
|
||||
}
|
||||
}
|
||||
|
||||
private isExpectedDisconnectionError(error: any): boolean {
|
||||
const message = error?.message?.toLowerCase() || ''
|
||||
const reason = error?.reason?.toLowerCase() || ''
|
||||
|
||||
return (
|
||||
message.includes('disconnect') ||
|
||||
message.includes('gatt_conn_terminate') ||
|
||||
message.includes('connection terminated') ||
|
||||
reason.includes('disconnect') ||
|
||||
error?.errorCode === 19
|
||||
) // GATT_CONN_TERMINATE_PEER_USER
|
||||
}
|
||||
|
||||
private isKnownNativeCrashError(error: any): boolean {
|
||||
const message = error?.message || ''
|
||||
const reason = error?.reason || ''
|
||||
|
||||
return (
|
||||
(error.errorCode === 0 && message.includes('Unknown error') && reason?.includes('PromiseImpl.reject')) ||
|
||||
message.includes('Parameter specified as non-null is null') ||
|
||||
reason?.includes('SafePromise.reject')
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue