mirror of
https://github.com/selfxyz/self.git
synced 2026-04-05 03:00:53 -04:00
feat: improve mixpanel flush strategy (#960)
* feat: improve mixpanel flush strategy * fixes * fix build * update lock * refactor methods * conslidate calls * update package and lock
This commit is contained in:
@@ -2,6 +2,10 @@
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
// NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE.
|
||||
|
||||
import { AppState, type AppStateStatus } from 'react-native';
|
||||
import { NativeModules } from 'react-native';
|
||||
import { ENABLE_DEBUG_LOGS, MIXPANEL_NFC_PROJECT_TOKEN } from '@env';
|
||||
import NetInfo from '@react-native-community/netinfo';
|
||||
import type { JsonMap, JsonValue } from '@segment/analytics-react-native';
|
||||
|
||||
import { TrackEventParams } from '@selfxyz/mobile-sdk-alpha';
|
||||
@@ -10,6 +14,15 @@ import { createSegmentClient } from '@/Segment';
|
||||
|
||||
const segmentClient = createSegmentClient();
|
||||
|
||||
// --- Analytics flush strategy ---
|
||||
let mixpanelConfigured = false;
|
||||
let eventCount = 0;
|
||||
let isConnected = true;
|
||||
const eventQueue: Array<{
|
||||
name: string;
|
||||
properties?: Record<string, unknown>;
|
||||
}> = [];
|
||||
|
||||
function coerceToJsonValue(
|
||||
value: unknown,
|
||||
seen = new WeakSet(),
|
||||
@@ -136,3 +149,101 @@ const analytics = () => {
|
||||
};
|
||||
|
||||
export default analytics;
|
||||
|
||||
/**
|
||||
* Cleanup function to clear event queues
|
||||
*/
|
||||
export const cleanupAnalytics = () => {
|
||||
eventQueue.length = 0;
|
||||
eventCount = 0;
|
||||
};
|
||||
|
||||
const setupFlushPolicies = () => {
|
||||
AppState.addEventListener('change', (state: AppStateStatus) => {
|
||||
if (state === 'background' || state === 'active') {
|
||||
flushMixpanelEvents();
|
||||
}
|
||||
});
|
||||
|
||||
NetInfo.addEventListener(state => {
|
||||
isConnected = state.isConnected ?? true;
|
||||
if (isConnected) {
|
||||
flushMixpanelEvents();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const flushMixpanelEvents = () => {
|
||||
if (!MIXPANEL_NFC_PROJECT_TOKEN) return;
|
||||
try {
|
||||
if (__DEV__) console.log('[Mixpanel] flush');
|
||||
// Send any queued events before flushing
|
||||
while (eventQueue.length > 0) {
|
||||
const evt = eventQueue.shift()!;
|
||||
NativeModules.PassportReader?.trackEvent?.(evt.name, evt.properties);
|
||||
}
|
||||
NativeModules.PassportReader?.flush?.();
|
||||
eventCount = 0;
|
||||
} catch (err) {
|
||||
if (__DEV__) console.warn('Mixpanel flush failed', err);
|
||||
// re-queue on failure
|
||||
if (typeof err !== 'undefined') {
|
||||
// no-op, events are already queued if failure happened before flush
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// --- Mixpanel NFC Analytics ---
|
||||
export const configureNfcAnalytics = () => {
|
||||
if (!MIXPANEL_NFC_PROJECT_TOKEN || mixpanelConfigured) return;
|
||||
const enableDebugLogs = JSON.parse(String(ENABLE_DEBUG_LOGS));
|
||||
NativeModules.PassportReader.configure(
|
||||
MIXPANEL_NFC_PROJECT_TOKEN,
|
||||
enableDebugLogs,
|
||||
{
|
||||
flushInterval: 20,
|
||||
flushCount: 5,
|
||||
flushOnBackground: true,
|
||||
flushOnForeground: true,
|
||||
flushOnNetworkChange: true,
|
||||
},
|
||||
);
|
||||
setupFlushPolicies();
|
||||
mixpanelConfigured = true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Consolidated analytics flush function that flushes both Segment and Mixpanel events
|
||||
* This should be called when you want to ensure all analytics events are sent immediately
|
||||
*/
|
||||
export const flushAllAnalytics = () => {
|
||||
// Flush Segment analytics
|
||||
const { flush: flushAnalytics } = analytics();
|
||||
flushAnalytics();
|
||||
|
||||
// Flush Mixpanel events
|
||||
flushMixpanelEvents();
|
||||
};
|
||||
|
||||
export const trackNfcEvent = (
|
||||
name: string,
|
||||
properties?: Record<string, unknown>,
|
||||
) => {
|
||||
if (!MIXPANEL_NFC_PROJECT_TOKEN) return;
|
||||
if (!mixpanelConfigured) configureNfcAnalytics();
|
||||
|
||||
if (!isConnected) {
|
||||
eventQueue.push({ name, properties });
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
NativeModules.PassportReader?.trackEvent?.(name, properties);
|
||||
eventCount++;
|
||||
if (eventCount >= 5) {
|
||||
flushMixpanelEvents();
|
||||
}
|
||||
} catch (err) {
|
||||
eventQueue.push({ name, properties });
|
||||
}
|
||||
};
|
||||
|
||||
@@ -2,14 +2,14 @@
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
// NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE.
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
import { Buffer } from 'buffer';
|
||||
import { NativeModules, Platform } from 'react-native';
|
||||
import PassportReader from 'react-native-passport-reader';
|
||||
import { ENABLE_DEBUG_LOGS, MIXPANEL_NFC_PROJECT_TOKEN } from '@env';
|
||||
import { reset, scan as scanDocument } from 'react-native-passport-reader';
|
||||
|
||||
import type { PassportData } from '@selfxyz/common/types';
|
||||
|
||||
import { configureNfcAnalytics } from '@/utils/analytics';
|
||||
|
||||
interface AndroidScanResponse {
|
||||
mrz: string;
|
||||
eContent: string;
|
||||
@@ -43,9 +43,17 @@ export const parseScanResponse = (response: unknown) => {
|
||||
: handleResponseIOS(response);
|
||||
};
|
||||
|
||||
export const scan = async (inputs: Inputs) => {
|
||||
configureNfcAnalytics();
|
||||
|
||||
return Platform.OS === 'android'
|
||||
? await scanAndroid(inputs)
|
||||
: await scanIOS(inputs);
|
||||
};
|
||||
|
||||
const scanAndroid = async (inputs: Inputs) => {
|
||||
PassportReader.reset();
|
||||
return await PassportReader.scan({
|
||||
reset();
|
||||
return await scanDocument({
|
||||
documentNumber: inputs.passportNumber,
|
||||
dateOfBirth: inputs.dateOfBirth,
|
||||
dateOfExpiry: inputs.dateOfExpiry,
|
||||
@@ -55,7 +63,7 @@ const scanAndroid = async (inputs: Inputs) => {
|
||||
};
|
||||
|
||||
const scanIOS = async (inputs: Inputs) => {
|
||||
return await NativeModules.PassportReader.scanPassport(
|
||||
return await NativeModules.PassportReader.scanDocument(
|
||||
inputs.passportNumber,
|
||||
inputs.dateOfBirth,
|
||||
inputs.dateOfExpiry,
|
||||
@@ -68,23 +76,6 @@ const scanIOS = async (inputs: Inputs) => {
|
||||
);
|
||||
};
|
||||
|
||||
export const scan = async (inputs: Inputs) => {
|
||||
if (MIXPANEL_NFC_PROJECT_TOKEN) {
|
||||
if (Platform.OS === 'ios') {
|
||||
const enableDebugLogs = JSON.parse(String(ENABLE_DEBUG_LOGS));
|
||||
NativeModules.PassportReader.configure(
|
||||
MIXPANEL_NFC_PROJECT_TOKEN,
|
||||
enableDebugLogs,
|
||||
);
|
||||
} else {
|
||||
}
|
||||
}
|
||||
|
||||
return Platform.OS === 'android'
|
||||
? await scanAndroid(inputs)
|
||||
: await scanIOS(inputs);
|
||||
};
|
||||
|
||||
const handleResponseIOS = (response: unknown) => {
|
||||
const parsed = JSON.parse(String(response));
|
||||
const dgHashesObj = JSON.parse(parsed?.dataGroupHashes);
|
||||
|
||||
Reference in New Issue
Block a user