Pulsar Haptic Feedback SDK

repository·main·Indexed 19 days ago

https://github.com/software-mansion/pulsar

A high-fidelity, cross-platform haptic feedback SDK providing consistent tactile experiences across iOS, Android, React Native, Flutter, KMP, and Web. It features three trigger methods: Presets for standard effects, PatternComposer for complex custom sequences using amplitude and frequency envelopes, and RealtimeComposer for gesture-driven, interactive feedback.

Tokens
47.3K
Snippets
133
Records
184
Agent score
59%

What's inside Pulsar

  1. What is Pulsar Studio?

    main

    Pulsar Studio is a visual haptic editor designed for developers to create custom haptic sequences. It allows you to:

    • Draw waveforms: Visually design the intensity and timing of haptic feedback.
    • Live Preview: Test your designed waveforms on a real device in real-time.
    • Export patterns: Seamlessly export your custom haptic patterns to iOS, Android, or React Native projects.
  2. Overview of Pulsar Haptics SDK

    main

    Pulsar is a cross-platform haptic feedback SDK designed for iOS, Android, React Native, Kotlin Multiplatform, Flutter, and the Web. It provides a consistent API for delivering rich tactile feedback through three main mechanisms:

    • Presets: A library of built-in patterns (e.g., hammer, dogBark, buzz, pulse) and system-level feedback styles (impacts, notifications, selection).
    • Pattern Composer: Allows you to define custom haptic patterns using discrete events and continuous amplitude/frequency envelopes.
    • Realtime Composer: Enables live amplitude and frequency control, ideal for gesture-driven haptics.

    For React Native users, all preset functions and hook methods are compatible with Reanimated worklets.

  3. Capabilities of the pulsar-haptics skill

    main

    The pulsar-haptics skill assists with several haptic development tasks, including:

    • Choosing presets and designing better haptic feedback.
    • Implementing Pulsar APIs in React Native, iOS, and Android.
    • Building gesture-driven haptics and custom patterns.
    • Migrating from legacy APIs such as expo-haptics, Core Haptics, and VibrationEffect.
    • Handling device compatibility, testing, and implementing graceful fallbacks.
  4. Pulsar features and compatibility

    main

    Pulsar is a haptic feedback SDK for React Native with the following key characteristics:

    • Cross-platform: Consistent API across iOS (Swift), Android (Kotlin), and React Native (TypeScript).
    • Worklet-compatible: All preset functions and hook methods are designed to work inside Reanimated worklets.
    • Core Components:
      • Presets: Built-in patterns (hammer, dogBark, buzz, pulse) and system styles (impacts, notifications, selection).
      • Pattern Composer: Custom sequences using discrete events and continuous envelopes.
      • Realtime Composer: Live amplitude/frequency control for gestures.
  5. Understand the PulsarApp Kotlin Multiplatform structure

    main

    PulsarApp is a Kotlin Multiplatform (KMP) project targeting Android and iOS. The project structure is organized to facilitate code sharing via Compose Multiplatform:

    • /composeApp: Contains the shared logic and UI code.
      • commonMain: The primary location for code that is shared across all targets.
      • Platform-specific folders (e.g., iosMain, jvmMain): Used for code that requires platform-specific APIs (for example, using Apple's CoreCrypto in iosMain).
    • /iosApp: The entry point for the iOS application. This directory is required even when sharing UI via Compose Multiplatform and is the location for adding SwiftUI code.
  6. Configure RealtimeComposerStrategy on Android

    main

    Since Android lacks a native continuous haptic API, RealtimeComposer uses a strategy to simulate continuous haptics. You can set this via pulsar.getRealtimeComposer(strategy: ...) or pulsar.setRealtimeComposerStrategy(...).

    Available strategies in RealtimeComposerStrategy:

    • envelope: Approximation based on the Envelope API (Android API 36+). Allows amplitude/frequency control but may be unstable.
    • primitiveTick: Uses the Composition API TICK primitive at varying intervals. Amplitude is controllable; frequency is simulated by timing. Signal is discrete.
    • primitiveComplex: Uses multiple primitives depending on the requested frequency.
    • envelopeWithDiscretePrimitives (Default): A hybrid strategy using the Envelope API for continuous events (API 36+) and composition primitives for discrete events (API 33+).
  7. Use AdaptiveHaptics for cross-platform presets

    main

    AdaptiveHaptics allows you to define a single AdaptivePreset that behaves differently on iOS and Android. This is useful for using native system presets on one platform while using custom PatternData on another.

    createAdaptiveHaptics is asynchronous because it pre-parses pattern-based configurations to ensure zero-latency playback. Call dispose() when the instance is no longer needed.

    Configuration Types

    • AdaptivePresetCallback: Invokes a callback on play(). Best for triggering native/built-in presets (e.g., pulsar.presets.systemNotificationSuccess()).
    • AdaptivePresetPattern: Plays a specific PatternData on each play() call.

    Example

    final adaptivePreset = AdaptivePreset(
      ios: AdaptivePresetCallback(() => pulsar.presets.systemNotificationSuccess()),
      android: AdaptivePresetPattern(
        PatternData(
          continuousPattern: const ContinuousPattern(amplitude: [], frequency: []),
          discretePattern: const [
            DiscretePoint(time: 0, amplitude: 1, frequency: 0.5),
            DiscretePoint(time: 150, amplitude: 0.6, frequency: 0.4),
          ],
        ),
      ),
    );
    
    final haptics = await pulsar.createAdaptiveHaptics(adaptivePreset);
    await haptics.play();
    import 'package:pulsar_haptics/pulsar.dart';
    
    final pulsar = Pulsar();
    
    final adaptivePreset = AdaptivePreset(
      ios: AdaptivePresetCallback(() => pulsar.presets.systemNotificationSuccess()),
      android: AdaptivePresetPattern(
        PatternData(
          continuousPattern: const ContinuousPattern(
            amplitude: [],
            frequency: [],
          ),
          discretePattern: const [
            DiscretePoint(time: 0, amplitude: 1, frequency: 0.5),
            DiscretePoint(time: 150, amplitude: 0.6, frequency: 0.4),
          ],
        ),
      ),
    );
    
    final haptics = await pulsar.createAdaptiveHaptics(adaptivePreset);
    await haptics.play();
  8. Core building blocks of the React Native SDK

    main

    The react-native-pulsar SDK is built around three primary abstractions for delivering haptic feedback:

    1. Presets: Ready-to-use haptic patterns.
    2. usePatternComposer: A hook for composing specific haptic patterns.
    3. useRealtimeComposer: A hook for real-time haptic composition.

    Crucially, all preset functions and hook methods are worklet-compatible, meaning they can be safely used within react-native-reanimated worklets for high-performance, synchronized haptics.

  9. How the Realtime Composer works

    main

    The useRealtimeComposer hook is designed for gesture-driven haptics, providing live control over haptic intensity. It allows you to update the amplitude and frequency of a continuous haptic effect in real-time based on user interaction (like dragging or scrolling).

    • set(amplitude, frequency): Updates the current haptic output.
    • stop(): Immediately ceases the haptic feedback.
    import { useRealtimeComposer } from 'react-native-pulsar';
    
    const { set, stop } = useRealtimeComposer();
    
    // Update haptics live (e.g., inside a gesture handler)
    set(0.7, 0.5);
    
    // Stop the haptics
    stop();