UNPKG

reblock

Version:

Build interactive Slack surfaces with React

110 lines (109 loc) 2.77 kB
import { createContainer, render, Root } from '../renderer' import { jsxToBlocks } from '../jsx/blocks' import { activeRoots, ensureEventRegistered } from '../events' import { blocks } from './blocks' export class MessageRoot extends Root { client args resolve reject ts existingTS constructor(client, args, resolve, reject) { super() this.client = client this.args = args this.resolve = resolve this.reject = reject } async publish() { try { activeRoots.add(this) const children = this.getChildren() const [blocks, text] = jsxToBlocks(children) if (!this.ts) { this.ts = (async () => { const result = await this.client.chat.postMessage({ ...this.args, blocks, ...(text ? { text } : {}), }) if (!result.ok || !result.ts) { const error = new Error('Failed to send message') if (this.reject) { this.reject(error) } throw error } if (this.resolve) { this.resolve(result.ts) } this.existingTS = result.ts return result.ts })() return } const ts = await this.ts await this.client.chat.update({ ...this.args, ts, blocks, }) } catch (error) { if (this.reject) { this.reject(error) } console.error(error) } } handle = new MessageHandle(this) } export class MessageHandle { root constructor(root) { this.root = root } get ts() { return this.root.existingTS } get channel() { return this.root.args.channel } get rendering() { return this.root.rendering } async stop(behavior = 'clear') { this.root.stopRendering() activeRoots.delete(this.root) if (!this.root.ts) return if (behavior === 'keep') return if (behavior === 'delete') { await this.root.client.chat.delete({ ts: await this.root.ts, channel: this.root.args.channel, }) return } const finalBlocks = behavior === 'clear' ? [] : blocks(behavior) await this.root.client.chat.update({ ...this.root.args, ts: await this.root.ts, blocks: finalBlocks, }) } } export async function message(app, argsOrID, element) { ensureEventRegistered(app) let resolve = undefined let reject = undefined const promise = new Promise((res, rej) => { resolve = res reject = rej }) const args = typeof argsOrID === 'string' ? { channel: argsOrID } : argsOrID const root = new MessageRoot(app.client, args, resolve, reject) const container = createContainer(root) render(element, container) await promise return root.handle }