From e08061fa21f5bcbbbb334158a90c9e31acb73b9b Mon Sep 17 00:00:00 2001 From: km2025 Date: Mon, 12 Jan 2026 13:37:54 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=9B=B4=E6=96=B0=E5=9B=BE=E7=89=87?= =?UTF-8?q?=E9=80=89=E6=8B=A9=E5=99=A8=E9=80=BB=E8=BE=91=EF=BC=8C=E5=A2=9E?= =?UTF-8?q?=E5=BC=BA=20BLE=20=E7=9B=91=E6=8E=A7=E9=94=99=E8=AF=AF=E5=A4=84?= =?UTF-8?q?=E7=90=86=EF=BC=9B=E6=9B=B4=E6=96=B0=E5=BA=94=E7=94=A8=E7=89=88?= =?UTF-8?q?=E6=9C=AC=E5=8F=B7=EF=BC=9B=E6=B7=BB=E5=8A=A0=20Figma=20?= =?UTF-8?q?=E6=9C=8D=E5=8A=A1=E5=99=A8=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscode/mcp.json | 9 +++ @share/apis/imgPicker.ts | 8 ++- app.constants.js | 2 +- app/(tabs)/_layout.tsx | 2 +- app/(tabs)/index.tsx | 29 +++++----- ble/managers/bleManager.ts | 11 +++- ble/services/BleProtocolService.ts | 93 +++++++----------------------- 7 files changed, 65 insertions(+), 89 deletions(-) create mode 100644 .vscode/mcp.json diff --git a/.vscode/mcp.json b/.vscode/mcp.json new file mode 100644 index 0000000..c992e3a --- /dev/null +++ b/.vscode/mcp.json @@ -0,0 +1,9 @@ +{ + "servers": { + "Figma": { + "url": "https://mcp.figma.com/mcp", + "type": "http" + } + }, + "inputs": [] +} \ No newline at end of file diff --git a/@share/apis/imgPicker.ts b/@share/apis/imgPicker.ts index 15ce5b9..856fe1d 100644 --- a/@share/apis/imgPicker.ts +++ b/@share/apis/imgPicker.ts @@ -1,9 +1,13 @@ import * as ImagePicker from 'expo-image-picker' + import Toast from '../components/Toast' // 定义图片项类型 -type PickerBaseParams = Omit & { +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, diff --git a/app.constants.js b/app.constants.js index b46c19a..0155184 100644 --- a/app.constants.js +++ b/app.constants.js @@ -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' diff --git a/app/(tabs)/_layout.tsx b/app/(tabs)/_layout.tsx index a6d8cee..1224c29 100644 --- a/app/(tabs)/_layout.tsx +++ b/app/(tabs)/_layout.tsx @@ -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) { diff --git a/app/(tabs)/index.tsx b/app/(tabs)/index.tsx index 903104b..784344c 100644 --- a/app/(tabs)/index.tsx +++ b/app/(tabs)/index.tsx @@ -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('') @@ -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,16 +158,21 @@ const Index = observer(function Index() { /** ================= tab 切换(抽象后的重点) ================= */ - const changeTab = useCallback((tab: ActiveTab) => { - queryRef.current = { - ...queryRef.current, - tab, - page: 1, - } - setHasMore(true) - firstLoadDoneRef.current = false - fetchList('init') - }, []) + const changeTab = useCallback( + (tab: ActiveTab) => { + // 重置加载状态,确保新的tab切换不会被旧的加载状态阻挡 + loadingRef.current = false + queryRef.current = { + ...queryRef.current, + tab, + page: 1, + } + setHasMore(true) + firstLoadDoneRef.current = false + fetchList('init') + }, + [isAuthenticated], + ) /** ================= 搜索 ================= */ diff --git a/ble/managers/bleManager.ts b/ble/managers/bleManager.ts index 514a506..95ca799 100644 --- a/ble/managers/bleManager.ts +++ b/ble/managers/bleManager.ts @@ -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( diff --git a/ble/services/BleProtocolService.ts b/ble/services/BleProtocolService.ts index 962d0c1..ac3fad3 100644 --- a/ble/services/BleProtocolService.ts +++ b/ble/services/BleProtocolService.ts @@ -51,55 +51,40 @@ 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) - return - } - - console.warn('BLE monitor error:', errorMsg) + console.warn('Monitor error', error) return } - if (value) { - try { - const buffer = Buffer.from(value, 'base64') - const hexString = - buffer - .toString('hex') - .match(/.{1,2}/g) - ?.join(' ') - .toUpperCase() || '' + const buffer = Buffer.from(value, 'base64') + const hexString = + buffer + .toString('hex') + .match(/.{1,2}/g) + ?.join(' ') + .toUpperCase() || '' - 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(`[BleProtocol] Received ${buffer.byteLength} bytes:`, hexString) + this.handleRawData(deviceId, buffer) } }, ) - - 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,22 +92,12 @@ 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 { - // ✅ 确保订阅引用被清理 - this.subscription = null + } 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) { @@ -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') - ) - } }