Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,7 @@ private void RegisterHandlers()
if (label.ClassListContains(SampleAppUi.Css.Copied)) return;
if (string.IsNullOrEmpty(label.text) || label.text == SampleAppUi.StatusBar.EmptyText) return;
GUIUtility.systemCopyBuffer = label.text;
label.text = "Copied!";
label.text = SampleAppUi.ButtonText.CopiedFlash;
FlashCopied(label);
});
}
Expand Down Expand Up @@ -533,17 +533,17 @@ private void RefreshStatusBar()
string? derivedFromKey = keyEmpty ? null : (isTest ? Constants.SandboxBaseUrl : Constants.ProductionBaseUrl);
string? endpoint = hasOverride ? overrideUrl : derivedFromKey;
bool warnState = hasOverride || (!keyEmpty && !isTest);
SetStatusCell(_statusEndpoint, endpoint, warnState ? "state-warn" : "state-ok");
SetStatusCell(_statusEndpoint, endpoint, warnState ? SampleAppUi.Css.StateWarn : SampleAppUi.Css.StateOk);
_prodWarning.EnableInClassList(SampleAppUi.HiddenClass, hasOverride || keyEmpty || isTest);

var consent = _initialised ? ImmutableAudience.CurrentConsent : ConsentOrder[Mathf.Clamp(_initialConsent?.index ?? 0, 0, ConsentOrder.Length - 1)];
int cIdx = Array.IndexOf(ConsentOrder, consent);
SetStatusCell(_statusConsent, consent.ToLowercaseString(), cIdx >= 0 ? ConsentStateClass[cIdx] : "dim");
SetStatusCell(_statusConsent, consent.ToLowercaseString(), cIdx >= 0 ? ConsentStateClass[cIdx] : SampleAppUi.Css.Dim);

SetStatusCell(_statusAnon, _initialised ? ImmutableAudience.AnonymousId : null, "dim");
SetStatusCell(_statusUser, _initialised ? ImmutableAudience.UserId : null, "dim");
SetStatusCell(_statusSession, _initialised ? ImmutableAudience.SessionId : null, "dim");
SetStatusCell(_statusQueue, _initialised ? ImmutableAudience.QueueSize.ToString(CultureInfo.InvariantCulture) : null, "dim");
SetStatusCell(_statusAnon, _initialised ? ImmutableAudience.AnonymousId : null, SampleAppUi.Css.Dim);
SetStatusCell(_statusUser, _initialised ? ImmutableAudience.UserId : null, SampleAppUi.Css.Dim);
SetStatusCell(_statusSession, _initialised ? ImmutableAudience.SessionId : null, SampleAppUi.Css.Dim);
SetStatusCell(_statusQueue, _initialised ? ImmutableAudience.QueueSize.ToString(CultureInfo.InvariantCulture) : null, SampleAppUi.Css.Dim);
}

private void RefreshConsentPills()
Expand Down
62 changes: 31 additions & 31 deletions examples/audience/Assets/SampleApp/Scripts/AudienceSample.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,30 +71,30 @@ private void OnShutdown() => RunAndLog(SampleAppUi.LogLabels.Shutdown, () =>
_initialised = false;
ResetIdentityMirror();
OnSdkStateChanged();
return "SDK stopped";
return SampleAppUi.Messages.SdkStopped;
});

private void OnReset() => RunAndLog(SampleAppUi.LogLabels.Reset, () =>
{
ImmutableAudience.Reset();
ResetIdentityMirror();
OnSdkStateChanged();
return "anonymous ID regenerated, queue cleared";
return SampleAppUi.Messages.AnonymousIdRegeneratedQueueCleared;
});

private async Task OnFlushAsync()
{
try { await ImmutableAudience.FlushAsync(); AppendLog(SampleAppUi.LogLabels.Flush, "queue flushed", LogLevel.Ok, LogSource.App); OnSdkStateChanged(); }
try { await ImmutableAudience.FlushAsync(); AppendLog(SampleAppUi.LogLabels.Flush, SampleAppUi.Messages.QueueFlushed, LogLevel.Ok, LogSource.App); OnSdkStateChanged(); }
catch (Exception ex) { AppendLog(SampleAppUi.LogLabels.Flush, ex.Message, LogLevel.Err, LogSource.App); }
}

