;; ported-from: src/notify.ts @ v1.2.0
;;
;; Framework-free invite toast: a small fixed card any suite app can show
;; when a friend's invite arrives live. Styles are injected once and scoped
;; under .soc-toast; accept navigates to the capability URL.
(ns ardegazu.social.notify
(:require [ardegazu.social.text :as text]))
(def ^:private CSS "
.soc-toast {
position: fixed; z-index: 9999;
right: calc(env(safe-area-inset-right, 0px) + 16px);
bottom: calc(env(safe-area-inset-bottom, 0px) + 64px);
max-width: min(320px, calc(100vw - 32px)); padding: 14px 16px; border-radius: 12px;
background: var(--soc-bg, #1e1c2a); color: var(--soc-fg, #eae6f2); border: 1px solid var(--soc-line, #2b2838);
font: 14px/1.5 -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;
box-shadow: 0 10px 26px -14px rgba(0,0,0,.7);
animation: soc-toast-in .25s ease;
}
@keyframes soc-toast-in { from { transform: translateY(12px); opacity: 0; } }
.soc-toast .who { font-weight: 650; }
.soc-toast .what { color: var(--soc-dim, #a49fb5); margin: 4px 0 10px; }
.soc-toast .row { display: flex; gap: 8px; }
.soc-toast button {
font: 600 13px/1 inherit; color: var(--soc-fg, #eae6f2); cursor: pointer;
background: var(--soc-bg, #272334); border: 1px solid var(--soc-line, #2b2838); border-radius: 8px; padding: 8px 12px;
}
.soc-toast button.go { border-color: var(--soc-accent, #93c1a5); }
")
(def ^:private css-injected (volatile! false))
(defn- ensure-css []
(when-not @css-injected
(vreset! css-injected true)
(let [style (js/document.createElement "style")]
(set! (.-textContent style) CSS)
(.appendChild js/document.head style))))
(defn invite-toast [inv opts]
(ensure-css)
(let [tt (text/mk-t (unchecked-get opts "t"))
card (js/document.createElement "div")
can-share (identical? (js* "typeof ~{}" (.-share js/navigator)) "function")]
(set! (.-className card) "soc-toast")
(set! (.-innerHTML card) "
<div class=\"who\"></div>
<div class=\"what\"></div>
<div class=\"row\">
<button class=\"go\"></button>
<button class=\"grab\"></button>
<button class=\"later\"></button>
</div>")
(set! (.-textContent (.querySelector card ".go")) (tt "social.toast.join" js/undefined))
(set! (.-textContent (.querySelector card ".grab"))
(if can-share (tt "social.toast.share" js/undefined) (tt "social.toast.copy" js/undefined)))
(set! (.-textContent (.querySelector card ".later")) (tt "social.toast.not-now" js/undefined))
(set! (.-textContent (.querySelector card ".who"))
(tt "social.toast.invites-you" (js-obj "name" (unchecked-get opts "label"))))
(let [inv-app (unchecked-get inv "app")
app-short (if ^boolean (js* "!!(~{})" inv-app)
(aget (.split ^js inv-app ".") 0)
"")
msg (unchecked-get inv "msg")
msg-k (when (some? msg) (unchecked-get msg "k"))
inv-label (unchecked-get inv "label")]
;; a message code renders in the receiver's language; legacy envelopes fall
;; back to the sender's prose label, then to the generic line
(set! (.-textContent (.querySelector card ".what"))
(if (and (identical? msg-k "join") ^boolean (js* "!!(~{})" app-short))
(tt "social.invite.join" (js-obj "app" app-short))
(if ^boolean (js* "!!(~{})" inv-label)
inv-label
(if ^boolean (js* "!!(~{})" app-short)
(tt "social.toast.come-to" (js-obj "app" app-short))
(tt "social.toast.come-play" js/undefined))))))
(let [close (fn [] (.remove card))]
(.addEventListener (.querySelector card ".go") "click"
(fn []
(close)
(if-let [on-accept (unchecked-get opts "onAccept")]
(on-accept inv)
(set! (.-href js/location) (unchecked-get inv "url")))))
;; installed-PWA path: a cross-app navigation from standalone is janky on
;; phones — carry the capability link out via the share sheet (or clipboard)
;; and open it wherever suits you
(let [grab (.querySelector card ".grab")]
(.addEventListener grab "click"
(fn []
(if can-share
(-> (.share js/navigator (js-obj "title" "ardegazu invite"
"url" (unchecked-get inv "url")))
(.catch (fn [_] nil)))
(when-let [cb (.-clipboard js/navigator)]
(.then (.writeText ^js cb (unchecked-get inv "url"))
(fn [_] (set! (.-textContent grab) (tt "social.toast.copied" js/undefined)))
(fn [_] (set! (.-textContent grab)
(str (.slice ^js (unchecked-get inv "url") 0 24) "…")))))))))
(.addEventListener (.querySelector card ".later") "click" (fn [] (close)))
(js/setTimeout close (let [t (unchecked-get opts "timeoutMs")] (if (nil? t) 45000 t)))
(.appendChild js/document.body card)
js/undefined)))