Skip to content

Commit 9150ddc

Browse files
committed
RU-T47 PR#221 fixes
1 parent 885755b commit 9150ddc

File tree

9 files changed

+415
-139
lines changed

9 files changed

+415
-139
lines changed

package.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,6 @@
109109
"app-icon-badge": "^0.1.2",
110110
"axios": "~1.12.0",
111111
"babel-plugin-module-resolver": "^5.0.2",
112-
"babel-plugin-transform-import-meta": "^2.3.3",
113112
"buffer": "^6.0.3",
114113
"countly-sdk-react-native-bridge": "25.4.1",
115114
"date-fns": "^4.1.0",
@@ -191,8 +190,9 @@
191190
"@types/mapbox-gl": "3.4.1",
192191
"@types/react": "~19.0.10",
193192
"@types/react-native-base64": "~0.2.2",
194-
"@typescript-eslint/eslint-plugin": "~7.18.0",
195-
"@typescript-eslint/parser": "~7.18.0",
193+
"@typescript-eslint/eslint-plugin": "^8.0.0",
194+
"@typescript-eslint/parser": "^8.0.0",
195+
"babel-plugin-transform-import-meta": "^2.3.3",
196196
"babel-jest": "~30.0.0",
197197
"concurrently": "9.2.1",
198198
"cross-env": "~7.0.3",
@@ -201,7 +201,7 @@
201201
"electron-builder": "26.4.0",
202202
"electron-squirrel-startup": "^1.0.1",
203203
"eslint": "~8.57.0",
204-
"eslint-config-expo": "~7.1.2",
204+
"eslint-config-expo": "~9.2.0",
205205
"eslint-config-prettier": "~9.1.0",
206206
"eslint-import-resolver-typescript": "~3.6.3",
207207
"eslint-plugin-i18n-json": "~4.0.0",
@@ -226,7 +226,7 @@
226226
"tailwindcss": "3.4.4",
227227
"ts-jest": "~29.1.2",
228228
"ts-node": "~10.9.2",
229-
"typescript": "~5.5.4",
229+
"typescript": "5.8.x",
230230
"wait-on": "9.0.3"
231231
},
232232
"repository": {

plugins/withInCallAudioModule.js

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,9 +115,18 @@ class InCallAudioModule(reactContext: ReactApplicationContext) : ReactContextBas
115115
when (normalizedRoute) {
116116
"bluetooth" -> {
117117
audioManager.isSpeakerphoneOn = false
118+
if (!audioManager.isBluetoothScoAvailableOffCall) {
119+
audioManager.isBluetoothScoOn = false
120+
promise.reject("BLUETOOTH_SCO_UNAVAILABLE", "Bluetooth SCO is not available off call")
121+
return
122+
}
123+
124+
audioManager.startBluetoothSco()
118125
audioManager.isBluetoothScoOn = true
119-
if (audioManager.isBluetoothScoAvailableOffCall) {
120-
audioManager.startBluetoothSco()
126+
127+
if (!audioManager.isBluetoothScoOn) {
128+
promise.reject("BLUETOOTH_SCO_START_FAILED", "Failed to start Bluetooth SCO")
129+
return
121130
}
122131
}
123132

src/components/settings/bluetooth-device-selection-bottom-sheet.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ export function BluetoothDeviceSelectionBottomSheet({ isOpen, onClose }: Bluetoo
4444
setHasScanned(true);
4545
await bluetoothAudioService.startScanning(10000); // 10 second scan
4646
} catch (error) {
47-
setHasScanned(false); // Reset scan state on error
4847
logger.error({
4948
message: 'Failed to start Bluetooth scan',
5049
context: { error },

src/lib/utils.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,14 +63,14 @@ export function invertColor(hex: string, bw: boolean): string {
6363

6464
export function padZero(str: string, len: number): string {
6565
len = len || 2;
66-
var zeros = new Array(len).join('0');
66+
const zeros = new Array(len).join('0');
6767
return (zeros + str).slice(-len);
6868
}
6969

7070
export function uuidv4() {
7171
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
72-
var r = (Math.random() * 16) | 0,
73-
v = c === 'x' ? r : (r & 0x3) | 0x8;
72+
const r = (Math.random() * 16) | 0;
73+
const v = c === 'x' ? r : (r & 0x3) | 0x8;
7474
return v.toString(16);
7575
});
7676
}

src/services/__tests__/bluetooth-audio.service.test.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,4 +244,42 @@ describe('BluetoothAudioService Refactoring', () => {
244244
expect(legacyStore.setMicrophoneEnabled).toHaveBeenCalledWith(true);
245245
});
246246
});
247+
248+
describe('Capability parsing strictness', () => {
249+
it('should reject explicit falsy read capability values', () => {
250+
const service = bluetoothAudioService as any;
251+
252+
expect(service.hasReadCapability({ Read: false })).toBe(false);
253+
expect(service.hasReadCapability({ read: 0 })).toBe(false);
254+
expect(service.hasReadCapability({ read: 'false' })).toBe(false);
255+
});
256+
257+
it('should accept explicit truthy read capability values', () => {
258+
const service = bluetoothAudioService as any;
259+
260+
expect(service.hasReadCapability({ Read: true })).toBe(true);
261+
expect(service.hasReadCapability({ read: 1 })).toBe(true);
262+
expect(service.hasReadCapability({ read: 'true' })).toBe(true);
263+
expect(service.hasReadCapability({ read: '1' })).toBe(true);
264+
expect(service.hasReadCapability({ read: 'read' })).toBe(true);
265+
});
266+
267+
it('should reject explicit falsy notify/read capability values', () => {
268+
const service = bluetoothAudioService as any;
269+
270+
expect(service.hasNotificationOrReadCapability({ Notify: false })).toBe(false);
271+
expect(service.hasNotificationOrReadCapability({ indicate: 0 })).toBe(false);
272+
expect(service.hasNotificationOrReadCapability({ read: 'false' })).toBe(false);
273+
});
274+
275+
it('should accept explicit truthy notify/read capability values', () => {
276+
const service = bluetoothAudioService as any;
277+
278+
expect(service.hasNotificationOrReadCapability({ notify: true })).toBe(true);
279+
expect(service.hasNotificationOrReadCapability({ indicate: 1 })).toBe(true);
280+
expect(service.hasNotificationOrReadCapability({ read: 'true' })).toBe(true);
281+
expect(service.hasNotificationOrReadCapability({ read: '1' })).toBe(true);
282+
expect(service.hasNotificationOrReadCapability({ notify: 'notify' })).toBe(true);
283+
});
284+
});
247285
});

src/services/app-lifecycle.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { AppState, type AppStateStatus } from 'react-native';
22

3-
import { useLogger } from '@/lib/logging';
3+
import { logger } from '@/lib/logging';
44
import { useAppLifecycleStore } from '@/stores/app/app-lifecycle';
55

66
class AppLifecycleService {
@@ -25,7 +25,7 @@ class AppLifecycleService {
2525
private handleAppStateChange = (nextAppState: AppStateStatus): void => {
2626
const currentState = useAppLifecycleStore.getState().appState;
2727

28-
useLogger().info({
28+
logger.info({
2929
message: 'App state changed',
3030
context: {
3131
from: currentState,

src/services/bluetooth-audio.service.ts

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -187,34 +187,40 @@ class BluetoothAudioService {
187187
}
188188
}
189189

190+
private addEventListener(listener: { remove: () => void }): void {
191+
if (!this.eventListeners.includes(listener)) {
192+
this.eventListeners.push(listener);
193+
}
194+
}
195+
196+
private removeEventListener(listener: { remove: () => void } | null): void {
197+
if (!listener) {
198+
return;
199+
}
200+
201+
this.eventListeners = this.eventListeners.filter((registeredListener) => registeredListener !== listener);
202+
}
203+
190204
private setupEventListeners(): void {
191205
// Bluetooth state change listener
192-
//const stateListener = DeviceEventEmitter.addListener('BleManagerDidUpdateState', this.handleBluetoothStateChange.bind(this));
193206
const stateListener = BleManager.onDidUpdateState(this.handleBluetoothStateChange.bind(this));
194-
this.eventListeners.push(stateListener);
207+
this.addEventListener(stateListener);
195208

196209
// Device disconnection listener
197-
//const disconnectListener = DeviceEventEmitter.addListener('BleManagerDisconnectPeripheral', this.handleDeviceDisconnected.bind(this));
198210
const disconnectListener = BleManager.onDisconnectPeripheral(this.handleDeviceDisconnected.bind(this));
199-
this.eventListeners.push(disconnectListener);
211+
this.addEventListener(disconnectListener);
200212

201213
// Device discovered listener
202-
//const discoverListener = DeviceEventEmitter.addListener('BleManagerDiscoverPeripheral', this.handleDeviceDiscovered.bind(this));
203214
const discoverListener = BleManager.onDiscoverPeripheral(this.handleDeviceDiscovered.bind(this));
204-
this.eventListeners.push(discoverListener);
215+
this.addEventListener(discoverListener);
205216

206217
// Characteristic value update listener
207-
//const valueUpdateListener = DeviceEventEmitter.addListener('BleManagerDidUpdateValueForCharacteristic', this.handleCharacteristicValueUpdate.bind(this));
208218
const valueUpdateListener = BleManager.onDidUpdateValueForCharacteristic(this.handleCharacteristicValueUpdate.bind(this));
209-
this.eventListeners.push(valueUpdateListener);
210-
211-
const legacyValueUpdateListener = DeviceEventEmitter.addListener('BleManagerDidUpdateValueForCharacteristic', this.handleCharacteristicValueUpdate.bind(this));
212-
this.eventListeners.push(legacyValueUpdateListener);
219+
this.addEventListener(valueUpdateListener);
213220

214221
// Stop scan listener
215-
//const stopScanListener = DeviceEventEmitter.addListener('BleManagerStopScan', this.handleScanStopped.bind(this));
216222
const stopScanListener = BleManager.onStopScan(this.handleScanStopped.bind(this));
217-
this.eventListeners.push(stopScanListener);
223+
this.addEventListener(stopScanListener);
218224
}
219225

220226
private handleBluetoothStateChange(args: { state: BleState }): void {
@@ -1126,11 +1132,12 @@ class BluetoothAudioService {
11261132
}
11271133

11281134
this.mediaButtonEventListener = DeviceEventEmitter.addListener('onMediaButtonEvent', this.handleMediaButtonFallbackEvent.bind(this));
1129-
this.eventListeners.push(this.mediaButtonEventListener);
1135+
this.addEventListener(this.mediaButtonEventListener);
11301136
}
11311137

11321138
private stopMediaButtonFallbackMonitoring(): void {
11331139
if (this.mediaButtonEventListener) {
1140+
this.removeEventListener(this.mediaButtonEventListener);
11341141
this.mediaButtonEventListener.remove();
11351142
this.mediaButtonEventListener = null;
11361143
}
@@ -1522,7 +1529,7 @@ class BluetoothAudioService {
15221529
return false;
15231530
}
15241531

1525-
return value === true || value === 1 || normalizedValue === normalizedKey || normalizedValue === 'true' || normalizedValue === '1' || normalizedValue.length > 0;
1532+
return value === true || value === 1 || normalizedValue === normalizedKey || normalizedValue === 'true' || normalizedValue === '1';
15261533
});
15271534
}
15281535

@@ -1558,7 +1565,7 @@ class BluetoothAudioService {
15581565
return false;
15591566
}
15601567

1561-
return value === true || value === 1 || normalizedValue === normalizedKey || normalizedValue === 'true' || normalizedValue === '1' || normalizedValue.length > 0;
1568+
return value === true || value === 1 || normalizedValue === normalizedKey || normalizedValue === 'true' || normalizedValue === '1';
15621569
});
15631570
}
15641571

src/services/callkeep.service.android.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,6 @@ export class CallKeepService {
323323
}
324324

325325
if (now < this.muteEventStormEndTime) {
326-
this.muteEventStormEndTime = now + 800;
327326
logger.debug({
328327
message: 'Ignored CallKeep mute state change (storm cooldown, Android)',
329328
context: { muted, callUUID, stormEndsAt: this.muteEventStormEndTime },

0 commit comments

Comments
 (0)