Skip to content

[FEATURE] One Signal Helper Development #175

@SelimKutuk

Description

@SelimKutuk

Prerequisites

  • I have searched for existing feature requests that might be similar
  • I have read the documentation
  • This feature would benefit the broader OSMEA community

Target Package

Core

Feature Type

New component/widget

Priority

High - Important for my use case

Problem Statement

Problem Statement: Missing OneSignal Helper

Currently, the project lacks a unified helper for OneSignal push notifications. Initialization, permission prompts, tagging/segmentation, and click-routing logic are implemented ad-hoc across different modules. This causes:

  • Code Duplication: Repeating boilerplate for init, permissions, and handlers.
  • Inconsistency: Divergent handling of notification payloads, deep links, and channels across features.
  • Fragile Routing: Notification click → screen routing (deep links) handled differently per screen.
  • Poor Observability: No single place to log outcomes/analytics or capture errors.
  • Env Drift: App IDs and channel configs differ across dev/stage/prod without clear centralization.
  • Maintainability Risks: Changes to SDK usage or OS permission rules require many scattered edits.

Proposed Solution

Proposed Solution: OneSignal Helper

Introduce a OneSignalHelper (e.g., lib/app/services/notifications/one_signal_helper.dart) that encapsulates all OneSignal concerns behind a clean, testable API.

Goals

  • Single Entry Point for initialization, permissions, listeners, and routing.
  • Flavor-Aware Config: Separate App IDs and defaults for dev/stage/prod.
  • Consistent Payload Schema: Normalize additionalData to a typed model.
  • Deterministic Routing: Centralize notification click → AutoRoute navigation.
  • Tagging/Segmentation Utilities: First-class methods for tags, aliases, externalId.
  • Observability: Outcome events + error reporting hooks.
  • Compliance: GDPR consent + Android/iOS permission nuances.

Suggested Interface (Dart Example)

class OneSignalConfig {
  final String appId;
  final bool allowProvisionalIOS; // iOS provisional auth
  final bool autoPrompt;          // defer if you need custom timing
  final Map<String, String> defaultTags;

  const OneSignalConfig({
    required this.appId,
    this.allowProvisionalIOS = true,
    this.autoPrompt = false,
    this.defaultTags = const {},
  });
}

typedef NotificationRouteResolver = Future<void> Function(OneSignalPayload payload);

class OneSignalHelper {
  static Future<void> init(OneSignalConfig config);
  static Future<bool> requestPermission();              // Android 13+ & iOS
  static Future<void> setExternalId(String userId);
  static Future<void> setTags(Map<String, String> tags);
  static Future<void> deleteTags(List<String> keys);
  static Future<String?> getPlayerId();                 // device/user id
  static void onNotificationReceived(void Function(OneSignalPayload p) cb);
  static void onNotificationOpened(NotificationRouteResolver resolver);
  static void enableInAppMessages(bool enabled);
  static Future<void> logOutcome(String name, {double? value});
}

Routing Contract

  • Normalize additionalData to a OneSignalPayload with fields like:
    • target: route name (e.g., "newsDetail")
    • params: { "id": "123", "category": "tech" }
    • screenTracking: optional analytics key

The helper calls a provided NotificationRouteResolver to perform navigation:

context.router.push(NewsDetailRoute(id: payload.params['id']));

Channels & Permissions

  • Android: Create channels (high/low importance), badge count, sound/vibration defaults.
  • iOS: Support provisional auth and explicit prompt; handle “Deliver Quietly” cases.
  • GDPR/Consent: Expose setConsentRequired, provideConsent.

Error & Retry

  • Wrap SDK calls with safeguards (network issues) and exponential backoff where meaningful.
  • Provide a simple internal logger hook so the app can forward to Crashlytics/Sentry.

Environment Management

  • Read ONE_SIGNAL_APP_ID per flavor from .env/--dart-define and inject via OneSignalConfig.
  • Enforce initialization before usage with an assert/guard.

Expected Benefits

  • Consistency in permissions, tags, channels, and routing.
  • Less Boilerplate, faster feature delivery.
  • Better Analytics via centralized outcome logging.
  • Safer Updates when SDK or OS rules change.

Alternatives Considered

No response

Use Cases

Use Cases: OneSignal Helper

1. First-Run Permission Flow

Defer the system notification prompt until after onboarding.

await OneSignalHelper.requestPermission();

2. User-Scoped Targeting

After login, set the external user ID and tags for segmentation.

await OneSignalHelper.setExternalId(user.id);
await OneSignalHelper.setTags({"role": "seller"});

3. Deep Link Routing

Open a specific screen (e.g., OrderDetail) when the user taps a notification.

OneSignalHelper.onNotificationOpened((payload) async {
  if (payload.target == "orderDetail") {
    context.router.push(OrderDetailRoute(id: payload.params["id"]));
  }
});

4. Segmented Campaigns

Apply tags to deliver targeted push notifications.

await OneSignalHelper.setTags({"lang": "tr", "tier": "gold"});

5. In-App Messages for Announcements

Enable in-app messages for announcements or feature rollouts.

OneSignalHelper.enableInAppMessages(true);

6. Outcome Tracking

Track outcomes when users interact with content from notifications.

await OneSignalHelper.logOutcome("open_news_detail");

7. Compliance Mode (GDPR/Consent)

Ensure GDPR consent before activating OneSignal functionality.

OneSignal.setConsentRequired(true);
OneSignal.provideConsent(true);

8. Multi-Flavor App IDs

Use different App IDs per environment (dev/stage/prod) to avoid mixing audiences.

9. Android 13+ Runtime Permissions

Prompt users for runtime notification permission with rationale.

10. Silent Update Hints

Handle silent push notifications to refresh cached content and show subtle in-app banners.

Mockups/Examples

No response

Implementation Ideas

No response

Contribution

  • I would like to work on this feature
  • I can help with testing
  • I can help with documentation
  • I can provide feedback during development

Additional Context

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions