Skip to content

Commit a01f940

Browse files
committed
Only register push when needed
1 parent 5ea382b commit a01f940

5 files changed

Lines changed: 109 additions & 14 deletions

File tree

src/lib/rpc.js

Lines changed: 56 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import {
22
saveRoomMessageAndUpdate,
33
setRoomMessages,
4+
syncRoomMessages,
45
setLatestRoomMessages,
56
} from '@/services/bare';
6-
import { getCurrentRoom, useGlobalStore } from '@/services/zustand';
7+
import { getCurrentRoom, useGlobalStore, usePreferencesStore } from '@/services/zustand';
8+
import { getDeviceId } from '../services/pushnotifications';
79
import { sleep } from '@/utils';
810
import Toast from 'react-native-toast-message';
911
import { Peers } from 'lib/connections';
@@ -55,6 +57,7 @@ export class Bridge {
5557
this.pushRegistrationTimer = null;
5658
this.pushRegistrationDebouncePromise = null;
5759
this.pushRegistrationDebounceMs = 750;
60+
this.pushRegistrationDone = false;
5861
this.rpc = new RPC(IPC, (req, error) => {
5962
const data = this.parse(b4a.toString(req.data));
6063
if (!data) {
@@ -114,11 +117,13 @@ export class Bridge {
114117

115118
get_pending_push_registrations(room_keys = []) {
116119
const all_room_keys = [...new Set([...this.get_room_keys_from_store(), ...room_keys])];
117-
const pending_room_keys = all_room_keys.filter((room_key) => !this.registeredRoomKeys.has(room_key));
120+
const prefs = usePreferencesStore.getState().preferences;
121+
const prefs_registered = prefs?.registeredRoomKeys || [];
122+
const pending_room_keys = all_room_keys.filter((room_key) => !this.registeredRoomKeys.has(room_key) && !prefs_registered.includes(room_key));
118123

119124
return {
120-
include_device_push: !this.basePushRegistered,
121-
include_call_push: !this.callPushRegistered,
125+
include_device_push: !this.basePushRegistered && !prefs?.basePushVerified,
126+
include_call_push: !this.callPushRegistered && !prefs?.basePushVerified,
122127
pending_room_keys,
123128
};
124129
}
@@ -161,8 +166,13 @@ export class Bridge {
161166
}
162167

163168
const sent = await this.send_push_registration(push_registration_batch);
169+
console.log('[rpc.js] Push registration sent:', sent);
164170
if (sent && sent.success === true) {
165171
this.mark_push_registrations_sent(state);
172+
const currentFirebaseToken = getDeviceId();
173+
if (currentFirebaseToken) {
174+
usePreferencesStore.getState().setLastRegisteredDeviceToken(currentFirebaseToken);
175+
}
166176
}
167177
return sent;
168178
}
@@ -176,6 +186,24 @@ export class Bridge {
176186
async sync_push_registrations(room_keys = []) {
177187
this.collect_pending_push_room_keys(room_keys);
178188

189+
const prefs = usePreferencesStore.getState().preferences;
190+
const currentFirebaseToken = getDeviceId();
191+
const tokenIsSame = currentFirebaseToken && currentFirebaseToken === prefs?.lastRegisteredDeviceToken;
192+
193+
if (!tokenIsSame && currentFirebaseToken) {
194+
usePreferencesStore.getState().clearRegisteredRoomKeys();
195+
}
196+
197+
const state = this.get_pending_push_registrations([...this.pendingPushRoomKeys]);
198+
199+
console.log('[rpc.js] Push registration rooms number:' + state.pending_room_keys?.length);
200+
console.log('[rpc.js] Push registration token is same:' + tokenIsSame);
201+
202+
if (state.pending_room_keys.length === 0 && tokenIsSame && !state.include_device_push && !state.include_call_push) {
203+
this.pendingPushRoomKeys.clear();
204+
return { success: true, skipped: true };
205+
}
206+
179207
if (!useGlobalStore.getState().huginNode.connected) {
180208
return null;
181209
}
@@ -231,12 +259,33 @@ export class Bridge {
231259
case 'hugin-node-connected':
232260
useGlobalStore.getState().setHuginNode({connected: true});
233261

262+
if (useGlobalStore.getState().appState !== 'active') {
263+
console.log('[rpc.js] App not active, skipping push registration sync');
264+
break;
265+
}
266+
267+
if (this.pushRegistrationDone) {
268+
console.log('[rpc.js] Push registration already done this run, skipping');
269+
break;
270+
}
271+
234272
if (useGlobalStore.getState().contacts.length === 0
235273
&& useGlobalStore.getState().rooms.length === 0) {
236274
console.log('[rpc.js] No contacts or rooms, skipping push registration sync')
237275
break;
238276
}
277+
278+
const prefs = usePreferencesStore.getState().preferences;
279+
const currentFirebaseToken = getDeviceId();
280+
if (currentFirebaseToken && currentFirebaseToken === prefs?.lastRegisteredDeviceToken) {
281+
console.log('[rpc.js] Push token has not changed since last registration, skipping');
282+
this.pushRegistrationDone = true;
283+
break;
284+
}
285+
239286
await this.sync_push_registrations();
287+
console.log('[rpc.js] Push registration sync completed');
288+
this.pushRegistrationDone = true;
240289
break;
241290
case 'hugin-node-disconnected':
242291
console.log('Hugin node disconnected!')
@@ -248,6 +297,7 @@ export class Bridge {
248297
break;
249298
case 'new-swarm':
250299
if (!json.beam && typeof json.key === 'string' && json.key.length > 0) {
300+
console.log('[rpc.js] New swarm started, syncing push registrations')
251301
await this.sync_push_registrations([json.key]);
252302
}
253303
break;
@@ -315,11 +365,7 @@ export class Bridge {
315365
case 'history-update':
316366
await sleep(500);
317367
if (getCurrentRoom() === json.key) {
318-
const currentState = useGlobalStore.getState();
319-
// This might need to be checked, may cause history sync not to show messages immediately
320-
if (!currentState.roomMessages || currentState.roomMessages.length === 0) {
321-
setRoomMessages(json.key, 0);
322-
}
368+
syncRoomMessages(json.key);
323369
if (json.history && !json.background) {
324370
Toast.show({
325371
type: 'success',
@@ -376,7 +422,7 @@ export class Bridge {
376422
WebRTC.signal(key, topic, address, data);
377423
break;
378424
case 'error-message':
379-
console.log('Error:', json.data);
425+
console.log('Error:', json);
380426
Toast.show({ text1: json.data?.message || 'Error', type: 'error' });
381427
break;
382428
case 'file-saved-to-downloads':

src/services/pushnotifications.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import { saveMessageToQueue, resetMessageQueue, getMessageQueue } from '../utils
2828
import VoipPushNotification from 'react-native-voip-push-notification';
2929
import { updateUser, useGlobalStore, usePreferencesStore, useUserStore } from './zustand';
3030
import { getRooms, initDB, messageExists, roomMessageExists, saveRoomMessage, addContact, saveMessage } from './bare/sqlite';
31-
import { Beam, decrypt_sealed_box, Nodes, Rooms } from 'lib/native';
31+
import { Beam, decrypt_sealed_box, Nodes, Rooms, sync_push_registrations } from 'lib/native';
3232
import { Connection } from './bare/globals';
3333
import { ConnectionStatus, User } from '../types/user';
3434
import { setLatestMessages, updateMessage } from './bare/contacts';
@@ -344,6 +344,13 @@ async function getEncryptionKey(): Promise<string | null> {
344344
const firebaseToken = await getToken(messaging);
345345
console.log('✅ Firebase Token:', firebaseToken);
346346
deviceId = firebaseToken;
347+
348+
const prefToken = usePreferencesStore.getState().preferences?.lastRegisteredDeviceToken;
349+
if (firebaseToken && firebaseToken !== prefToken) {
350+
console.log('🔄 Device token changed or not registered yet, triggering sync...');
351+
sync_push_registrations();
352+
}
353+
347354
return firebaseToken;
348355
} catch (err) {
349356
console.error('❌ Failed to get FCM token:', err);
@@ -390,6 +397,9 @@ let channelId;
390397
if (box?.type && box?.type == 'room') {
391398
console.log('🔔 Room message received!!');
392399
message = await decryptRoomMessage(box.box, box.timestamp);
400+
if (message && message.roomKey) {
401+
usePreferencesStore.getState().addRegisteredRoomKeys([message.roomKey]);
402+
}
393403

394404
if (await roomMessageExists(message.hash)) {
395405
console.log('🔕 Room message already exists, skipping synchronization.');
@@ -418,6 +428,9 @@ let channelId;
418428
const key = await getEncryptionKey();
419429
if (!key) return; // Cannot decrypt without key
420430
message = decryptMessage(box.box, box.t, key as string);
431+
if (message) {
432+
usePreferencesStore.getState().setBasePushVerified(true);
433+
}
421434

422435
console.log('🔔 Direct message received!!', message.from);
423436

@@ -497,6 +510,9 @@ let channelId;
497510
console.log('🔔 Room message received!!');
498511

499512
message = await decryptRoomMessage(box.box, box.timestamp);
513+
if (message && message.roomKey) {
514+
usePreferencesStore.getState().addRegisteredRoomKeys([message.roomKey]);
515+
}
500516

501517
if (await roomMessageExists(message.hash)) {
502518
console.log('🔕 Room message already exists, skipping notification.');
@@ -528,6 +544,9 @@ let channelId;
528544
const key = await getEncryptionKey();
529545

530546
message = decryptMessage(box.box, box.t, key);
547+
if (message) {
548+
usePreferencesStore.getState().setBasePushVerified(true);
549+
}
531550

532551
console.log('Displaying notification for message:', message);
533552

src/services/zustand/async-storage-stores.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,10 @@ interface PreferencesStore {
209209
setAuthMethod: (authMethod: AuthMethods | null) => void;
210210
setSkipBgRefreshWarning: (skip: boolean) => void;
211211
skipBgRefreshWarning: boolean;
212+
setLastRegisteredDeviceToken: (token: string) => void;
213+
addRegisteredRoomKeys: (keys: string[]) => void;
214+
clearRegisteredRoomKeys: () => void;
215+
setBasePushVerified: (verified: boolean) => void;
212216
}
213217

214218
export const usePreferencesStore = create<PreferencesStore>()(
@@ -226,6 +230,25 @@ export const usePreferencesStore = create<PreferencesStore>()(
226230
})),
227231
skipBgRefreshWarning: false,
228232
setSkipBgRefreshWarning: (skip) => set({ skipBgRefreshWarning: skip }),
233+
setLastRegisteredDeviceToken: (token: string) =>
234+
set((state) => ({
235+
preferences: { ...state.preferences, lastRegisteredDeviceToken: token },
236+
})),
237+
addRegisteredRoomKeys: (keys: string[]) =>
238+
set((state) => ({
239+
preferences: {
240+
...state.preferences,
241+
registeredRoomKeys: [...new Set([...(state.preferences.registeredRoomKeys || []), ...keys])],
242+
},
243+
})),
244+
clearRegisteredRoomKeys: () =>
245+
set((state) => ({
246+
preferences: { ...state.preferences, registeredRoomKeys: [], basePushVerified: false },
247+
})),
248+
setBasePushVerified: (verified: boolean) =>
249+
set((state) => ({
250+
preferences: { ...state.preferences, basePushVerified: verified },
251+
})),
229252
}),
230253
{
231254
merge: (persistedState: unknown, currentState: PreferencesStore) => {
@@ -236,6 +259,11 @@ export const usePreferencesStore = create<PreferencesStore>()(
236259
typedPersistedState?.preferences ?? defaultPreferences;
237260
const skipBgRefreshWarning =
238261
typedPersistedState?.skipBgRefreshWarning ?? false;
262+
const lastRegisteredDeviceToken =
263+
typedPersistedState?.preferences?.lastRegisteredDeviceToken;
264+
// Merge preferences with whatever was persisted plus any top-level things
265+
// Wait, preferences is already extracted above
266+
239267
return { ...currentState, preferences, skipBgRefreshWarning }
240268
},
241269
name: ASYNC_STORAGE_KEYS.PREFERENCES,

src/services/zustand/global-store.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { create } from 'zustand';
33
import { subscribeWithSelector } from 'zustand/middleware';
44

55
import type { Balance, Message, RemoteFile, Room, User, Contact, Call, HuginNode } from '@/types';
6-
import { AppStateStatus } from 'react-native';
6+
import { AppState, AppStateStatus } from 'react-native';
77

88
type GlobalStore = {
99
balance: Balance;
@@ -166,7 +166,7 @@ export const useGlobalStore = create<
166166
set((state) => ({
167167
fileDownloads: state.fileDownloads.filter((f) => f.hash !== hash),
168168
})),
169-
appState: 'inactive',
169+
appState: AppState.currentState || 'active',
170170
talkingUsers: {},
171171
setAppState: (appState) => set({appState}),
172172
setVoipPayload: (voipPayload) => set({ voipPayload }),

src/types/user.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ export interface Preferences {
1919
node: string;
2020
huginNodeMode?: 'automatic' | 'manual';
2121
huginNode?: string;
22-
22+
lastRegisteredDeviceToken?: string;
23+
registeredRoomKeys?: string[];
24+
basePushVerified?: boolean;
2325
}
2426

2527
export interface Payee {

0 commit comments

Comments
 (0)