mirror of
https://github.com/jjbrunton/Sauci.git
synced 2026-11-01 18:19:43 +00:00
Add streaks, scheduled releases, and notification settings
- Couple streaks with milestone notifications - Scheduled pack releases with admin UI - Notification preferences screen - Refactored profile settings screens - Partner activity notifications
This commit is contained in:
1 parent
12f312421b
commit
494ed17fe2
82 files changed
+4189
-725
No files matched your search
@@ -172,15 +172,27 @@ export function logScreenView(screenName: string, screenClass?: string) {
|
||||
}
|
||||
}
|
||||
|
||||
// Flush events (useful before app backgrounding)
|
||||
export function flush() {
|
||||
// Firebase Analytics batches and sends events automatically
|
||||
// No manual flush needed, but we keep the function for API compatibility
|
||||
if (__DEV__) console.log("[Analytics] Flush called (no-op for Firebase)");
|
||||
}
|
||||
|
||||
// Pre-defined event helpers for common actions
|
||||
export const Events = {
|
||||
// Flush events (useful before app backgrounding)
|
||||
export function flush() {
|
||||
// Firebase Analytics batches and sends events automatically
|
||||
// No manual flush needed, but we keep the function for API compatibility
|
||||
if (__DEV__) console.log("[Analytics] Flush called (no-op for Firebase)");
|
||||
}
|
||||
|
||||
function truncateParam(value: string, maxLength = 100) {
|
||||
if (value.length <= maxLength) return value;
|
||||
return value.slice(0, maxLength - 1) + "…";
|
||||
}
|
||||
|
||||
function safeParam(value: unknown, maxLength = 100): string {
|
||||
if (typeof value === "string") return truncateParam(value, maxLength);
|
||||
if (typeof value === "number" || typeof value === "boolean") return String(value);
|
||||
if (value instanceof Error) return truncateParam(value.message, maxLength);
|
||||
return value == null ? "" : truncateParam(String(value), maxLength);
|
||||
}
|
||||
|
||||
// Pre-defined event helpers for common actions
|
||||
export const Events = {
|
||||
// Auth events
|
||||
signUp: (method: string) => logEvent("sign_up", { method }),
|
||||
signIn: (method: string) => logEvent("login", { method }),
|
||||
@@ -210,13 +222,26 @@ export const Events = {
|
||||
messageSent: () => logEvent("message_sent"),
|
||||
mediaUploaded: () => logEvent("chat_media_uploaded"),
|
||||
|
||||
// Subscription events
|
||||
paywallShown: (source: string) => logEvent("paywall_shown", { source }),
|
||||
purchaseInitiated: (packageType: string) =>
|
||||
logEvent("purchase_initiated", { package_type: packageType }),
|
||||
purchaseCompleted: (packageType: string) =>
|
||||
logEvent("purchase", { package_type: packageType }),
|
||||
purchaseRestored: () => logEvent("purchase_restored"),
|
||||
// Subscription events
|
||||
paywallShown: (source: string) => logEvent("paywall_shown", { source }),
|
||||
paywallClosed: (source: string, reason: string) =>
|
||||
logEvent("paywall_closed", { source, reason }),
|
||||
purchaseInitiated: (packageType: string) =>
|
||||
logEvent("purchase_initiated", { package_type: packageType }),
|
||||
purchaseCancelled: (packageType: string, errorCode?: unknown) =>
|
||||
logEvent("purchase_cancelled", {
|
||||
package_type: packageType,
|
||||
error_code: safeParam(errorCode) || "unknown",
|
||||
}),
|
||||
purchaseFailed: (packageType: string, errorCode?: unknown, errorMessage?: unknown) =>
|
||||
logEvent("purchase_failed", {
|
||||
package_type: packageType,
|
||||
error_code: safeParam(errorCode) || "unknown",
|
||||
error_message: safeParam(errorMessage),
|
||||
}),
|
||||
purchaseCompleted: (packageType: string) =>
|
||||
logEvent("purchase", { package_type: packageType }),
|
||||
purchaseRestored: () => logEvent("purchase_restored"),
|
||||
|
||||
// Pack events
|
||||
packEnabled: (packId: string) => logEvent("pack_enabled", { pack_id: packId }),
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
import * as Notifications from 'expo-notifications';
|
||||
import { Platform } from 'react-native';
|
||||
|
||||
/**
|
||||
* App icon badge management utility.
|
||||
* Sets the badge count on the app icon (iOS only, Android has no equivalent).
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set the app icon badge count.
|
||||
* On iOS, this updates the red badge number on the app icon.
|
||||
* On Android, this is a no-op as Android doesn't have app icon badges.
|
||||
*/
|
||||
export async function setBadgeCount(count: number): Promise<void> {
|
||||
// Badge count is iOS only
|
||||
if (Platform.OS !== 'ios') {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await Notifications.setBadgeCountAsync(Math.max(0, count));
|
||||
} catch (error) {
|
||||
console.error('Failed to set badge count:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the app icon badge.
|
||||
*/
|
||||
export async function clearBadge(): Promise<void> {
|
||||
await setBadgeCount(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current badge count.
|
||||
*/
|
||||
export async function getBadgeCount(): Promise<number> {
|
||||
if (Platform.OS !== 'ios') {
|
||||
return 0;
|
||||
}
|
||||
|
||||
try {
|
||||
return await Notifications.getBadgeCountAsync();
|
||||
} catch (error) {
|
||||
console.error('Failed to get badge count:', error);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sync badge count with the total of new matches and unread messages.
|
||||
* This should be called whenever either count changes.
|
||||
*/
|
||||
export async function syncBadgeCount(newMatchesCount: number, unreadMessagesCount: number): Promise<void> {
|
||||
const total = newMatchesCount + unreadMessagesCount;
|
||||
await setBadgeCount(total);
|
||||
}
|
||||
Reference in new issue
Block a user