@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.
- package/CLAUDE.md +103 -0
- package/README.md +32 -10
- package/dist/Base/ClassId.d.ts +2 -0
- package/dist/Jackpots/JackpotDetails.d.ts +14 -15
- package/dist/Jackpots/JackpotPot.d.ts +10 -6
- package/dist/Raffle/GetRaffleWonPrizesRequest.d.ts +9 -0
- package/dist/Raffle/GetRaffleWonPrizesResponse.d.ts +52 -0
- package/dist/Raffle/index.d.ts +2 -0
- package/dist/SmarticoAPI.d.ts +6 -1
- package/dist/SmarticoLib/index.d.ts +5 -1
- package/dist/WSAPI/WSAPIAvatars.d.ts +267 -49
- package/dist/WSAPI/WSAPIBonuses.d.ts +224 -10
- package/dist/WSAPI/WSAPIGamePick.d.ts +538 -253
- package/dist/WSAPI/WSAPIGeneral.d.ts +156 -14
- package/dist/WSAPI/WSAPIInbox.d.ts +547 -58
- package/dist/WSAPI/WSAPIJackpots.d.ts +292 -57
- package/dist/WSAPI/WSAPILeaderBoard.d.ts +127 -13
- package/dist/WSAPI/WSAPIMiniGames.d.ts +465 -49
- package/dist/WSAPI/WSAPIRaffles.d.ts +576 -52
- package/dist/WSAPI/WSAPITournaments.d.ts +3 -3
- package/dist/WSAPI/WSAPITypes.d.ts +243 -132
- package/dist/WSAPI/WSAPIUser.d.ts +193 -43
- package/dist/index.js +3409 -615
- package/dist/index.js.map +1 -1
- package/dist/index.modern.mjs +3391 -608
- package/dist/index.modern.mjs.map +1 -1
- package/docs/Callbacks.md +162 -0
- package/docs/SmarticoObject.md +445 -0
- package/docs/Transforms.md +99 -0
- package/docs/api/README.md +26 -0
- package/docs/api/classes/WSAPIAvatars.md +282 -54
- package/docs/api/classes/WSAPIBonuses.md +233 -12
- package/docs/api/classes/WSAPIClans.md +380 -10
- package/docs/api/classes/WSAPIGamePick.md +555 -26
- package/docs/api/classes/WSAPIGeneral.md +165 -16
- package/docs/api/classes/WSAPIInbox.md +588 -64
- package/docs/api/classes/WSAPIJackpots.md +320 -66
- package/docs/api/classes/WSAPILeaderBoard.md +133 -15
- package/docs/api/classes/WSAPIMiniGames.md +501 -64
- package/docs/api/classes/WSAPIMissions.md +58 -79
- package/docs/api/classes/WSAPIRaffles.md +647 -69
- package/docs/api/classes/WSAPIStore.md +83 -108
- package/docs/api/classes/WSAPITournaments.md +495 -28
- package/docs/api/classes/WSAPIUser.md +520 -83
- package/docs/api/documents/Callbacks.md +162 -0
- package/docs/api/documents/SmarticoObject.md +445 -0
- package/docs/api/documents/Transforms.md +99 -0
- package/docs/api/enumerations/BonusStatus-1.md +11 -6
- package/docs/api/enumerations/JoinClanErrorCode.md +81 -0
- package/docs/api/enumerations/TournamentRegistrationError.md +12 -0
- package/docs/api/functions/clanTournamentPlayersTransform.md +13 -0
- package/docs/api/interfaces/AvatarCustomized.md +25 -0
- package/docs/api/interfaces/AvatarDefinition.md +94 -0
- package/docs/api/interfaces/AvatarPrompt.md +45 -0
- package/docs/api/interfaces/BonusMetaMap-1.md +4 -1
- package/docs/api/interfaces/BonusTemplateMetaMap-1.md +9 -4
- package/docs/api/interfaces/Clan.md +4 -0
- package/docs/api/interfaces/ClanInfo.md +109 -0
- package/docs/api/interfaces/ClanMember.md +53 -0
- package/docs/api/interfaces/ClanTournamentPlayerRaw.md +67 -0
- package/docs/api/interfaces/GemsDiamondsLog.md +43 -0
- package/docs/api/interfaces/GetClanInfoResponse.md +61 -0
- package/docs/api/interfaces/GetClanTournamentPlayersResponse.md +81 -0
- package/docs/api/interfaces/GetRaffleWonPrizesRequest.md +59 -0
- package/docs/api/interfaces/GetRaffleWonPrizesResponse.md +95 -0
- package/docs/api/interfaces/InboxMarkMessageAction.md +10 -2
- package/docs/api/interfaces/JackpotDetails.md +14 -15
- package/docs/api/interfaces/JackpotPot.md +9 -6
- package/docs/api/interfaces/LeaderBoardDetailsT.md +14 -8
- package/docs/api/interfaces/LeaderBoardUserT.md +8 -5
- package/docs/api/interfaces/LeaderBoardsRewardsT.md +7 -0
- package/docs/api/interfaces/PointsLog.md +43 -0
- package/docs/api/interfaces/RaffleWonPrize.md +59 -0
- package/docs/api/interfaces/RaffleWonPrizePublicMeta.md +27 -0
- package/docs/api/interfaces/RaffleWonPrizeUser.md +43 -0
- package/docs/api/interfaces/TAchCategory.md +2 -7
- package/docs/api/interfaces/TAvatarCustomized.md +4 -4
- package/docs/api/interfaces/TAvatarDefinition.md +13 -14
- package/docs/api/interfaces/TAvatarPrompt.md +6 -6
- package/docs/api/interfaces/TBonus.md +16 -8
- package/docs/api/interfaces/TBuyStoreItemResult.md +4 -29
- package/docs/api/interfaces/TClaimBonusResult.md +5 -5
- package/docs/api/interfaces/TClan.md +8 -4
- package/docs/api/interfaces/TClanInfo.md +47 -0
- package/docs/api/interfaces/TClanJoinResult.md +11 -1
- package/docs/api/interfaces/TClanTournamentPlayer.md +55 -0
- package/docs/api/interfaces/TClanTournamentPlayersResult.md +27 -0
- package/docs/api/interfaces/TClans.md +3 -1
- package/docs/api/interfaces/TGetTranslations.md +4 -0
- package/docs/api/interfaces/TInboxMessage.md +14 -6
- package/docs/api/interfaces/TInboxMessageBody.md +18 -12
- package/docs/api/interfaces/TLevel.md +17 -20
- package/docs/api/interfaces/TLevelCurrent.md +19 -18
- package/docs/api/interfaces/TMiniGamePlayBatchResult.md +14 -6
- package/docs/api/interfaces/TMiniGamePlayResult.md +9 -4
- package/docs/api/interfaces/TMissionClaimRewardResult.md +1 -9
- package/docs/api/interfaces/TMissionOptInResult.md +1 -5
- package/docs/api/interfaces/TMissionOrBadge.md +4 -7
- package/docs/api/interfaces/TRaffleOptinResponse.md +4 -2
- package/docs/api/interfaces/TSegmentCheckResult.md +10 -0
- package/docs/api/interfaces/TSetAvatarResult.md +3 -3
- package/docs/api/interfaces/TStoreItem.md +3 -13
- package/docs/api/interfaces/TTournament.md +1 -1
- package/docs/api/interfaces/TTournamentDetailed.md +1 -1
- package/docs/api/interfaces/TTournamentRegistrationResult.md +4 -2
- package/docs/api/interfaces/TUICustomSection.md +23 -19
- package/docs/api/interfaces/TUserProfile.md +18 -16
- package/docs/api/interfaces/TransformedRaffleClaimPrizeResponse.md +6 -2
- package/docs/api/interfaces/UserLevelExtraCountersT.md +9 -2
- package/docs/api/type-aliases/ActivityLogEntry.md +3 -0
- package/docs/native/ADDING_METHODS.md +7 -2
- package/docs/native/PROTOCOL.md +337 -0
- package/docs/ui/avatars/UIGuide_getAvatarPrompts.md +100 -0
- package/docs/ui/avatars/UIGuide_getAvatarsCustomized.md +90 -0
- package/docs/ui/avatars/UIGuide_getAvatarsList.md +105 -0
- package/docs/ui/avatars/UIGuide_setAvatar.md +118 -0
- package/docs/ui/bonuses/UIGuide_claimBonus.md +144 -0
- package/docs/ui/bonuses/UIGuide_getBonuses.md +176 -0
- package/docs/ui/gamepick/UIGuide_gamePickGetActiveRound.md +99 -0
- package/docs/ui/gamepick/UIGuide_gamePickGetActiveRounds.md +76 -0
- package/docs/ui/gamepick/UIGuide_gamePickGetBoard.md +81 -0
- package/docs/ui/gamepick/UIGuide_gamePickGetGameInfo.md +78 -0
- package/docs/ui/gamepick/UIGuide_gamePickGetHistory.md +55 -0
- package/docs/ui/gamepick/UIGuide_gamePickGetRoundInfoForUser.md +71 -0
- package/docs/ui/gamepick/UIGuide_gamePickGetUserInfo.md +64 -0
- package/docs/ui/gamepick/UIGuide_gamePickSubmitSelection.md +103 -0
- package/docs/ui/gamepick/UIGuide_gamePickSubmitSelectionQuiz.md +67 -0
- package/docs/ui/general/UIGuide_getCustomSections.md +137 -0
- package/docs/ui/general/UIGuide_getRelatedItemsForGame.md +140 -0
- package/docs/ui/inbox/UIGuide_deleteInboxMessage.md +135 -0
- package/docs/ui/inbox/UIGuide_getInboxMessageBody.md +133 -0
- package/docs/ui/inbox/UIGuide_getInboxMessages.md +186 -0
- package/docs/ui/inbox/UIGuide_markInboxMessageAsRead.md +122 -0
- package/docs/ui/inbox/UIGuide_markUnmarkInboxMessageAsFavorite.md +84 -0
- package/docs/ui/jackpots/UIGuide_getJackpotEligibleGames.md +73 -0
- package/docs/ui/jackpots/UIGuide_getJackpotWinners.md +83 -0
- package/docs/ui/jackpots/UIGuide_jackpotGet.md +138 -0
- package/docs/ui/jackpots/UIGuide_jackpotOptIn.md +85 -0
- package/docs/ui/jackpots/UIGuide_jackpotOptOut.md +65 -0
- package/docs/ui/leaderboard/UIGuide_getLeaderBoard.md +166 -0
- package/docs/ui/minigames/UIGuide_getMiniGames.md +153 -0
- package/docs/ui/minigames/UIGuide_getMiniGamesHistory.md +90 -0
- package/docs/ui/minigames/UIGuide_playMiniGame.md +150 -0
- package/docs/ui/minigames/UIGuide_playMiniGameBatch.md +128 -0
- package/docs/ui/raffles/UIGuide_claimRafflePrize.md +99 -0
- package/docs/ui/raffles/UIGuide_getRaffleDrawRun.md +117 -0
- package/docs/ui/raffles/UIGuide_getRaffleDrawRunsHistory.md +92 -0
- package/docs/ui/raffles/UIGuide_getRaffleWonPrizes.md +120 -0
- package/docs/ui/raffles/UIGuide_getRaffles.md +175 -0
- package/docs/ui/raffles/UIGuide_requestRaffleOptin.md +114 -0
- package/docs/ui/user/UIGuide_getActivityLog.md +130 -0
- package/docs/ui/user/UIGuide_getLevels.md +47 -42
- package/package.json +1 -1
- package/src/Base/ClassId.ts +2 -0
- package/src/Jackpots/JackpotDetails.ts +14 -15
- package/src/Jackpots/JackpotPot.ts +10 -6
- package/src/Raffle/GetRaffleWonPrizesRequest.ts +12 -0
- package/src/Raffle/GetRaffleWonPrizesResponse.ts +56 -0
- package/src/Raffle/index.ts +3 -1
- package/src/SmarticoAPI.ts +14 -1
- package/src/SmarticoLib/index.ts +4 -0
- package/src/WSAPI/WSAPIAvatars.ts +267 -49
- package/src/WSAPI/WSAPIBonuses.ts +224 -10
- package/src/WSAPI/WSAPIGamePick.ts +538 -253
- package/src/WSAPI/WSAPIGeneral.ts +156 -14
- package/src/WSAPI/WSAPIInbox.ts +545 -56
- package/src/WSAPI/WSAPIJackpots.ts +297 -61
- package/src/WSAPI/WSAPILeaderBoard.ts +127 -13
- package/src/WSAPI/WSAPIMiniGames.ts +465 -49
- package/src/WSAPI/WSAPIRaffles.ts +592 -64
- package/src/WSAPI/WSAPITournaments.ts +3 -3
- package/src/WSAPI/WSAPITypes.ts +243 -132
- package/src/WSAPI/WSAPIUser.ts +193 -43
- 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.
|