private async Task OnDeleteDataAsync()
{
AppendLog(SampleAppUi.LogLabels.DeleteData, "erasure request dispatched", LogLevel.Info, LogSource.App);
AppendLog(SampleAppUi.LogLabels.DeleteData, SampleAppUi.Messages.ErasureRequestDispatched, LogLevel.Info, LogSource.App);
try
{
await ImmutableAudience.DeleteData();
AppendLog(SampleAppUi.LogLabels.DeleteData, "backend acknowledged", LogLevel.Ok, LogSource.App);
AppendLog(SampleAppUi.LogLabels.DeleteData, SampleAppUi.Messages.BackendAcknowledged, LogLevel.Ok, LogSource.App);
}
catch (Exception ex)
{
Expand Down Expand Up @@ -130,17 +130,17 @@ private void OnSendCatalogueEvent(EventSpec spec, Dictionary<string, VisualEleme
ImmutableAudience.Track(typed);
return Json.Serialize(new Dictionary<string, object>
{
["event"] = spec.Name,
["overload"] = "typed",
[SampleAppUi.LogPayloadKeys.Event] = spec.Name,
[SampleAppUi.LogPayloadKeys.Overload] = SampleAppUi.LogPayloadKeys.OverloadValues.Typed,
[MessageFields.Properties] = typed.ToProperties(),
}, 2);
}

ImmutableAudience.Track(spec.Name, props.Count > 0 ? props : null);
return Json.Serialize(new Dictionary<string, object>
{
["event"] = spec.Name,
["overload"] = "string",
[SampleAppUi.LogPayloadKeys.Event] = spec.Name,
[SampleAppUi.LogPayloadKeys.Overload] = SampleAppUi.LogPayloadKeys.OverloadValues.String,
[MessageFields.Properties] = props,
}, 2);
});
Expand All @@ -154,7 +154,7 @@ private void OnSendCustomEvent() => RunAndLog(SampleAppUi.LogLabels.Track, () =>
var f = CaptureCustomEventForm();
var props = string.IsNullOrEmpty(f.RawProps) ? null : JsonReader.DeserializeObject(f.RawProps);
ImmutableAudience.Track(f.Name, props);
var echo = new Dictionary<string, object> { ["event"] = f.Name };
var echo = new Dictionary<string, object> { [SampleAppUi.LogPayloadKeys.Event] = f.Name };
if (props != null) echo[MessageFields.Properties] = props;
return Json.Serialize(echo, 2);
});
Expand All @@ -171,14 +171,14 @@ private void OnSetConsent(ConsentLevel level) => RunAndLog(SampleAppUi.LogLabels
if (!level.CanIdentify()) ResetIdentityMirror();
var payload = new Dictionary<string, object>
{
["from"] = previous.ToLowercaseString(),
["to"] = level.ToLowercaseString(),
[SampleAppUi.LogPayloadKeys.From] = previous.ToLowercaseString(),
[SampleAppUi.LogPayloadKeys.To] = level.ToLowercaseString(),
};
var effects = new List<string>();
if (previous == ConsentLevel.None && level != ConsentLevel.None) effects.Add(SampleAppUi.Messages.QueueStartedSessionCreated);
if (level == ConsentLevel.None) effects.Add(SampleAppUi.Messages.QueuePurgedAnonymousIdCleared);
if (!level.CanIdentify() && previous.CanIdentify()) effects.Add(SampleAppUi.Messages.UserIdCleared);
if (effects.Count > 0) payload["effects"] = effects;
if (effects.Count > 0) payload[SampleAppUi.LogPayloadKeys.Effects] = effects;
OnSdkStateChanged();
return Json.Serialize(payload, 2);
});
Expand All @@ -198,9 +198,9 @@ private void OnIdentify() => RunAndLog(SampleAppUi.LogLabels.Identify, () =>
OnSdkStateChanged();
var payload = new Dictionary<string, object>
{
["id"] = f.Id,
[MessageFields.IdentityType] = f.Type,
["accepted"] = accepted,
[SampleAppUi.LogPayloadKeys.Id] = f.Id,
[MessageFields.IdentityType] = f.Type,
[SampleAppUi.LogPayloadKeys.Accepted] = accepted,
};
if (traits != null) payload[MessageFields.Traits] = traits;
return Json.Serialize(payload, 2);
Expand Down Expand Up @@ -233,9 +233,9 @@ private void OnAlias() => RunAndLog(SampleAppUi.LogLabels.Alias, () =>
}
return Json.Serialize(new Dictionary<string, object>
{
["from"] = new Dictionary<string, object> { ["id"] = f.FromId, [MessageFields.IdentityType] = f.FromType },
["to"] = new Dictionary<string, object> { ["id"] = f.ToId, [MessageFields.IdentityType] = f.ToType },
["accepted"] = accepted,
[SampleAppUi.LogPayloadKeys.From] = new Dictionary<string, object> { [SampleAppUi.LogPayloadKeys.Id] = f.FromId, [MessageFields.IdentityType] = f.FromType },
[SampleAppUi.LogPayloadKeys.To] = new Dictionary<string, object> { [SampleAppUi.LogPayloadKeys.Id] = f.ToId, [MessageFields.IdentityType] = f.ToType },
[SampleAppUi.LogPayloadKeys.Accepted] = accepted,
}, 2);
});

