southgames_flutter 0.19.0 copy "southgames_flutter: ^0.19.0" to clipboard
southgames_flutter: ^0.19.0 copied to clipboard

Flutter SDK for SouthGames — integrate gamification and loyalty features (spin wheel, scratch cards, trivia, slot machine, promo codes, in-app notifications) into your Flutter app with a single package.

0.19.0 #

  • getRankingPrizes() — qué reparte el ranking de una campaña, por período, para mostrarle al jugador qué está compitiendo. Solo vienen los períodos habilitados y con premios: una tabla apagada llega vacía, porque mostrarla prometería algo que no va a pasar.
  • Un premio de proveedor externo llega como CodePrizeReward sin monto: lo emite un tercero y cuánto vale es parte del acuerdo con él. El jugador ve que gana un código; el valor lo dice el código al canjearse.
  • El parseo es tolerante: una recompensa de un tipo que esta versión todavía no conoce se ignora, en vez de romper la tabla entera.

0.18.2 #

  • One close button, not twoSouthGamesGameView now hides its native top-right X when the game announces southgames:capabilities {selfClose: true} after the bridge handshake (Doggis Delivery >= 1.2.5 does). Such games render their own in-game X — with a proper abandon screen and a safe close that flushes any pending submitResult. Older games that never announce the capability keep the native X: nobody is left without an exit.
  • The native X no longer kills games silently — while it is visible, tapping it first routes a southgames:requestClose message into the game. A game that understands it acknowledges with southgames:requestCloseAck and opens its own abandon / safe-close flow (so an in-flight result is never lost). If no acknowledgement arrives within ~600 ms (older games), the SDK falls back to calling onClose directly, exactly as before.

0.18.1 #

  • Game campaigns now render truly full screenSouthGamesGameView no longer constrains the WebView to 70% of the screen height (which produced black bars above and below the game). The game page handles its own safe areas via viewport-fit=cover.
  • kSdkVersion now reports the real package version (0.18.0 introduced itself as "0.17.0" in the sdkVersion header).

0.18.0 #

  • Rankings (getRankings / getMyRanking) — dos métodos nuevos sobre /api/v1/rankings que exponen la tabla de posiciones que el servidor ya venía alimentando con cada partida. getRankings trae el top del período (RankingPeriod.daily / weekly / monthly / allTime), acotado por RankingScope.campaign / gameType / org, ordenable por RankingSortBy.rankingScore (la fórmula compuesta que configura la organización, default del servidor), highScore, totalScore o totalWins. getMyRanking devuelve la fila y la posición de UN jugador en una sola llamada aunque esté fuera del top — pensado para fijar "tu posición" al pie de la tabla — y expone entry == null / hasPlayed == false cuando todavía no jugó en ese período, para que el host muestre su estado vacío en vez de un cero. Sin externalUserId explícito usa el que persistió el último identify(). Los cortes de día, semana y mes los resuelve el servidor en la ZONA HORARIA DE LA ORGANIZACIÓN (nunca UTC), así que "hoy" es el día del jugador. limit se recorta al rango 1..100 que acepta el servidor, y pedir campaign/gameType sin scopeId lanza ArgumentError en el cliente en vez de gastar un round-trip para recibir un 400. Parseo tolerante en todos los modelos: un campo ausente, nulo o de un tipo inesperado cae a su neutro y jamás lanza — un servidor más nuevo que agregue campos, o uno más viejo que no los mande, no rompen al cliente.

0.17.0 #

  • prize en SouthGamesGameResult — campo aditivo SouthGamesPrize? con el código de premio emitido por la PLATAFORMA cuando el gajo ganador tiene "Código del premio" configurado en el editor (estudio de mini-juegos, F1). prize.code trae el código canjeable y prize.fulfillment es "fulfilled" o "pending" (emisión transitoria fallida: la plantilla reintenta sola y el código queda recuperable en el award). Llega con el mismo payload en onGameResult y onGameFinished. Parseo tolerante: ausente, null o con shape raro → null, jamás lanza — servers y plantillas viejas siguen funcionando igual.

