# The push inbox - JavaScript bridge API

> Messages the creator sent from a dashboard, kept on the device so the page can show a history rather than only a tray pop-up.

- **Applies to:** AppMint
- **Source:** extracted from the app runtime and its per-method example files; this page is generated from them.
- **HTML:** https://freewebtoapk.com/docs/api/push

### `clearPushInbox`

```js
window.WebToApk.clearPushInbox(): Boolean
```

Empties the push inbox (the tray and server history are untouched).

**Example**

Empties the push inbox on this phone.

**Returns:** `true` when done; `false` on an internal error. **Needs:** turn on **AppMint Push** in the Integrate step (Step 3) when you build.

```js
document.getElementById('clear-inbox').addEventListener('click', function () {
  if (!(window.WebToApk && window.WebToApk.clearPushInbox)) return;
  if (!confirm('Delete all messages? This cannot be undone.')) return;
  if (WebToApk.clearPushInbox()) renderInbox();
});
```

**Notes:** this is permanent - unlike `dismissPushMessage`, there is no undo. Tray notifications and your send history in AppMint are not touched. New messages still arrive.

### `dismissPushMessage`

```js
window.WebToApk.dismissPushMessage(id: String): Boolean
```

Dismisses ONE message from the inbox - the per-row swipe-away an inbox screen needs (clearPushInbox is all-or-nothing). REVERSIBLE by design: the entry is hidden, not destroyed, so the UI can offer "Undo" for a few seconds after the swipe. Local only: the tray notification and the creator's history are untouched.

**Example**

Hides one message from the push inbox (a swipe-away). It can be undone with `restorePushMessage(id)`.

**Returns:** `true` if the message was hidden; `false` if the id is unknown or it was already hidden. **Needs:** turn on **AppMint Push** in the Integrate step (Step 3) when you build.

**Swipe away with a 5-second Undo:**

```js
function dismissRow(id, rowEl) {
  if (!(window.WebToApk && window.WebToApk.dismissPushMessage)) return;
  if (!WebToApk.dismissPushMessage(id)) return;
  rowEl.remove();

  const bar = document.getElementById('undo-bar');
  bar.hidden = false;
  const timer = setTimeout(function () { bar.hidden = true; }, 5000);
  document.getElementById('undo-btn').onclick = function () {
    clearTimeout(timer);
    bar.hidden = true;
    WebToApk.restorePushMessage(id);         // back in its old place
    renderInbox();
  };
}
```

**Notes:** only this phone's inbox changes. The tray notification and your send history in AppMint stay. Hidden messages are not returned by `getPushInbox()`.

### `getPushInbox`

```js
window.WebToApk.getPushInbox(): String
```

AppMint Push inbox (creator-sent messages, newest first, max 50): JSON array of {id, title, body, imageUrl, link, receivedAt, read}. Always the full current truth - an app that mounts late loses nothing by having missed the live `appmint:push` events.

**Example**

Reads the in-app inbox of push messages you sent with AppMint Push: newest first, up to 50, without the ones the user dismissed.

**Returns:** a JSON **string**, synchronously. Parse it. Each item: `{ id, title, body, imageUrl, link, receivedAt, read }` (`receivedAt` in epoch ms; `imageUrl` and `link` are `''` when the message has none), plus optional design fields when you used a template in AppMint: `template`, `accent`, `iconUrl`, `buttons: [{label, link}]`, `badge`, `inapp`, `countdownAt`, `progress`, `lines`, `collapse`. `'[]'` when empty. **Needs:** turn on **AppMint Push** in the Integrate step (Step 3) when you build; without it the inbox is always empty.

**Render the inbox, and refresh it live with `appmint:push`:**

```js
function loadInbox() {
  if (!(window.WebToApk && window.WebToApk.getPushInbox)) return [];
  try { return JSON.parse(WebToApk.getPushInbox() || '[]'); } catch (e) { return []; }
}

function renderInbox() {
  const inbox = loadInbox();
  const unread = inbox.filter(function (m) { return !m.read; }).length;
  document.getElementById('bell-count').textContent = unread ? String(unread) : '';
  const ul = document.getElementById('inbox');
  ul.innerHTML = '';
  inbox.forEach(function (m) {
    const li = document.createElement('li');
    li.className = m.read ? 'read' : 'unread';
    li.textContent = m.title + ' — ' + m.body;
    li.onclick = function () {
      WebToApk.markPushRead(m.id);
      if (m.link) location.href = m.link;
      renderInbox();
    };
    ul.appendChild(li);
  });
}

// While the app is open:
window.addEventListener('appmint:push', function (e) {
  // { type: 'received', message: {id, title, body, ...}, presented: true|false }
  // { type: 'revoked', id }  — you retracted the message
  // presented = the app already showed it on screen (see setPushPresentation)
  if (e.detail.type === 'received' && !e.detail.presented) showBanner(e.detail.message.title);
  renderInbox();
});

renderInbox();
```

**Notes:** the inbox is kept on the phone, so read it when your screen opens - events only arrive while the app is on screen. A message you retract from AppMint disappears from the inbox and the tray. Messages sent as "push only" (tray) are not added to the inbox. The same detail is also passed to `window.onAppMintPush(detail)` if you define it.

### `markPushRead`

```js
window.WebToApk.markPushRead(id: String): Boolean
```

Marks one push message read; pass "" to mark every message read.

**Example**

Marks one push inbox message as read, or all of them when you pass `''`.

**Returns:** `true` if a message changed; `false` if nothing changed (unknown id, already read, or AppMint Push not enabled). **Needs:** turn on **AppMint Push** in the Integrate step (Step 3) when you build.

```js
function openMessage(id) {
  if (!(window.WebToApk && window.WebToApk.markPushRead)) return;
  WebToApk.markPushRead(id);                 // one message
  updateBellCount();
}

document.getElementById('mark-all-read').addEventListener('click', function () {
  if (!(window.WebToApk && window.WebToApk.markPushRead)) return;
  WebToApk.markPushRead('');                 // every message
  updateBellCount();
});

function updateBellCount() {
  const inbox = JSON.parse(WebToApk.getPushInbox() || '[]');
  const unread = inbox.filter(function (m) { return !m.read; }).length;
  document.getElementById('bell-count').textContent = unread ? String(unread) : '';
}
```

**Notes:** read state is stored only on this phone. It does not remove the tray notification.

### `restorePushMessage`

```js
window.WebToApk.restorePushMessage(id: String): Boolean
```

Undo a dismiss: puts the message back in its place in the inbox.

**Example**

Undoes `dismissPushMessage(id)`: the message comes back to the push inbox in its old place.

**Returns:** `true` if the message was restored; `false` if the id is unknown or it was not hidden. **Needs:** turn on **AppMint Push** in the Integrate step (Step 3) when you build.

```js
let lastDismissed = null;

function onSwipe(id) {
  if (!(window.WebToApk && window.WebToApk.dismissPushMessage)) return;
  if (WebToApk.dismissPushMessage(id)) {
    lastDismissed = id;
    showUndo();
    renderInbox();
  }
}

document.getElementById('undo-btn').addEventListener('click', function () {
  if (!lastDismissed || !window.WebToApk) return;
  if (WebToApk.restorePushMessage(lastDismissed)) renderInbox();
  lastDismissed = null;
});
```

**Notes:** a message cleared with `clearPushInbox()` or retracted by you from AppMint cannot be restored.

### `setPushPresentation`

```js
window.WebToApk.setPushPresentation(mode: String): Boolean
```

Native in-app presentation of push messages: "auto" (default) lets the shell draw the banner / modal / sheet / full-screen card the creator chose while the app is open; "none" turns it off for good (persisted) - for apps that draw their own. The `appmint:push` event and the inbox are unaffected either way; the received event's `presented` flag says whether the shell showed it.

**Example**

Turns the app's own on-screen display of AppMint Push messages on (`'auto'`, the default) or off (`'none'`) - for apps that draw their own banner from the `appmint:push` event.

**Returns:** `true` when the mode was saved; `false` for any value other than `'auto'` or `'none'`. The choice is saved on the phone and stays until changed. **Needs:** turn on **AppMint Push** in the Integrate step (Step 3) when you build.

**Draw your own banner** instead of the shell's:

```js
if (window.WebToApk && window.WebToApk.setPushPresentation) {
  WebToApk.setPushPresentation('none');       // 'auto' to give it back to the shell
}

window.addEventListener('appmint:push', function (e) {
  const d = e.detail;
  // { type: 'received', message: {...}, presented: false } — presented = the shell already showed it
  if (d.type === 'received' && !d.presented) showMyBanner(d.message.title, d.message.body, d.message.link);
  if (d.type === 'revoked') hideMyBanner(d.id);
});
```

**Notes:** with `'auto'`, a message you sent with an in-app style is shown over the app while it is open (and then not also put in the tray). With `'none'` the shell never draws it; the inbox (`getPushInbox`) and the `appmint:push` event work the same either way. Setting `'none'` also closes a message the shell is showing now.