Expand All @@ -246,8 +246,8 @@ private void OnAlias() => RunAndLog(SampleAppUi.LogLabels.Alias, () =>
private void OnSdkError(AudienceError err) =>
AppendLog(SampleAppUi.LogLabels.OnError, Json.Serialize(new Dictionary<string, object>
{
["code"] = err.Code.ToString(),
["message"] = err.Message,
[SampleAppUi.LogPayloadKeys.Code] = err.Code.ToString(),
[SampleAppUi.LogPayloadKeys.Message] = err.Message,
}, 2), LogLevel.Err, LogSource.Sdk);

// SDK Log.Writer adapter. May fire from any thread; AppendLog handles
Expand Down Expand Up @@ -288,7 +288,7 @@ private static void GuardConsentForTrack()
var consent = ImmutableAudience.CurrentConsent;
if (!consent.CanTrack())
throw new InvalidOperationException(
$"track dropped — consent is {consent.ToLowercaseString()}; raise to anonymous or full to queue events");
string.Format(SampleAppUi.Messages.TrackDroppedConsentFmt, consent.ToLowercaseString()));
}

// Refresh* are idempotent reads, so calling all four every time is
Expand Down Expand Up @@ -320,7 +320,7 @@ private AudienceConfig BuildAudienceConfig(InitForm form, Action<AudienceError>
if (form.FlushIntervalMs is int flushMs && flushMs > 0)
{
if (flushMs < 1000)
AppendLog(SampleAppUi.LogLabels.Init, $"flushInterval {flushMs}ms below 1s — clamped", LogLevel.Warn, LogSource.App);
AppendLog(SampleAppUi.LogLabels.Init, string.Format(SampleAppUi.Messages.FlushIntervalBelowOneSecondClampedFmt, flushMs), LogLevel.Warn, LogSource.App);
config.FlushIntervalSeconds = Math.Max(1, flushMs / 1000);
}
if (form.FlushSize is int flushSize && flushSize > 0)
Expand All @@ -334,17 +334,17 @@ private static Dictionary<string, object> BuildConfigEcho(AudienceConfig config)
{
var echo = new Dictionary<string, object>
{
["consent"] = config.Consent.ToString(),
["debug"] = config.Debug,
["flushIntervalSeconds"] = config.FlushIntervalSeconds,
["flushSize"] = config.FlushSize,
["packageVersion"] = config.PackageVersion,
["shutdownFlushTimeoutMs"] = config.ShutdownFlushTimeoutMs,
[SampleAppUi.LogPayloadKeys.Consent] = config.Consent.ToString(),
[SampleAppUi.LogPayloadKeys.Debug] = config.Debug,
[SampleAppUi.LogPayloadKeys.FlushIntervalSeconds] = config.FlushIntervalSeconds,
[SampleAppUi.LogPayloadKeys.FlushSize] = config.FlushSize,
[SampleAppUi.LogPayloadKeys.PackageVersion] = config.PackageVersion,
[SampleAppUi.LogPayloadKeys.ShutdownFlushTimeoutMs] = config.ShutdownFlushTimeoutMs,
};
if (!string.IsNullOrEmpty(config.PublishableKey))
echo["publishableKey"] = RedactPublishableKey(config.PublishableKey);
echo[SampleAppUi.LogPayloadKeys.PublishableKey] = RedactPublishableKey(config.PublishableKey);
if (!string.IsNullOrEmpty(config.PersistentDataPath))
echo["persistentDataPath"] = config.PersistentDataPath;
echo[SampleAppUi.LogPayloadKeys.PersistentDataPath] = config.PersistentDataPath;
return echo;
}

Expand Down
56 changes: 55 additions & 1 deletion examples/audience/Assets/SampleApp/Scripts/SampleAppUi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,10 @@ internal static class ButtonText
internal const string Send = "Send";
internal const string Copy = "Copy";
internal const string Copied = "Copied";

// Click-to-copy flash on status cells (transient label override).
// Distinct from Copied which is the post-click button label.
internal const string CopiedFlash = "Copied!";
}