0.16.0 #

  • externalId en SouthGamesGameResult — campo aditivo String? con el identificador que el operador declaró para el gajo ganador en el editor del portal, pensado para mapear el resultado contra TU plataforma (un SKU, un id de cupón, etc.) sin depender del segmentId interno. Llega con el mismo payload en onGameResult y onGameFinished. Parseo fail-closed: si el campo viene ausente, null, vacío o con un tipo inesperado, el modelo expone null y jamás lanza — así una notificación compilada con un HTML viejo (que no emite el campo) o un gajo sin identificador declarado siguen funcionando exactamente igual que antes. Requiere portal actualizado y notificación recompilada para que el valor viaje; con configs anteriores el campo simplemente es null.

0.15.0 #

  • onGameFinished callback (fin de la animación del mini-juego)SouthGamesNotificationOverlay gana onGameFinished: void Function(SouthGamesGameResult)?, espejo exacto de onGameResult. La plantilla de la ruleta ahora emite DOS eventos por giro con el MISMO payload JSON: result: apenas el servidor confirma el giro (usalo para precargar datos con awardId en paralelo a la animación, como hasta hoy) y finished: (nuevo) cuando la rueda se detiene y el resultado quedó a la vista — el momento correcto para navegar a tu propia pantalla o reaccionar en la UI. finished: es solo señal: nunca cierra el overlay, nunca marca impresiones ni eventos, y un payload malformado se ignora con log sin lanzar jamás (mismo contrato fail-closed que result:). Requiere una notificación recompilada con la plantilla vigente para que el evento exista; con un HTML viejo el callback simplemente no se dispara, y un SDK anterior a 0.15.0 ignora finished: sin errores. Ojo: si el usuario cierra la in-app a mitad del giro (el botón de cerrar sigue activo durante la animación), finished: ya no llega para ese giro — no difieras a onGameFinished nada crítico: acredita/decide con onGameResult y usa onGameFinished solo para UI/navegación.

0.14.0 #

  • Mini-juegos sin caps de impresiones/cooldown: las in-apps de mini-juego (isGame en el wire, servido por el portal) ya no se regulan por maxImpressions ni cooldownMinutes — su unica regulacion es la cadencia de giro del servidor (frecuencia de giro + replay idempotente). Las in-apps normales conservan sus caps sin cambios. Requiere portal actualizado (el flag es aditivo: con un portal viejo, los juegos siguen con caps como antes).

0.13.1 #

  • Fix: in-apps mostradas DOS veces cuando SouthGamesNotificationOverlay se suscribia mientras init() seguia corriendo (o tras un re-init de logout): el stream es broadcast y el auto-overlay interno quedaba escuchando junto al widget. El deshabilitado del auto-overlay ahora es persistente (sobrevive a init/re-init) y ademas se re-chequea en cada emision. El widget tambien gana el guard de "misma in-app ya visible" que el auto-overlay siempre tuvo (el re-emit del poll ya no recarga el WebView ni infla impresiones).

0.13.0 #

  • shouldShowNotification — la app decide si se muestra la in-app. Antes de mostrar CADA in-app (poll normal o abierta desde un push vinculado — mismo choke point, el callback no distingue la fuente hoy), el SDK deja que la app host la vete con su propia lógica (pantalla actual, estado del usuario, reglas de negocio): SouthGamesNotificationOverlay(shouldShowNotification: (notification) async => !estoyEnCheckout()). También SouthGamesSDK.instance.shouldShowInApp = ... para apps que usan el auto-overlay (sin widget) — si ambos están definidos, gana el del widget (es el path activo mientras el widget está montado). Semántica completa:
    • Corre ANTES del preload (_onNotification, justo después del check de isDismissed): un "no" no gasta red ni crea WebViews.
    • Es por intento, no permanente: un "no" no descarta la notificación — la próxima vez que se reemita (p. ej. el siguiente poll) se vuelve a preguntar, así que lógica de la app que cambia con el tiempo ("no durante el checkout") se respeta en vivo.
    • REQUISITO DURO — cero rastro con un "no": jamás se emite el evento shown al servidor (trackInAppEvent), jamás se incrementa el contador local de impresiones ni el frequency cap, jamás se persiste nada. Para el sistema, esa entrega no existió.
    • Fail-open estricto: si el callback lanza o no resuelve en 3s, la in-app SE MUESTRA igual (+ debugPrint) — un bug del integrador no puede apagar las campañas de una org en silencio.
    • Sin callback definido (ni widget ni SDK), comportamiento idéntico al de antes: el gate ni se evalúa — cero cambio para las apps que no usan esta feature.

0.12.0 #

  • Fondo transparente en mini-juegos HTML (transparentBackground) — cuando el servidor manda transparentBackground: true para una notificación in-app HTML (hoy, la ruleta de premios con el switch "Fondo transparente" activado en el editor), el SDK deja de pintar cualquier fondo propio detrás del mini-juego: el WebView carga con setBackgroundColor(Colors.transparent) en vez del color/opacidad configurados, y su contenedor pierde tanto el color como la sombra que normalmente dibuja. Lo que queda visible detrás es la app del cliente, atenuada por el velo del modal de siempre (backdropOpacity, sin cambios). Fail-closed: cualquier valor que no sea exactamente true (ausente, false, string, número) se comporta exactamente como hoy — cero cambio de color, cero cambio de decoración. Aplica por igual a los dos caminos de despliegue del SDK (el widget SouthGamesNotificationOverlay y el overlay automático), porque ambos renderizan el mismo NotificationOverlayWidget. La tarjeta de resultado del mini-juego nunca se transparenta — esto solo afecta el fondo detrás del WebView.
  • Caveat: requiere una notificación recompilada con manifiesto de plantilla 1.4.0+. El HTML compilado nunca se recompila solo (ver la guía "Mini-juegos in-app" del dashboard) — una ruleta guardada antes de este flag sigue sirviendo el HTML viejo, sin transparentBackground en absoluto, así que activar el switch en el editor no tiene ningún efecto hasta volver a abrirla y guardarla (eso dispara la recompilación contra la plantilla vigente).
  • Caveat: SDKs anteriores a 0.12.0 ignoran el flag sin errores. Un SDK más viejo no sabe interpretar transparentBackground — el campo simplemente no existe en su modelo — así que el mini-juego se sigue mostrando dentro de su contenedor opaco de siempre, sin ningún error ni degradación visible más allá de perder el efecto transparente.

0.11.2 #

  • La recuperación de clientId obsoleto ahora es compartida entre llamadas concurrentes: si el polling y una apertura de push chocan con el 404 a la vez, ambas esperan la MISMA re-registración y reintentan con el id recuperado. Antes, la segunda rebotaba en el guard de reentrada y logueaba un Notification poll error espurio (se auto-corregía al siguiente tick, pero ensuciaba el log).

0.11.1 #

  • Auto-sanación de clientId obsoleto: si el servidor responde 404 NOT_FOUND (el clientId guardado apunta a un cliente que ya no existe — p. ej. la respuesta de un identify se perdió a mitad de un merge), el SDK descarta el id muerto, se re-registra con la identidad persistida (o el deviceToken) y reintenta la llamada una vez. Aplica a heartbeat, getInAppNotifications (incluido el polling) y getInAppNotificationById (apertura de in-apps vinculadas a push, que antes podía quedar crasheando en loop).
  • El sync de arranque adopta y persiste el clientId que resuelva el servidor (con las lápidas de merge server-side, un id viejo en prefs se corrige solo).

0.11.0 #

  • onGameResult callback (mini-game results)SouthGamesNotificationOverlay gains a new onGameResult: void Function(SouthGamesGameResult)? callback, same pattern as the existing onCtaTap/onNotificationShown. It fires the moment a mini-game running inside an HTML in-app (e.g. the roulette) posts its result over the SouthGamesNotif channel — as soon as the server confirms the spin, before the in-notification result card even animates in — so your app can call your own platform (points, wallet, coupons) in parallel with the ~4s spin animation instead of waiting for it to finish. The new SouthGamesGameResult model exposes notificationId, segmentId, label, isPrize (fail-closed: only true when the server confirms it), awardId (nullable — use it as your idempotency key before crediting anything), and alreadyPlayed (true on a replayed/idempotent delivery). A malformed or unexpected channel message is ignored with a debug log — it never throws and never affects the overlay's own dismiss behavior; the callback simply isn't called for that message.
  • Caveat: only roulette notifications compiled with template 1.3.1+ send the full payload. Compiled HTML never auto-recompiles (see the dashboard's "Mini-juegos in-app" guide), so a roulette saved before 1.3.1 still emits the old, late-only result: message — after the spin animation, and also for local-fallback and replayed draws. Against 0.11.0 that arrives as isPrize: false, awardId: null, notificationId: '', alreadyPlayed: false (fail-safe — never over-credits, but gives nothing to act on). Re-save the notification in the editor to recompile it against the current template and get real values.

0.10.0 #

  • In-apps now preload all assets before showing — the SDK precaches every image the notification will render (legacy imageUrl, image blocks, YouTube video thumbnails) and, for HTML in-apps, pre-creates the WebView and waits for the page to finish loading, BEFORE inserting the overlay. The card appears fully rendered in one shot instead of popping in images progressively. A single global budget of 4 s (configurable via SouthGamesNotificationOverlay(preloadTimeout: ...)) caps the wait: on timeout the in-app is shown anyway with whatever loaded (already-cached images appear instantly; slow ones pop in as they arrive), so a campaign is never lost to a slow network. A notification that never got shown never counts an impression. Applies to both display paths (the SouthGamesNotificationOverlay widget and the automatic overlay). If a newer notification arrives while an older one is still preloading, the newer one wins and the stale preload is discarded silently.

0.9.1 #

  • Dismiss is now session-scoped, not permanent — closing an in-app (or tapping its CTA) hides it only for the current session; on the next app launch it's eligible again. Re-display is governed by maxImpressions and cooldownMinutes as intended. Previously the dismiss flag was persisted and permanently suppressed the notification, so an always in-app with no caps (or its CTA tapped once) would show only once ever — ignoring the frequency config. Set maxImpressions: 1 for genuine show-once, or a cooldownMinutes to space repeats.

0.9.0 #

  • Launch a game campaign from a notification (onLaunchCampaign) — when an in-app or push references a game campaign with the canonical form southgames://campaign/{id} (what the dashboard writes with the new "game campaign" selector), the SDK routes the campaignId to a typed onLaunchCampaign(campaignId) handler instead of the generic onDeeplink. The SDK still never opens the game itself — you decide WHERE to mount it, typically getCampaignById(id) + SouthGamesGameView. Shares the cold-start buffer with onDeeplink. Register via SouthGamesSDK.init(onLaunchCampaign: ...) or the onLaunchCampaign setter. Only the southgames:// scheme is treated as a campaign launch, so your own app schemes (myapp://campaign/x) are never hijacked; if onLaunchCampaign isn't registered, these links fall back to onDeeplink where you can handle them with link.match('campaign/:id').
  • getCampaignById(id) — fetches a single campaign by id (with its signed embedUrl and merged gameConfig), without audience filtering, so a recipient can open a campaign they were explicitly sent even if they're not in its segment. Throws SouthGamesException if the campaign is missing or unavailable (paused/expired). Also exposed: SgDeeplink.campaignId getter and SgLaunchCampaignHandler typedef.
  • Registering onDeeplink and onLaunchCampaign back-to-back via setters (the recommended cold-start pattern) is now safe: router installation is coalesced to a microtask, so a pending cold-start deeplink is delivered once, with both handlers in place, instead of being routed against a half-registered set.
  • In-app background & backdrop opacity — in-app notifications now honor bgOpacity (card background, 0–100) and backdropOpacity (the dim veil behind modal/center/full, 0–100; 0 = no veil) from the dashboard. Defaults preserve the previous look (opaque card, 54% veil). Banners/toasts (top/bottom) never show a veil.

0.8.0 #

  • Unified deeplink pipeline (onDeeplink) — a single handler now receives ALL deeplinks: data.deeplink from tapped pushes and CTA/button actions from in-app notifications. The SDK never opens or interprets the link — it delivers a parsed SgDeeplink (raw string, uri, params, pathSegments, source, match('promo/:id') route helper) so the app routes it with its own navigation/config system. Register via SouthGamesSDK.init(onDeeplink: ...) (delivered after the first frame, so your navigator/router exists) or the onDeeplink setter (delivered immediately, register it when your router is ready). Legacy callbacks (PushConfig.onDeeplinkReceived, onCtaTap) keep working unchanged.
  • Cold-start deeplinks no longer get lost — previously, a push tapped while the app was terminated fired the deeplink callback during init(), before the app's navigator existed, silently dropping it. Deeplinks that arrive before a handler is registered are now buffered and delivered on registration (or retrievable via consumePendingDeeplink()).
  • Push-linked in-app auto-open — tapping a push sent with the dashboard's "also show as in-app" option (data.inAppId) automatically fetches the linked in-app notification and shows it via the overlay, bypassing local dismiss/frequency state (explicit open). Disable with PushConfig(autoOpenLinkedInApp: false). New APIs: getInAppNotificationById(id), SouthGamesPush.getInAppId(message), SouthGamesNotificationManager.forceEmit(...).

0.7.4 #

  • getCampaigns() now sends identity — the request to GET /api/v1/campaigns includes a clientId query param when the SDK has one (set by init()/identify()), or falls back to the externalUserId persisted by the last identify() call. The server uses it to filter campaigns by segment strictly for the current user. Calls without any identity are unchanged (no query params).

0.7.3 #

  • Auto re-identify on app boot — the SDK now persists the identify payload (externalId, email, firstName, lastName, phone) to SharedPreferences after every successful identify() call. On every subsequent init(), _syncClient re-sends that payload to /api/v1/clients/register so the server keeps the client identified even when the integrator app has a persistent session and doesn't re-call identify() on each launch. Fixes the case where users who logged in once stayed anonymous in SouthGames because their session outlived the original identify trigger. Idempotent — the server merges into the same client doc.
  • logout() clears the persisted identify payload alongside the existing clientId reset.

0.7.2 #

  • createPromoCode(...) method — New SDK method to create a single promo code for an end user on a campaign. Uses POST /api/v1/codes; params (discount, expiry, prefix, length, maxDiscountAmount) come from the campaign's defaultCodeConfig, enforced server-side. Returns a CreateCodeResult with code, discountType, discountValue, maxDiscountAmount, maxUses, expiresAt, remainingGenerations, limitPeriod, and idempotent fields.
  • Automatic idempotency — Each call auto-generates a UUID v4 Idempotency-Key header so HTTP-layer retries never produce duplicates. Override by passing idempotencyKey.
  • Webhook — Server dispatches code.created event on successful generation (not on idempotent replays).

0.7.1 #

  • Rankings endpoint — New GET /api/v1/rankings support for leaderboard queries by campaign, game type, or organization scope, with all-time, weekly, and monthly periods.

0.7.0 #

  • Fix API paths — All SDK endpoints now use /api/v1/ (previously /api/sdk/). Resolves 404 errors on all API calls.

0.6.9 #

  • Campaign imageUrlCampaign model now exposes imageUrl (nullable). Gaming campaigns return the marketplace game icon; traditional campaigns return their optional campaign image.

0.6.8 #

  • Unit tests — Added 163 unit tests covering all model fromJson() deserialization (Attribution, Campaign, ClientInfo, CtaButton, GameResult, InAppNotification, Points, PromoCodeResult, TrackEventResult), exceptions, HTTP client (headers, errors, timeouts), SDK config (URL construction, defaults), and notification manager (trigger evaluation, frequency capping, impression tracking).

0.6.7 #

  • Push & in-app event tracking with clientIdtrackInAppEvent and push event tracking now include clientId in the request body, enabling per-user engagement analytics on the server.

0.6.6 #

  • first_open event — Tracks first_open custom event on first device registration, with automatic retry on next launch if the initial attempt fails.
  • Offline event queue — Failed trackEvent calls (network errors, 5xx) are persisted and retried on next app start. Events expire after 24 hours. Max queue size: 50.
  • HTTP timeouts — All API requests now timeout after 30 seconds instead of hanging indefinitely.
  • Concurrent push dismiss flush — Pending push dismiss events are now sent concurrently instead of sequentially on app start.
  • Cleanup — Removed redundant debug logging loop in notification fetching, deduplicated OS detection helper.

0.6.5 #

  • Game view height cap — The game WebView container now uses a maximum of 70% of the screen height, keeping movement buttons and surrounding UI visible.

0.6.4 #

  • Responsive font sizes — Text sizes in in-app notification blocks now scale proportionally to the device screen width (reference: 375pt), clamped between 0.85x–1.3x to avoid extremes on very small or very large screens.
  • Full-width buttons — Single buttons in block-based notifications now stretch to fill the available width.
  • Button text scaling — Button labels use FittedBox to stay on a single line and scale down proportionally when space is limited, ensuring consistent appearance between single and grouped buttons.

0.6.3 #

  • Singleton patternSouthGamesSDK is now a true singleton. Call SouthGamesSDK.init() once, then access the instance from anywhere via SouthGamesSDK.instance. This fixes issues where methods like trackEvent() threw SouthGamesNotInitializedException despite init() having been called.
  • Instance methodsidentify(), trackEvent(), getCampaigns(), play(), redeem(), heartbeat(), registerClient(), getInAppNotifications(), trackInAppEvent(), getPointsBalance(), getPointsHistory(), spendPoints(), earnPoints(), requestPushPermission(), logout(), disableAutoOverlay() are now instance methods accessed via SouthGamesSDK.instance.
  • Static methodsinit(), handleBackgroundMessage(), dispose(), and isInitialized remain static.

0.6.2 #

  • Fix — Fixed State class name mismatch in NotificationOverlayWidget that caused compilation errors.

0.6.1 #

  • Fix — Made NotificationOverlayWidget public so auto-overlay can reference it correctly.

0.6.0 #

  • Auto in-app notifications — In-app notifications now render automatically without requiring SouthGamesNotificationOverlay widget. Just call SouthGamesSDK.init() and notifications appear on top of all routes.
  • Optional callbacks in init()onCtaTap and onNotificationShown can now be passed directly to init() instead of requiring the widget.
  • Static callback settersSouthGamesSDK.onCtaTap and SouthGamesSDK.onNotificationShown setters for apps that configure callbacks after init.
  • Backward compatibleSouthGamesNotificationOverlay widget still works. When used, it automatically disables the auto-overlay to prevent duplicates.

0.5.20 #

  • Global notification overlaySouthGamesNotificationOverlay now uses a global OverlayEntry so notifications always render on top of all routes and dialogs, even when placed inside a specific view instead of MaterialApp.builder.
  • HTTP debug logging — logs status code and response body (first 200 chars) when server returns non-JSON responses, making it easier to diagnose API issues.

0.5.19 #

  • Fix duplicate client creation — SDK now sends persisted clientId on every /register call so the server finds the existing client instead of creating a new one.
  • Sync on every app startinit() now calls the server on each launch to update deviceToken, location, and metadata for existing clients.
  • externalId is now optional in identify() and registerClient() — clients can be registered/updated with just deviceToken or clientId.
  • Server: clientId lookup/api/sdk/clients/register now accepts clientId as a lookup field, with fallback chain: clientIdexternalIdemaildeviceToken.

0.5.18 #

  • Fix 301 redirect on API calls — server-side fix (skipTrailingSlashRedirect) eliminates unnecessary 301 redirects on SDK HTTP requests, reducing latency.

0.5.17 #

  • Server-side in-app notification analytics — the overlay now reports shown, dismissed, and cta_click events to the server via POST /api/sdk/notifications/in-app/events.
  • New SouthGamesSDK.trackInAppEvent() static method for custom event tracking on in-app notifications.

0.5.16 #

  • Disable scroll in HTML notification overlay — set overflow: hidden and height: 100% on both html and body to prevent scrolling inside the WebView modal.

0.5.15 #

  • Fix isHtml detection — notifications with htmlContent present are now treated as HTML even if contentType field is missing from Firestore (backward compatibility for notifications created before the contentType field existed).

0.5.14 #

  • Debug logging for HTML notifications — logs raw server response fields (contentType, htmlContent length, modalSize) and overlay state (isHtml, parsed values) to help diagnose rendering issues.

0.5.13 #

  • Fix HTML notification WebView — replaced Uri.dataFromString (fails on Android with large content) with loadHtmlString for reliable HTML rendering.
  • Auto-detect full HTML documents — if htmlContent already contains <!DOCTYPE> or <html>, it's loaded as-is without wrapping in another HTML shell.
  • WebView controller lifecycle — controller is now stored as state and properly cleaned up on dismiss, preventing stale WebView instances.
  • WebView error logging — added NavigationDelegate with onPageFinished and onWebResourceError for debugging.

0.5.12 #

  • Fix HTML notification rendering — HTML in-app notifications now display correctly with proper width/height constraints using screen-relative sizing (40%/65%/85%/full).
  • Fix modalSize mapping — handles both portal values (small, medium, large) and shorthand (sm, md, lg).
  • Fix Expanded in non-flex parent — replaced with Positioned.fill inside Stack for the WebView widget.

0.5.11 #

  • HTML in-app notifications — notifications with contentType: "html" now render in a WebView instead of native text widgets. Supports custom HTML/CSS content with full viewport control.
  • JS bridge for HTML notifications — HTML content can call SouthGamesNotif.postMessage('dismiss') to dismiss or SouthGamesNotif.postMessage('cta:action') to trigger CTA actions.
  • Modal size support — HTML notifications respect modalSize (sm, md, lg, full) for height control.
  • Auto-polling for in-app notifications — notifications are fetched automatically after init() and identify(), no manual call needed.
  • Overlay subscription retrySouthGamesNotificationOverlay retries subscription in didChangeDependencies if SDK wasn't ready at init.
  • Fixed double evaluation — polling no longer calls evaluateAndEmit twice per fetch cycle.

0.5.10 #

  • WebView bridge fix — games now work correctly in Flutter WebView (fake window.parent injection so SDK methods like close(), getConfig(), submitResult() no longer fail with "Not running inside an iframe").
  • Deduplicated message forwarding — prevent duplicate postMessage handling that caused renderer crashes.
  • Navigator safetyonClose callback is deferred via addPostFrameCallback to avoid Navigator._debugLocked assertion.
  • Mounted guard_respondToGame checks mounted before using the WebView controller, preventing "Bad state" errors on dispose.
  • Removed client-side submitResult throttle — the bridge no longer blocks repeat submissions (backend handles dedup); fixes "Resultado ya enviado" errors on replay.
  • trackEvent auto-resolves clientId — uses the internally stored client ID when no explicit clientId or externalId is passed.

0.5.9 #

  • Fixed synchronization between init() and identify() functions.

0.5.8 #

  • Anonymous device registrationinit() now auto-registers the device as an anonymous client, enabling push notifications from app install without requiring user login.
  • New SouthGamesSDK.clientId getter — exposes the current client ID (anonymous or identified).
  • Automatic client merge — when identify() is called after anonymous registration, the anonymous client's tokens are transferred to the identified client and the anonymous record is deleted.
  • New SouthGamesSDK.logout() method — unregisters the device token from the server, deletes the local FCM token, clears all local state (SharedPreferences), and disposes the SDK.
  • Client ID persistence via SharedPreferences (sg_client_id, sg_anon_client_id) — survives app restarts.
  • Token refresh now works for anonymous clients (re-registers via /api/sdk/clients/register-device).

0.5.7 #

  • Auto-detect and send app version (appVersion) on client registration via package_info_plus.
  • Send SDK version (sdkVersion) on every registration for version tracking.
  • Auto-detect geolocation passively on identify() — uses existing permissions only, never requests.
  • Push notification click and dismiss tracking — clicks tracked on tap, dismisses inferred via SharedPreferences and flushed on next app launch.
  • New dependency: package_info_plus (>=4.0.0), geolocator (>=6.0.0).

0.5.6 #

  • New Points System — spendable currency alongside XP progression.
  • getPointsBalance() — get the current points balance for a user.
  • getPointsHistory() — get the points ledger (earn/spend history).
  • spendPoints() — spend points from a user's balance.
  • earnPoints() — manually trigger a points earn action.
  • New models: PointsBalance, PointsLedgerEntry, SpendPointsResponse, EarnPointsResponse.
  • Game play and code redemption now automatically award points when configured.
  • Webhook dispatch on all major events (game.played, game.won, code.redeemed, client.registered, client.level_up, points.earned, points.spent).

0.5.5 #

  • Auto-detect device locale (e.g. es-CL) and send it on client registration.
  • Fix: add debug logging for device token resolution — prints warnings when tokenProvider is missing, returns null, or throws.
  • RegisterResponse now includes deviceTokenSent field so devs can verify if the token was included.
  • Token refresh re-registration now logs success/failure instead of silently ignoring errors.
  • Guard against empty string tokens being sent to the backend.

0.5.4 #

  • Update README with complete documentation for identify(), tokenProvider, onTokenRefresh, SouthGamesGameView, and manual push registration.
  • Fix class name references from SouthGames to SouthGamesSDK in all docs and examples.

0.5.3 #

  • New identify() method: registers the user and automatically sends the device token on every app start.
  • init() now accepts optional tokenProvider and onTokenRefresh parameters for automatic token management.
  • Automatic re-registration when the device token is refreshed (via onTokenRefresh stream).

0.5.2 #

  • Rename SouthGames class to SouthGamesSDK.
  • Add firstName, lastName, phone, latitude, longitude parameters to registerClient.
  • Add embedUrl and isMarketplaceGame to Campaign model.
  • New SouthGamesGameView widget for running marketplace games in a WebView with full postMessage bridge support.
  • New dependency: webview_flutter: ^4.10.0.

0.5.1 #

  • Fix default base URL to https://southgames.ai.

0.5.0 #

  • Breaking: Remove firebase_messaging as a required dependency — Firebase is no longer needed.
  • registerClient now accepts an optional deviceToken parameter. Pass your own token from any push provider (FCM, APNs, OneSignal, etc.).
  • Removed enablePush and vapidKey parameters from registerClient.
  • SouthGamesPush is now a lightweight base class with registerDeviceToken() for manual token registration.
  • For FCM integration, use the separate southgames_flutter_fcm package (coming soon) or call SouthGames.push.registerDeviceToken() with your own FCM token.

0.4.4 #

  • Upgrade firebase_messaging to ^16.0.0 for compatibility with firebase_core ^4.0.0.

0.4.3 #

  • Restore firebase_messaging to ^15.0.0 for compatibility with firebase_core ^4.0.0.

0.4.2 #

  • Downgrade firebase_messaging dependency from ^14.0.0 to ^13.0.0 for broader compatibility.

0.4.1 #

  • Downgrade firebase_messaging dependency from ^15.0.0 to ^14.0.0 for broader compatibility.

0.4.0 #

  • Breaking: registerClient now requires externalId (your platform's user ID) instead of email as primary identifier.
  • Device token is now obtained internally via FCM — no need to call initPush separately.
  • Server creates and returns clientId — the developer only provides externalId.
  • New enablePush parameter (default true) to opt out of push registration.
  • New vapidKey parameter for Flutter web push token support.
  • Automatic token refresh listener re-registers with externalId on FCM token change.
  • Removed SouthGames.initPush() — push is now handled inside registerClient.
  • Improved OS detection using dart:io Platform with proper web fallback.

0.3.0 #

  • baseUrl is now optional in SouthGames.init() — defaults to https://portal.southgames.ai.
  • orgId now accepts the organization slug (e.g. mi-empresa) in addition to the UUID.

0.2.0 #

  • Add push notification support via Firebase Cloud Messaging.
  • New SouthGamesPush class (lib/src/push.dart).
  • SouthGames.initPush(clientId:, vapidKey:) — request permission, obtain FCM token, and register it automatically.
  • SouthGames.push.onMessage — stream of foreground notifications.
  • SouthGames.push.onMessageOpenedApp — stream of notification taps from background/terminated state.
  • SouthGames.push.getInitialMessage() — check if app was launched from a notification tap.
  • Automatic token re-registration on onTokenRefresh.
  • New dependency: firebase_messaging: ^15.0.0.

0.1.0 #

  • Initial release.
  • Client registration and heartbeat.
  • List active campaigns (spin wheel, scratch card, trivia, slot machine).
  • Play games and receive promo codes on win.
  • Redeem promo codes.
  • Fetch segment-targeted in-app notifications.
0
likes
110
points
709
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Flutter SDK for SouthGames — integrate gamification and loyalty features (spin wheel, scratch cards, trivia, slot machine, promo codes, in-app notifications) into your Flutter app with a single package.

Homepage
Repository (GitHub)
View/report issues

Topics

#gamification #loyalty #games #promotions #notifications

License

MIT (license)

Dependencies

firebase_core, firebase_messaging, flutter, geolocator, http, meta, package_info_plus, shared_preferences, webview_flutter

More

Packages that depend on southgames_flutter