@smartico/public-api 0.0.380 → 0.0.381

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (174) hide show
  1. package/CLAUDE.md +103 -0
  2. package/README.md +32 -10
  3. package/dist/Base/ClassId.d.ts +2 -0
  4. package/dist/Jackpots/JackpotDetails.d.ts +14 -15
  5. package/dist/Jackpots/JackpotPot.d.ts +10 -6
  6. package/dist/Raffle/GetRaffleWonPrizesRequest.d.ts +9 -0
  7. package/dist/Raffle/GetRaffleWonPrizesResponse.d.ts +52 -0
  8. package/dist/Raffle/index.d.ts +2 -0
  9. package/dist/SmarticoAPI.d.ts +6 -1
  10. package/dist/SmarticoLib/index.d.ts +5 -1
  11. package/dist/WSAPI/WSAPIAvatars.d.ts +267 -49
  12. package/dist/WSAPI/WSAPIBonuses.d.ts +224 -10
  13. package/dist/WSAPI/WSAPIGamePick.d.ts +538 -253
  14. package/dist/WSAPI/WSAPIGeneral.d.ts +156 -14
  15. package/dist/WSAPI/WSAPIInbox.d.ts +547 -58
  16. package/dist/WSAPI/WSAPIJackpots.d.ts +292 -57
  17. package/dist/WSAPI/WSAPILeaderBoard.d.ts +127 -13
  18. package/dist/WSAPI/WSAPIMiniGames.d.ts +465 -49
  19. package/dist/WSAPI/WSAPIRaffles.d.ts +576 -52
  20. package/dist/WSAPI/WSAPITournaments.d.ts +3 -3
  21. package/dist/WSAPI/WSAPITypes.d.ts +243 -132
  22. package/dist/WSAPI/WSAPIUser.d.ts +193 -43
  23. package/dist/index.js +3409 -615
  24. package/dist/index.js.map +1 -1
  25. package/dist/index.modern.mjs +3391 -608
  26. package/dist/index.modern.mjs.map +1 -1
  27. package/docs/Callbacks.md +162 -0
  28. package/docs/SmarticoObject.md +445 -0
  29. package/docs/Transforms.md +99 -0
  30. package/docs/api/README.md +26 -0
  31. package/docs/api/classes/WSAPIAvatars.md +282 -54
  32. package/docs/api/classes/WSAPIBonuses.md +233 -12
  33. package/docs/api/classes/WSAPIClans.md +380 -10
  34. package/docs/api/classes/WSAPIGamePick.md +555 -26
  35. package/docs/api/classes/WSAPIGeneral.md +165 -16
  36. package/docs/api/classes/WSAPIInbox.md +588 -64
  37. package/docs/api/classes/WSAPIJackpots.md +320 -66
  38. package/docs/api/classes/WSAPILeaderBoard.md +133 -15
  39. package/docs/api/classes/WSAPIMiniGames.md +501 -64
  40. package/docs/api/classes/WSAPIMissions.md +58 -79
  41. package/docs/api/classes/WSAPIRaffles.md +647 -69
  42. package/docs/api/classes/WSAPIStore.md +83 -108
  43. package/docs/api/classes/WSAPITournaments.md +495 -28
  44. package/docs/api/classes/WSAPIUser.md +520 -83
  45. package/docs/api/documents/Callbacks.md +162 -0
  46. package/docs/api/documents/SmarticoObject.md +445 -0
  47. package/docs/api/documents/Transforms.md +99 -0
  48. package/docs/api/enumerations/BonusStatus-1.md +11 -6
  49. package/docs/api/enumerations/JoinClanErrorCode.md +81 -0
  50. package/docs/api/enumerations/TournamentRegistrationError.md +12 -0
  51. package/docs/api/functions/clanTournamentPlayersTransform.md +13 -0
  52. package/docs/api/interfaces/AvatarCustomized.md +25 -0
  53. package/docs/api/interfaces/AvatarDefinition.md +94 -0
  54. package/docs/api/interfaces/AvatarPrompt.md +45 -0
  55. package/docs/api/interfaces/BonusMetaMap-1.md +4 -1
  56. package/docs/api/interfaces/BonusTemplateMetaMap-1.md +9 -4
  57. package/docs/api/interfaces/Clan.md +4 -0
  58. package/docs/api/interfaces/ClanInfo.md +109 -0
  59. package/docs/api/interfaces/ClanMember.md +53 -0
  60. package/docs/api/interfaces/ClanTournamentPlayerRaw.md +67 -0
  61. package/docs/api/interfaces/GemsDiamondsLog.md +43 -0
  62. package/docs/api/interfaces/GetClanInfoResponse.md +61 -0
  63. package/docs/api/interfaces/GetClanTournamentPlayersResponse.md +81 -0
  64. package/docs/api/interfaces/GetRaffleWonPrizesRequest.md +59 -0
  65. package/docs/api/interfaces/GetRaffleWonPrizesResponse.md +95 -0
  66. package/docs/api/interfaces/InboxMarkMessageAction.md +10 -2
  67. package/docs/api/interfaces/JackpotDetails.md +14 -15
  68. package/docs/api/interfaces/JackpotPot.md +9 -6
  69. package/docs/api/interfaces/LeaderBoardDetailsT.md +14 -8
  70. package/docs/api/interfaces/LeaderBoardUserT.md +8 -5
  71. package/docs/api/interfaces/LeaderBoardsRewardsT.md +7 -0
  72. package/docs/api/interfaces/PointsLog.md +43 -0
  73. package/docs/api/interfaces/RaffleWonPrize.md +59 -0
  74. package/docs/api/interfaces/RaffleWonPrizePublicMeta.md +27 -0
  75. package/docs/api/interfaces/RaffleWonPrizeUser.md +43 -0
  76. package/docs/api/interfaces/TAchCategory.md +2 -7
  77. package/docs/api/interfaces/TAvatarCustomized.md +4 -4
  78. package/docs/api/interfaces/TAvatarDefinition.md +13 -14
  79. package/docs/api/interfaces/TAvatarPrompt.md +6 -6
  80. package/docs/api/interfaces/TBonus.md +16 -8
  81. package/docs/api/interfaces/TBuyStoreItemResult.md +4 -29
  82. package/docs/api/interfaces/TClaimBonusResult.md +5 -5
  83. package/docs/api/interfaces/TClan.md +8 -4
  84. package/docs/api/interfaces/TClanInfo.md +47 -0
  85. package/docs/api/interfaces/TClanJoinResult.md +11 -1
  86. package/docs/api/interfaces/TClanTournamentPlayer.md +55 -0
  87. package/docs/api/interfaces/TClanTournamentPlayersResult.md +27 -0
  88. package/docs/api/interfaces/TClans.md +3 -1
  89. package/docs/api/interfaces/TGetTranslations.md +4 -0
  90. package/docs/api/interfaces/TInboxMessage.md +14 -6
  91. package/docs/api/interfaces/TInboxMessageBody.md +18 -12
  92. package/docs/api/interfaces/TLevel.md +17 -20
  93. package/docs/api/interfaces/TLevelCurrent.md +19 -18
  94. package/docs/api/interfaces/TMiniGamePlayBatchResult.md +14 -6
  95. package/docs/api/interfaces/TMiniGamePlayResult.md +9 -4
  96. package/docs/api/interfaces/TMissionClaimRewardResult.md +1 -9
  97. package/docs/api/interfaces/TMissionOptInResult.md +1 -5
  98. package/docs/api/interfaces/TMissionOrBadge.md +4 -7
  99. package/docs/api/interfaces/TRaffleOptinResponse.md +4 -2
  100. package/docs/api/interfaces/TSegmentCheckResult.md +10 -0
  101. package/docs/api/interfaces/TSetAvatarResult.md +3 -3
  102. package/docs/api/interfaces/TStoreItem.md +3 -13
  103. package/docs/api/interfaces/TTournament.md +1 -1
  104. package/docs/api/interfaces/TTournamentDetailed.md +1 -1
  105. package/docs/api/interfaces/TTournamentRegistrationResult.md +4 -2
  106. package/docs/api/interfaces/TUICustomSection.md +23 -19
  107. package/docs/api/interfaces/TUserProfile.md +18 -16
  108. package/docs/api/interfaces/TransformedRaffleClaimPrizeResponse.md +6 -2
  109. package/docs/api/interfaces/UserLevelExtraCountersT.md +9 -2
  110. package/docs/api/type-aliases/ActivityLogEntry.md +3 -0
  111. package/docs/native/ADDING_METHODS.md +7 -2
  112. package/docs/native/PROTOCOL.md +337 -0
  113. package/docs/ui/avatars/UIGuide_getAvatarPrompts.md +100 -0
  114. package/docs/ui/avatars/UIGuide_getAvatarsCustomized.md +90 -0
  115. package/docs/ui/avatars/UIGuide_getAvatarsList.md +105 -0
  116. package/docs/ui/avatars/UIGuide_setAvatar.md +118 -0
  117. package/docs/ui/bonuses/UIGuide_claimBonus.md +144 -0
  118. package/docs/ui/bonuses/UIGuide_getBonuses.md +176 -0
  119. package/docs/ui/gamepick/UIGuide_gamePickGetActiveRound.md +99 -0
  120. package/docs/ui/gamepick/UIGuide_gamePickGetActiveRounds.md +76 -0
  121. package/docs/ui/gamepick/UIGuide_gamePickGetBoard.md +81 -0
  122. package/docs/ui/gamepick/UIGuide_gamePickGetGameInfo.md +78 -0
  123. package/docs/ui/gamepick/UIGuide_gamePickGetHistory.md +55 -0
  124. package/docs/ui/gamepick/UIGuide_gamePickGetRoundInfoForUser.md +71 -0
  125. package/docs/ui/gamepick/UIGuide_gamePickGetUserInfo.md +64 -0
  126. package/docs/ui/gamepick/UIGuide_gamePickSubmitSelection.md +103 -0
  127. package/docs/ui/gamepick/UIGuide_gamePickSubmitSelectionQuiz.md +67 -0
  128. package/docs/ui/general/UIGuide_getCustomSections.md +137 -0
  129. package/docs/ui/general/UIGuide_getRelatedItemsForGame.md +140 -0
  130. package/docs/ui/inbox/UIGuide_deleteInboxMessage.md +135 -0
  131. package/docs/ui/inbox/UIGuide_getInboxMessageBody.md +133 -0
  132. package/docs/ui/inbox/UIGuide_getInboxMessages.md +186 -0
  133. package/docs/ui/inbox/UIGuide_markInboxMessageAsRead.md +122 -0
  134. package/docs/ui/inbox/UIGuide_markUnmarkInboxMessageAsFavorite.md +84 -0
  135. package/docs/ui/jackpots/UIGuide_getJackpotEligibleGames.md +73 -0
  136. package/docs/ui/jackpots/UIGuide_getJackpotWinners.md +83 -0
  137. package/docs/ui/jackpots/UIGuide_jackpotGet.md +138 -0
  138. package/docs/ui/jackpots/UIGuide_jackpotOptIn.md +85 -0
  139. package/docs/ui/jackpots/UIGuide_jackpotOptOut.md +65 -0
  140. package/docs/ui/leaderboard/UIGuide_getLeaderBoard.md +166 -0
  141. package/docs/ui/minigames/UIGuide_getMiniGames.md +153 -0
  142. package/docs/ui/minigames/UIGuide_getMiniGamesHistory.md +90 -0
  143. package/docs/ui/minigames/UIGuide_playMiniGame.md +150 -0
  144. package/docs/ui/minigames/UIGuide_playMiniGameBatch.md +128 -0
  145. package/docs/ui/raffles/UIGuide_claimRafflePrize.md +99 -0
  146. package/docs/ui/raffles/UIGuide_getRaffleDrawRun.md +117 -0
  147. package/docs/ui/raffles/UIGuide_getRaffleDrawRunsHistory.md +92 -0
  148. package/docs/ui/raffles/UIGuide_getRaffleWonPrizes.md +120 -0
  149. package/docs/ui/raffles/UIGuide_getRaffles.md +175 -0
  150. package/docs/ui/raffles/UIGuide_requestRaffleOptin.md +114 -0
  151. package/docs/ui/user/UIGuide_getActivityLog.md +130 -0
  152. package/docs/ui/user/UIGuide_getLevels.md +47 -42
  153. package/package.json +1 -1
  154. package/src/Base/ClassId.ts +2 -0
  155. package/src/Jackpots/JackpotDetails.ts +14 -15
  156. package/src/Jackpots/JackpotPot.ts +10 -6
  157. package/src/Raffle/GetRaffleWonPrizesRequest.ts +12 -0
  158. package/src/Raffle/GetRaffleWonPrizesResponse.ts +56 -0
  159. package/src/Raffle/index.ts +3 -1
  160. package/src/SmarticoAPI.ts +14 -1
  161. package/src/SmarticoLib/index.ts +4 -0
  162. package/src/WSAPI/WSAPIAvatars.ts +267 -49
  163. package/src/WSAPI/WSAPIBonuses.ts +224 -10
  164. package/src/WSAPI/WSAPIGamePick.ts +538 -253
  165. package/src/WSAPI/WSAPIGeneral.ts +156 -14
  166. package/src/WSAPI/WSAPIInbox.ts +545 -56
  167. package/src/WSAPI/WSAPIJackpots.ts +297 -61
  168. package/src/WSAPI/WSAPILeaderBoard.ts +127 -13
  169. package/src/WSAPI/WSAPIMiniGames.ts +465 -49
  170. package/src/WSAPI/WSAPIRaffles.ts +592 -64
  171. package/src/WSAPI/WSAPITournaments.ts +3 -3
  172. package/src/WSAPI/WSAPITypes.ts +243 -132
  173. package/src/WSAPI/WSAPIUser.ts +193 -43
  174. package/tsconfig.json +9 -1
@@ -0,0 +1,140 @@
1
+ # UI Guide — `getRelatedItemsForGame`
2
+
3
+ ## Overview
4
+ - Returns the missions and tournaments that reference a casino / sportsbook
5
+ game in the operator's catalog.
6
+ - Use to surface "X missions / Y tournaments feature this game" badges on
7
+ game tiles, lobby cards, or dedicated game detail screens.
8
+ - Server applies user-eligibility filtering — results are already scoped to
9
+ what this user should see.
10
+ - No cache; every call is a live round-trip.
11
+
12
+ ## Trigger points
13
+
14
+ When to call:
15
+
16
+ | Surface | Trigger |
17
+ |---|---|
18
+ | Game tile in lobby | Hover (desktop) / focus (mobile) — debounce 300 ms |
19
+ | Game detail page | Mount |
20
+ | Tournament detail "Related Games" panel | Mount (the reverse direction — `tournament.related_games[]` lists games, this method goes game → tournament) |
21
+ | Mission detail panel | Mount alongside the mission's own data |
22
+
23
+ Do NOT call on every game tile render — the response is not cached and
24
+ network roundtrips per tile will overwhelm the connection. Use lazy / hover-
25
+ triggered loading.
26
+
27
+ ## Result rendering
28
+
29
+ The response has two arrays:
30
+
31
+ ```ts
32
+ {
33
+ achievements: UserAchievement[]; // missions (same shape as getMissions)
34
+ tournaments?: Tournament[]; // tournaments (same shape as getTournamentsList)
35
+ }
36
+ ```
37
+
38
+ Both may be empty / undefined. The shape mirrors `getMissions` and
39
+ `getTournamentsList` — no reduced subset, no different field semantics.
40
+
41
+ ### Quick badge (game tile overlay)
42
+
43
+ For a small overlay on a game tile:
44
+
45
+ ```ts
46
+ const r = await window._smartico.api.getRelatedItemsForGame(gameId);
47
+ const total = (r.achievements?.length ?? 0) + (r.tournaments?.length ?? 0);
48
+
49
+ if (total > 0) {
50
+ console.log('[smartico] show a "+' + total + '" badge on the game tile');
51
+ }
52
+ ```
53
+
54
+ The default Smartico UI uses a small accent badge with the total count and an
55
+ icon hinting at gamification (typically a star or trophy).
56
+
57
+ ### Full panel (game detail / mission / tournament context)
58
+
59
+ For a detail panel:
60
+
61
+ | Section | Source | Layout |
62
+ |---|---|---|
63
+ | "Missions featuring this game" | `r.achievements` | Vertical list, mission card per item |
64
+ | "Tournaments featuring this game" | `r.tournaments` | Horizontal scroll or vertical list, tournament card per item |
65
+
66
+ Use the same card layouts as `getMissions` (see
67
+ [`getMissions`](../../api/classes/WSAPIMissions.md#getmissions) UI guide) and
68
+ `getTournamentsList` (see
69
+ [`getTournamentsList`](../../api/classes/WSAPITournaments.md#gettournamentslist)
70
+ UI guide). Field semantics are identical.
71
+
72
+ ## Empty results
73
+
74
+ Empty results are the default for most games — operators typically link
75
+ missions / tournaments to specific featured games, not the entire catalog.
76
+
77
+ UI options:
78
+
79
+ - **Game tile overlay**: hide the badge entirely (don't render an empty
80
+ "0 missions" placeholder).
81
+ - **Detail panel**: omit the panel when both arrays are empty. The default
82
+ Smartico UI shows a small "No related missions or tournaments" message
83
+ only when the user explicitly opens a dedicated "Related" tab and it's
84
+ empty.
85
+
86
+ ## Refresh
87
+
88
+ - **No cache** — every call hits the server.
89
+ - Re-call after:
90
+ - The user opts into or completes a related mission (to refresh the
91
+ progress/status displayed on the badge).
92
+ - The user navigates between games.
93
+ - Do NOT build a consumer-side cache for UI-critical paths — missions and
94
+ tournaments are live-operated state and stale data would mis-render
95
+ eligibility.
96
+
97
+ ## Loading state
98
+
99
+ The call typically returns in 100–300 ms. UI patterns:
100
+
101
+ - **Game tile overlay**: render the tile immediately; show the badge once
102
+ the call resolves. No spinner.
103
+ - **Detail panel**: show a skeleton row layout (1–3 placeholder rows) while
104
+ loading.
105
+
106
+ ## Error handling
107
+
108
+ The method returns the raw protocol response. Inspect transport-level
109
+ exceptions via try/catch:
110
+
111
+ ```ts
112
+ try {
113
+ const r = await window._smartico.api.getRelatedItemsForGame('gold-slot2');
114
+ // ...
115
+ } catch (e) {
116
+ console.error('[smartico] related items fetch failed — hide the related badge:', e);
117
+ }
118
+ ```
119
+
120
+ ## Visitor mode
121
+
122
+ Documented as supported via `_smartico.vapi(lang).getRelatedItemsForGame(...)`,
123
+ but in practice the server may require an authenticated user for the
124
+ eligibility filtering to work. Visitor calls have been seen to fail in some
125
+ deployments — test the specific deployment before relying on it.
126
+
127
+ ## Mobile vs desktop
128
+
129
+ - **Mobile**: overlay badges on tiles; tap-through to a sheet with the
130
+ related items.
131
+ - **Desktop**: hover-overlay or always-visible badges; click to open the
132
+ related panel in a sidebar or modal.
133
+
134
+ ## Performance
135
+
136
+ - One round-trip per game ID. No cache.
137
+ - Debounce hover-triggered calls (300 ms) to avoid spurious requests when
138
+ the user moves the cursor across tiles.
139
+ - Pre-fetch on game tile mount only if the lobby is small (< 20 tiles);
140
+ otherwise lazy-load on user interest.
@@ -0,0 +1,135 @@
1
+ # UI Guide — `deleteInboxMessage` (and `deleteAllInboxMessages`)
2
+
3
+ ## Overview
4
+ - Soft-deletes inbox messages. Two variants:
5
+ - **Single**: `deleteInboxMessage(messageGuid)` — drop one message.
6
+ - **Bulk**: `deleteAllInboxMessages()` — drop every message
7
+ globally.
8
+ - Both return `{ err_code, err_message }`. `err_code === 0` =
9
+ success.
10
+ - **No undelete via the SDK** — deletion is server-recorded but
11
+ the user cannot recover the message. Recovery requires operator
12
+ intervention.
13
+ - Both are idempotent at the server.
14
+
15
+ ## When to call
16
+
17
+ **Single**: from a delete affordance per row:
18
+
19
+ | Trigger | Platform | Notes |
20
+ |---|---|---|
21
+ | Trash icon click (hover-visible) | Desktop | |
22
+ | Swipe past threshold (~75 px) | Mobile | Left or right swipe, with CSS `translateX(±100%)` |
23
+ | Delete button in detail panel | Desktop full-page | When the message is open in the right-side panel |
24
+
25
+ **No confirm dialog** for the single-message delete — the action
26
+ is fast and the user's intent is explicit (they clicked / swiped).
27
+
28
+ **Bulk**: typically in a header overflow menu under "Delete all
29
+ messages". **Surface a confirm dialog** for the bulk variant —
30
+ this is destructive at scale and there is no undo.
31
+
32
+ ```ts
33
+ // Single — swipe handler
34
+ const onDelete = async (msg: TInboxMessage) => {
35
+ // Optimistic: drop from local list immediately.
36
+ removeFromLocalList(msg.message_guid);
37
+
38
+ const r = await window._smartico.api.deleteInboxMessage(msg.message_guid);
39
+ if (r.err_code !== 0) {
40
+ // Revert.
41
+ restoreToLocalList(msg);
42
+ console.error('[smartico] delete failed, restored:', r.err_message);
43
+ } else {
44
+ console.log('[smartico] message deleted — show "Message deleted" toast (no undo affordance)');
45
+ }
46
+ };
47
+
48
+ // Bulk — after confirm dialog
49
+ const onDeleteAll = async () => {
50
+ const previousMessages = messages;
51
+ setMessages([]);
52
+
53
+ const r = await window._smartico.api.deleteAllInboxMessages();
54
+ if (r.err_code !== 0) {
55
+ setMessages(previousMessages);
56
+ console.error('[smartico] delete-all failed, restored:', r.err_message);
57
+ } else {
58
+ console.log('[smartico] all messages deleted — inbox cleared, badge auto-drops to 0');
59
+ }
60
+ };
61
+ ```
62
+
63
+ ## Loading state
64
+
65
+ - **Single**: skip the explicit loading state — the row animates
66
+ out (slide ~300 ms) and the perceived feedback is the row
67
+ disappearing.
68
+ - **Bulk**: show loading dots on the "Delete all" button while
69
+ pending; disable the button to prevent double-clicks.
70
+
71
+ ## Optimistic update
72
+
73
+ Recommended for both variants:
74
+
75
+ - **Single**: drop the row from local state before the call.
76
+ Revert by re-adding it at the same index if the call fails.
77
+ - **Bulk**: replace `messages` with `[]` immediately. Revert by
78
+ restoring the snapshot if the call fails.
79
+
80
+ The risk of a revert is low — the server is idempotent and the
81
+ soft-delete operation rarely fails outside of transport issues.
82
+
83
+ ## Refresh behavior
84
+
85
+ - `getInboxMessages` `onUpdate` does NOT fire on delete — the SDK
86
+ doesn't auto-refresh the list.
87
+ - The unread badge auto-updates via the user-properties channel
88
+ (any deleted unread messages drop from the count).
89
+ - For bulk delete, the badge drops to 0 (or near 0 if a new
90
+ message arrived mid-operation).
91
+
92
+ ## Idempotency
93
+
94
+ Both variants are idempotent at the server:
95
+
96
+ - `deleteInboxMessage(alreadyDeletedGuid)` → returns
97
+ `err_code === 0`. Already-deleted messages are filtered out
98
+ server-side, so the server sees no work to do.
99
+ - `deleteAllInboxMessages()` on an empty inbox → returns
100
+ `err_code === 0`. No-op.
101
+
102
+ ## No undo
103
+
104
+ There is **no undelete path via the SDK**. The default Smartico
105
+ UI does NOT offer an undo affordance after delete. If your
106
+ product surface needs an undo pattern, implement it
107
+ client-side using an optimistic deferred call: stash the row in
108
+ local state, show a "Message deleted [Undo]" toast for ~5 s,
109
+ and only fire `deleteInboxMessage` when the toast dismisses.
110
+
111
+ ## Error handling
112
+
113
+ | `err_code` | Action |
114
+ |---|---|
115
+ | `0` (success) | Drop locally; show "Message deleted" toast (single) or "All messages deleted" toast (bulk). |
116
+ | Other non-zero | Revert local state (restore row(s)); show non-blocking error toast with `err_message`. Allow retry. |
117
+
118
+ ## Animations / transitions
119
+
120
+ - **Single delete (swipe)**: row slides off-screen
121
+ (`translateX: ±100%`, 300 ms ease-out), then collapses height
122
+ (200 ms).
123
+ - **Single delete (click)**: row collapses height + fades opacity
124
+ (200 ms each).
125
+ - **Bulk delete**: list fades to empty state animation.
126
+
127
+ ## Mobile vs desktop
128
+
129
+ - **Trigger**: mobile = swipe (left or right past threshold);
130
+ desktop = hover-visible trash icon.
131
+ - **RTL**: swipe direction flips with `direction: rtl` —
132
+ `translateX(+100%)` becomes the swipe-left animation.
133
+ - **Bulk delete UI**: mobile = in the overflow menu;
134
+ desktop = inline in the inbox header (still behind a confirm
135
+ dialog).
@@ -0,0 +1,133 @@
1
+ # UI Guide — `getInboxMessageBody`
2
+
3
+ ## Overview
4
+ - Returns the rich body (title, preview, icon, action, html_body,
5
+ buttons, custom_data) for one message identified by its
6
+ `message_guid`.
7
+ - Fetched from a CDN, NOT over the WebSocket — latency depends on
8
+ CDN proximity. No SDK-level cache (browser HTTP cache may apply
9
+ via CDN Cache-Control headers).
10
+ - Use in two contexts: (a) co-fetched with the envelope list for
11
+ rendering list-row titles + previews, (b) on-demand for a detail
12
+ view.
13
+
14
+ ## Detail view layout
15
+
16
+ Top-to-bottom layout for a full message detail:
17
+
18
+ 1. **Icon** — `body.icon` at a larger render size (typically
19
+ 128×128 px to match the source). Center-aligned at top.
20
+ 2. **Title** — `body.title`, primary heading.
21
+ 3. **Body content** — branches on `body.action`:
22
+ - `'dp:inbox'` → render `body.html_body` in a sandboxed
23
+ iframe (see "Rich vs simple" below).
24
+ - any other value → render `body.preview_body` as a formatted
25
+ text block.
26
+ 4. **Buttons** — `body.buttons[]` (max 2) — only when
27
+ `action === 'dp:inbox'`. Render side-by-side or stacked
28
+ depending on width.
29
+ 5. **CTA** — single primary CTA driving `body.action` when the
30
+ message has no `html_body` (i.e. `action !== 'dp:inbox'`).
31
+
32
+ ## Rich vs simple messages
33
+
34
+ | `action` value | Shape | Render |
35
+ |---|---|---|
36
+ | `'dp:inbox'` | Rich: has `html_body`, optional `buttons[]` (max 2) | Sandboxed iframe + button row |
37
+ | Anything else (`'dp:gf_missions'`, `'https://...'`, etc.) | Simple: title + preview only | Title + `preview_body` + single CTA wired to `action` |
38
+
39
+ The transform inside the SDK enforces this — if the underlying CDN
40
+ payload has `html_body` or `buttons` but the action isn't
41
+ `'dp:inbox'`, those fields are stripped before reaching the SDK
42
+ consumer. Don't try to render `html_body` for non-`'dp:inbox'`
43
+ messages — it will be `undefined`.
44
+
45
+ ## Sandboxed iframe (for `html_body`)
46
+
47
+ `html_body` is operator-supplied HTML. **Render in a sandboxed
48
+ iframe** to prevent script execution in your host page:
49
+
50
+ ```ts
51
+ // Recommended pattern (data: URL, no script execution).
52
+ const html = sanitize(body.html_body);
53
+ const iframe = document.createElement('iframe');
54
+ iframe.sandbox = ''; // no extra permissions
55
+ iframe.srcdoc = html;
56
+ container.appendChild(iframe);
57
+ ```
58
+
59
+ The default Smartico UI uses an injected ResizeObserver script to
60
+ auto-size the iframe height to its content. If you replicate this,
61
+ include the script inside `srcdoc` (not as a sandbox permission) so
62
+ the host page stays isolated.
63
+
64
+ Wrap any deep-links found inside the HTML body with a click handler
65
+ that calls `_smartico.dp(href)` rather than letting the native
66
+ navigation execute — this keeps deep-link routing consistent.
67
+
68
+ ## Action button decision matrix
69
+
70
+ | Condition | Button label | Click behavior |
71
+ |---|---|---|
72
+ | `body.action === 'dp:inbox'` AND no `buttons` | (no top-level CTA) | Action buttons (if any) are the primary affordances. The "open this message" deep-link is satisfied by being in the detail view already. |
73
+ | `body.action === 'dp:inbox'` AND `buttons` non-empty | Render each `button.text` | Click handler executes `_smartico.dp(button.action)` AND fires {@link reportClickEvent} with `action: button.action`. |
74
+ | `body.action !== 'dp:inbox'` (simple message) | Single CTA (operator usually puts text in `preview_body`; consumer may default to "Open") | Click handler executes `_smartico.dp(body.action)` AND fires {@link reportClickEvent} with `action: body.action`. |
75
+
76
+ The default Smartico UI does NOT render an explicit "Close" or
77
+ "Back" button inside the detail body — modal/sheet chrome handles
78
+ that.
79
+
80
+ ## Telemetry pairing
81
+
82
+ - Fire {@link reportImpressionEvent} when the detail view opens (or
83
+ the message first becomes visible).
84
+ - Fire {@link reportClickEvent} when any action button or CTA is
85
+ tapped. Pass the deep-link / URL as the `action` argument so
86
+ operator analytics can attribute the click to the specific link.
87
+
88
+ ## `custom_data`
89
+
90
+ Operator-defined per-message data. The SDK auto-parses
91
+ JSON-looking strings, so at runtime `custom_data` is `any` despite
92
+ the `string` type. Guard with `typeof custom_data === 'object'`
93
+ before property access; treat non-object values as raw strings.
94
+
95
+ Common consumer patterns:
96
+ - A custom badge / category-color derived from a `custom_data.tag`
97
+ field.
98
+ - A deep-link override for specific message types.
99
+ - Operator-defined A/B variant identifier.
100
+
101
+ ## Empty / loading / error states
102
+
103
+ - **Loading**: render a skeleton block in the detail panel — icon
104
+ placeholder, title placeholder, 3–4 lines of preview placeholder.
105
+ - **Error**: CDN fetch failures should fall back to displaying the
106
+ envelope's `sent_date` and a "Message body unavailable, please
107
+ try again" placeholder. Allow retry.
108
+
109
+ ## Animations / transitions
110
+
111
+ - **Detail open (mobile inline)**: 0.5 s height transition.
112
+ - **Detail open (desktop panel)**: 150 ms fade.
113
+ - **Iframe height adjust** (rich body): smooth height transition
114
+ via ResizeObserver — avoid jitter on small content changes.
115
+
116
+ ## Mobile vs desktop
117
+
118
+ - **Modal style**: mobile inline expand or full-screen sheet;
119
+ desktop right-panel.
120
+ - **Icon size**: desktop ~128 px; mobile may scale down to 64 px
121
+ to save vertical space.
122
+ - **Button layout**: side-by-side on desktop; stacked on mobile
123
+ for thumb reach.
124
+
125
+ ## Performance
126
+
127
+ - Each call is a CDN HTTP GET. For a list of 20 messages, parallel
128
+ body fetches via `Promise.all()` complete in roughly one CDN
129
+ round-trip time.
130
+ - Cache bodies in your application state — the SDK does not cache
131
+ them, and re-opening a message would otherwise refetch.
132
+ - Browser HTTP cache (Cache-Control from the CDN) provides some
133
+ free caching on repeat fetches within a session.
@@ -0,0 +1,186 @@
1
+ # UI Guide — `getInboxMessages`
2
+
3
+ ## Overview
4
+ - Returns the lightweight `TInboxMessage[]` envelopes — newest first.
5
+ - For each visible message, fetch the rich body via
6
+ [`getInboxMessageBody`](../../api/classes/WSAPIInbox.md#getinboxmessagebody)
7
+ separately. The list type alone is NOT enough to render the title
8
+ / preview / icon.
9
+ - `onUpdate` fires only when a NEW message is pushed by the server.
10
+ Mutations (`markRead`, `favorite`, `delete`) do NOT auto-refresh
11
+ the list — re-call or update local state.
12
+
13
+ ## List view organization
14
+
15
+ The default Smartico UI presents inbox messages in a **single
16
+ scrollable list** with two filter tabs at the top:
17
+
18
+ | Tab | Filter |
19
+ |---|---|
20
+ | **All** | No filter — all messages |
21
+ | **Favorite** | `onlyFavorite: true` |
22
+
23
+ `InboxCategories` (`General` / `Platform` / `Personal`) and
24
+ `InboxReadStatus` are exposed via the SDK but NOT surfaced as tabs in
25
+ the default UI. Custom UIs may add them as additional tabs or filter
26
+ chips.
27
+
28
+ **Sort order**: server-driven, newest `sent_date` first. No
29
+ client-side re-sort.
30
+
31
+ **Pagination**: 20 messages per page. For load-more pagination,
32
+ advance `from` by 20 on each subsequent call.
33
+
34
+ ## Item card / row
35
+
36
+ Fields rendered per row (combining `TInboxMessage` envelope with
37
+ the pre-fetched `TInboxMessageBody`):
38
+
39
+ | Field | Source | Notes |
40
+ |---|---|---|
41
+ | Icon | `body.icon` (128×128 px) | CSS `background-image`. Fallback to a generic message icon if missing. |
42
+ | Title | `body.title` | Primary text. |
43
+ | Preview | `body.preview_body` | Single-line excerpt. |
44
+ | Sent date | `envelope.sent_date` | Render as relative time ("2h ago", "Yesterday", "12 Jun"). |
45
+ | Unread dot | `envelope.read === false` | Filled colored dot. Hide when read. |
46
+ | Favorite star | `envelope.favorite` | Filled star icon when favorited; outline otherwise. |
47
+ | Delete affordance | hover (desktop) / swipe (mobile) | See "Delete UX". |
48
+ | "Read more" link | shown when `body.html_body` exists | Triggers inline expand. |
49
+
50
+ **The list needs pre-fetched bodies** — call
51
+ [`getInboxMessageBody`](../../api/classes/WSAPIInbox.md#getinboxmessagebody)
52
+ for each envelope before rendering. The default Smartico UI batches
53
+ these fetches alongside the list. Cache bodies in your application
54
+ state to avoid re-fetching on scroll.
55
+
56
+ ## Detail view / expand
57
+
58
+ Two rendering modes per device:
59
+
60
+ - **Mobile / widget**: tap the row → message body expands inline
61
+ (CSS transition ~0.5 s). The `html_body` (if present) is rendered
62
+ in a sandboxed iframe with auto-resizing height.
63
+ - **Desktop full-page**: a right-side detail panel renders the
64
+ selected message; the first message auto-opens.
65
+
66
+ Detail-view content top-to-bottom:
67
+
68
+ 1. Icon (larger size).
69
+ 2. Title.
70
+ 3. Either the rich `html_body` (in a sandboxed iframe) OR a
71
+ formatted `preview_body` block, depending on whether
72
+ `body.action === 'dp:inbox'`.
73
+ 4. Up to 2 action buttons (`body.buttons`) — only when
74
+ `action === 'dp:inbox'`.
75
+ 5. Single CTA (when `body.action` is a deep-link / URL other than
76
+ `'dp:inbox'`).
77
+
78
+ **Sandbox the iframe**: the `html_body` is operator-supplied content.
79
+ Render via `<iframe srcdoc>` or a sandboxed `<iframe>` to prevent
80
+ script injection into your host page.
81
+
82
+ ## Auto-mark-as-read
83
+
84
+ The default Smartico UI auto-marks-read when the message detail
85
+ expands (or auto-opens on desktop). Wire it alongside the
86
+ {@link reportImpressionEvent} call so a single user action fires
87
+ both the read mutation and the impression analytic.
88
+
89
+ If you build a viewport-based "auto-read-on-scroll" instead, set a
90
+ threshold (e.g. row visible in viewport for ≥500 ms) — instant
91
+ mark-on-scroll generates noisy impressions.
92
+
93
+ ## Favorite toggle
94
+
95
+ Inline star icon click handler:
96
+
97
+ ```ts
98
+ const onToggleFavorite = async (msg: TInboxMessage) => {
99
+ const target = !msg.favorite;
100
+ console.log('[smartico] optimistically flip star to', target);
101
+ const r = await window._smartico.api.markUnmarkInboxMessageAsFavorite(
102
+ msg.message_guid,
103
+ target,
104
+ );
105
+ if (r.err_code !== 0) {
106
+ console.error('[smartico] favorite failed — revert local state and show error toast:', r.err_message);
107
+ }
108
+ };
109
+ ```
110
+
111
+ Show a brief "Added to favorites" / "Removed from favorites" toast
112
+ on success.
113
+
114
+ ## Delete UX
115
+
116
+ | Trigger | Platform |
117
+ |---|---|
118
+ | Trash-icon click (visible on hover) | Desktop |
119
+ | Swipe left/right past threshold (~75 px) | Mobile |
120
+ | Delete button in detail panel | Desktop full-page |
121
+
122
+ **No confirm dialog** for single-message delete — the action is
123
+ fast. Animate the row out of the list (~300 ms slide), then call
124
+ {@link deleteInboxMessage}. Show "Message deleted" toast.
125
+
126
+ For **mark-all** / **delete-all** mutations, surface a confirm dialog
127
+ (those operations are destructive at scale).
128
+
129
+ ## Image / asset specs
130
+
131
+ | Field | Recommended source | Aspect | Fallback |
132
+ |---|---|---|---|
133
+ | `body.icon` | 128×128 px | 1:1 (square) | Generic message-icon placeholder |
134
+ | `body.html_body` images | (operator-supplied) | (any) | Iframe sandbox handles broken images |
135
+
136
+ ## Empty / loading / error states
137
+
138
+ - **Loading**: render a skeleton list (5–8 placeholder rows).
139
+ - **Empty (all)**: Lottie animation + "No messages yet…" copy.
140
+ - **Empty (favorite filter active)**: "No favorite messages".
141
+ - **Empty (unread filter active)**: "No unread messages".
142
+ - **Error**: keep prior list visible if any; show non-blocking error
143
+ banner; retry on next user action.
144
+
145
+ ## Animations / transitions
146
+
147
+ - **List entry**: stagger fade-in (~30 ms per row) on first render.
148
+ - **New message arrival**: when a push fires `onUpdate`, insert the
149
+ new row at the top with a slide-in animation (~200 ms).
150
+ - **Detail expand (mobile)**: 0.5 s height transition; iframe height
151
+ adjusts via ResizeObserver.
152
+ - **Delete**: 300 ms slide-out + height collapse.
153
+ - **Mark-as-read**: unread dot fades from opacity 1 to 0.
154
+
155
+ ## Refresh
156
+
157
+ `onUpdate` fires ONLY on new-message pushes. After any of the
158
+ mutation methods:
159
+
160
+ - Update local state optimistically (flip `read`/`favorite`, drop
161
+ the row from the list).
162
+ - The unread badge auto-updates via
163
+ [`getUserProfile`](../../api/classes/WSAPIUser.md#getuserprofile)'s
164
+ `core_inbox_unread_count` (push-driven) — no need to manually
165
+ refresh the count.
166
+ - Re-call `getInboxMessages` only if you need the server-canonical
167
+ view (e.g. after a long offline period).
168
+
169
+ ## Mobile vs desktop
170
+
171
+ - **Layout**: mobile is full-width single column with inline detail
172
+ expand; desktop is 50/50 list + detail split panel.
173
+ - **Detail trigger**: mobile = inline expand; desktop = right
174
+ panel with auto-open.
175
+ - **Delete**: mobile = swipe; desktop = hover trash-icon.
176
+ - **Favorite**: mobile = always-visible star; desktop =
177
+ hover-visible.
178
+
179
+ ## Performance
180
+
181
+ - 20 messages per page keeps payloads small. For very long inboxes,
182
+ use the load-more pattern rather than fetching everything.
183
+ - Body fetches are CDN HTTP GETs — batch them in parallel using
184
+ `Promise.all()` for the initial list.
185
+ - Cache message bodies in application state — the SDK does NOT
186
+ cache them, and re-opening a message would otherwise refetch.