// ---- Resources paths ----
Expand All @@ -182,9 +186,22 @@ internal static class Messages
internal const string QueueStartedSessionCreated = "queue started, session created";
internal const string QueuePurgedAnonymousIdCleared = "queue purged, anonymous ID cleared";
internal const string UserIdCleared = "userId cleared";
internal const string NoActiveIdentity = "no active identity call Identify first";
internal const string NoActiveIdentity = "no active identity, call Identify first";
internal const string TraitsRequired = "traits required";
internal const string Ready = "Sample app loaded. Paste a publishable key and click Init.";

// Status messages emitted by AudienceSample's RunAndLog handlers.
internal const string SdkStopped = "SDK stopped";
internal const string AnonymousIdRegeneratedQueueCleared = "anonymous ID regenerated, queue cleared";
internal const string QueueFlushed = "queue flushed";
internal const string ErasureRequestDispatched = "erasure request dispatched";
internal const string BackendAcknowledged = "backend acknowledged";

// Formatted variants for use with string.Format or interpolation.
internal const string TrackDroppedConsentFmt =
"track dropped, consent is {0}; raise to anonymous or full to queue events";
internal const string FlushIntervalBelowOneSecondClampedFmt =
"flushInterval {0}ms below 1s, clamped";
}

// Mirrors AudienceSample.UI.cs PopulateTypedEventAccordions naming:
Expand Down Expand Up @@ -301,5 +318,42 @@ internal static class Consent
internal const string Anonymous = "anonymous";
internal const string Full = "full";
}

// Log payload JSON keys used by RunAndLog "Ok" row dictionaries.

internal static class LogPayloadKeys
{
// Track outcomes
internal const string Event = "event";
internal const string Overload = "overload";
internal const string Effects = "effects";

// Identify / Alias outcomes
internal const string Id = "id";
internal const string Accepted = "accepted";
internal const string From = "from";
internal const string To = "to";

// OnError row payload
internal const string Code = "code";
internal const string Message = "message";

// Init config echo
internal const string Consent = "consent";
internal const string Debug = "debug";
internal const string FlushIntervalSeconds = "flushIntervalSeconds";
internal const string FlushSize = "flushSize";
internal const string PackageVersion = "packageVersion";
internal const string ShutdownFlushTimeoutMs = "shutdownFlushTimeoutMs";
internal const string PublishableKey = "publishableKey";
internal const string PersistentDataPath = "persistentDataPath";

// Track overload values.
internal static class OverloadValues
{
internal const string Typed = "typed";
internal const string String = "string";
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace Immutable.Audience.Samples.SampleApp.Tests
{
// Values used by SampleAppLiveFireTests when filling the demo input fields.
internal static class SampleAppLiveFireFixtures
{
internal const string MilestoneSmokeName = "il2cpp_smoke";
internal const string GameId = "il2cpp_game_1";
internal const string LinkUrl = "https://example.com/il2cpp";
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading