Skip to content

feat(audience-sample-app): add sample app for ImmutableAudience SDK [SDK-152]#711

Open
ImmutableJeffrey wants to merge 5 commits intomainfrom
feat/audience-sample-app
Open

feat(audience-sample-app): add sample app for ImmutableAudience SDK [SDK-152]#711
ImmutableJeffrey wants to merge 5 commits intomainfrom
feat/audience-sample-app

Conversation

@ImmutableJeffrey
Copy link
Copy Markdown
Collaborator

@ImmutableJeffrey ImmutableJeffrey commented Apr 28, 2026

Summary

Adds a sample app under examples/audience exercising every public ImmutableAudience API across four tabs (Setup, Consent, Typed Events, Identity) plus an event log mirroring SDK debug output.

Linear: SDK-152

@ImmutableJeffrey ImmutableJeffrey requested review from a team as code owners April 28, 2026 08:29
@ImmutableJeffrey ImmutableJeffrey changed the title feat(audience-sample-app): UI Toolkit demo for ImmutableAudience SDK [SDK-152] feat(audience-sample-app): add sample app for ImmutableAudience SDK [SDK-152] Apr 28, 2026
@ImmutableJeffrey ImmutableJeffrey force-pushed the feat/audience-sample-app branch 2 times, most recently from 55515d7 to 92d670a Compare April 28, 2026 08:38
@ImmutableJeffrey ImmutableJeffrey force-pushed the feat/audience-sample-app branch from 92d670a to 6983964 Compare April 28, 2026 16:27
…format envelope key

Two transport-layer fixes surfaced during sample-app testing:

* HttpTransport includes the response body in the OnError message for
  4xx/5xx responses. Previous "HTTP 400" rows gave studios no actionable
  signal; the body string carries the validation reason.

* Wire-format envelope key is "messages", not "batch". The backend ingest
  path expects "messages" and the prior key silently dropped events.

Tests updated for both.
Roboto-Regular.ttf and RobotoMono-Regular.ttf for sample-app text
(prose and monospace respectively). Apache 2.0 LICENSE files included
alongside.
Unity-package wiring for the sample under examples/audience:
* Packages/manifest.json points at com.immutable.audience locally
* Scripts/Immutable.Audience.Samples.SampleApp.asmdef declares the
  sample assembly + dependencies
* Top-level README

Removes Assets/Scenes.meta (legacy folder meta — sample's scene now
lives at Assets/SampleApp/Scenes/).
Visual layer for the sample app — these reference each other:

* SampleApp.unity scene with a UIDocument component
* AudienceSampleAppPanelSettings panel settings asset (referenced by
  the UIDocument)
* AudienceSampleAppTheme.tss theme stylesheet (referenced by the
  panel settings)
* AudienceSample.uxml visual tree — header, status bar, tab bar,
  controls + log columns, drag handle
* Templates/Accordion.uxml — typed-events accordion template
  (cloned per Catalogue entry at runtime)
* AudienceSample.uss stylesheet with shared tokens (--bg, --panel-bg,
  --text, --accent, --ok, --warn, --err, --debug, --transparent,
  --text-on-accent, ...) and ~95 selectors covering tabs, accordions,
  status bar, log rows, drag handle, responsive single-column layout
  below 1024px width.
Three partials of the AudienceSample MonoBehaviour, each with one
concern:

* AudienceSample.cs        SDK calls, On* handlers, mirror state, SDK
                           callbacks (OnError, Log.Writer adapter),
                           config builders. Reads UXML state ONLY via
                           UI's Capture*Form accessors — never touches
                           a UXML field directly.
* AudienceSample.UI.cs     UXML fields, binding, rendering, log pane
                           mechanics, drag-resize, Refresh* methods,
                           Capture*Form accessors. No SDK calls.
* AudienceSample.Events.cs Catalogue (typed + string events), typed-
                           event factory, props builder. Pure factory:
                           no UXML, no SDK.

Form-snapshot DTOs (InitForm, IdentifyForm, AliasForm, CustomEventForm)
hand button-click state from UI to main. Refresh* fan-out collapses to
OnSdkStateChanged.

Threading: SDK OnError fires from background flush threads; AppendLog
captures SynchronizationContext + main thread id at startup and
re-dispatches via SyncContext.Post on off-main entry. Required because
_logView.schedule.Execute silently drops off-main callers in 2021.3
runtime panels.

The log pane caps at 200 rows (oldest evicted on overflow) with
stateless per-row "was at bottom?" auto-scroll. Each row stashes its
LogEntry on userData so the visual tree IS the log data — no parallel
buffer to maintain.
@ImmutableJeffrey ImmutableJeffrey force-pushed the feat/audience-sample-app branch from 6983964 to 9e825b9 Compare April 28, 2026 16:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant