Skip to content

feat(android): runtime .pulsar bundle loader + Gradle plugin (3/6) - #204

Merged
piaskowyk merged 4 commits into
mainfrom
feat/preset-bundles-android
Aug 11, 2026
Merged

feat(android): runtime .pulsar bundle loader + Gradle plugin (3/6)#204
piaskowyk merged 4 commits into
mainfrom
feat/preset-bundles-android

Conversation

@piaskowyk

Copy link
Copy Markdown
Member

Stack 3/6 — base: feat/preset-bundles-ios.

What

Runtime bundle loading in the standalone Android SDK (com.swmansion:pulsar).

  • bundle/Unzip.ktjava.util.zip reader (STORE+DEFLATE).
  • bundle/BundleManifest.kt@Serializable manifest + device-wire haptics DTOs (kotlinx.serialization, already on the SDK), mapped into the SDK PatternData.
  • bundle/PulsarBundle.ktPresetHandle (lazy parse; synced audio via parsePatternWithSound with hapticChannels=false so music + haptics play together; animation bytes for the app); LoadedBundle (untyped bridge surface); typed PulsarBundle<P> / BundleDescriptor<P>.
  • bundle/BundleLoader.kt + Pulsar.loadBundle(bytes/path/asset/descriptor).
  • tools/pulsar-gen-gradle — Gradle plugin (id "com.swmansion.pulsar.gen"): generates typed Kotlin per .pulsar in src/pulsarBundles/ and packages bundles into assets before compile (FlutterGen / Compose-Resources model).
  • BundleUnitTest — JVM decode/unzip/mapping.

Verification

⚠️ Not compiled here — please run the Gradle build + BundleUnitTest.

Foundation for custom preset bundles. Defines the .pulsar format (ZIP +
manifest.json), a JSON schema, and pulsar-gen: a zero-dependency Node/TS CLI
that reads a .pulsar and emits typed accessors for swift/kotlin/dart and an
RN JSON sidecar (keyof-inference, nano-icons style). Includes a fixture bundle,
golden outputs, and a node:test suite (7 passing). Portable emitter core is
reusable from Studio's browser exporter.
Adds runtime bundle loading to the standalone iOS SDK (PulsarHaptics), the
artifact RN + Flutter link against:

- Bundle/PulsarUnzip.swift: minimal STORE+DEFLATE zip reader over the
  Compression framework (no new dependency).
- Bundle/PulsarBundle.swift: Codable manifest, PresetHandle (lazy parse,
  synced audio via parsePatternWithSound, animation bytes for the app to
  render), LoadedBundle (untyped string-keyed surface for the RN/Flutter
  bridges), and the typed PulsarBundle<P>/BundleDescriptor<P>/BundleResolver.
- Bundle/BundleLoader.swift: Pulsar.loadBundle(data:/path:) + typed
  loadBundle(_:strict:); haptics JSON decodes straight into PatternData;
  audio extracted to caches for Core Haptics.
- pulsar-gen-swift host tool + PulsarGenPlugin build-tool plugin: regenerate
  the typed accessor on every build, no Node/network in the sandbox.
- BundleTests: unzip + load + typed-view + schema-rejection (Swift Testing).

The loaded bundle owns its handles, so no change to the compiled preset
registry. Note: native/plugin code is not compiled in this environment
(iOS/UIKit); verify via xcodebuild on a simulator.
…(PR2)

Adds runtime bundle loading to the standalone Android SDK (com.swmansion:pulsar),
the artifact RN + Flutter link against:

- bundle/Unzip.kt: java.util.zip reader (STORE+DEFLATE).
- bundle/BundleManifest.kt: @serializable manifest + device-wire haptics DTOs
  (kotlinx.serialization, already on the SDK), mapped into the SDK PatternData.
- bundle/PulsarBundle.kt: PresetHandle (lazy parse, synced audio via
  parsePatternWithSound with hapticChannels=false so music + haptics play
  together, animation bytes for the app to render), LoadedBundle (untyped
  string-keyed surface for bridges), typed PulsarBundle<P>/BundleDescriptor<P>.
- bundle/BundleLoader.kt + Pulsar.loadBundle(bytes/path/asset/descriptor).
- tools/pulsar-gen-gradle: Gradle plugin (id com.swmansion.pulsar.gen) that
  generates typed Kotlin per .pulsar in src/pulsarBundles/ and packages bundles
  into assets before compile (FlutterGen/Compose-Resources model).
- BundleUnitTest: JVM decode/unzip/mapping tests.

Loaded bundle owns its handles; no change to the compiled preset registry.
Note: Android/Gradle code not compiled in this environment; verify via gradle.
Base automatically changed from feat/preset-bundles-ios to main August 11, 2026 15:47
@piaskowyk
piaskowyk merged commit 0f60501 into main Aug 11, 2026
1 check passed
@piaskowyk
piaskowyk deleted the feat/preset-bundles-android branch August 11, 2026 15:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant