forked from cadence/Carbon
		
	Display ghost messages that are being sent
This commit is contained in:
		
							parent
							
								
									f9662e31a2
								
							
						
					
					
						commit
						0e084c0a68
					
				
					 9 changed files with 201 additions and 55 deletions
				
			
		| 
						 | 
				
			
			@ -2,10 +2,10 @@
 | 
			
		|||
<html>
 | 
			
		||||
  <head>
 | 
			
		||||
    <meta charset="utf-8">
 | 
			
		||||
    <link rel="stylesheet" type="text/css" href="static/main.css?static=9aad8398d2">
 | 
			
		||||
    <link rel="stylesheet" type="text/css" href="static/main.css?static=f7c0898b94">
 | 
			
		||||
    <script type="module" src="static/groups.js?static=2cc7f0daf8"></script>
 | 
			
		||||
    <script type="module" src="static/chat-input.js?static=92188b34f9"></script>
 | 
			
		||||
    <script type="module" src="static/room-picker.js?static=7bc94b38d3"></script>
 | 
			
		||||
    <script type="module" src="static/chat-input.js?static=16321d4eb4"></script>
 | 
			
		||||
    <script type="module" src="static/room-picker.js?static=46999be5e5"></script>
 | 
			
		||||
    <script type="module" src="static/sync/sync.js?static=56e374b23d"></script>
 | 
			
		||||
    <script type="module" src="static/chat.js?static=fc121d3d23"></script>
 | 
			
		||||
    <title>Carbon</title>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,13 @@
 | 
			
		|||
import {ElemJS, ejs} from "./basic.js"
 | 
			
		||||
import {Subscribable} from "./store/Subscribable.js"
 | 
			
		||||
import {Anchor} from "./Anchor.js"
 | 
			
		||||
import * as lsm from "./lsm.js"
 | 
			
		||||
 | 
			
		||||
let sentIndex = 0
 | 
			
		||||
 | 
			
		||||
function getTxnId() {
 | 
			
		||||
	return Date.now() + (sentIndex++)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function eventSearch(list, event, min = 0, max = -1) {
 | 
			
		||||
	if (list.length === 0) return {success: false, i: 0}
 | 
			
		||||
| 
						 | 
				
			
			@ -28,23 +35,35 @@ class Event extends ElemJS {
 | 
			
		|||
		super("div")
 | 
			
		||||
		this.class("c-message")
 | 
			
		||||
		this.data = null
 | 
			
		||||
		this.group = null
 | 
			
		||||
		this.update(data)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	setGroup(group) {
 | 
			
		||||
		this.group = group
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	update(data) {
 | 
			
		||||
		this.data = data
 | 
			
		||||
		this.render()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	removeEvent() {
 | 
			
		||||
		if (this.group) this.group.removeEvent(this)
 | 
			
		||||
		else this.remove()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	render() {
 | 
			
		||||
		this.child(this.data.content.body)
 | 
			
		||||
		this.element.classList[this.data.pending ? "add" : "remove"]("c-message--pending")
 | 
			
		||||
		this.text(this.data.content.body)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class EventGroup extends ElemJS {
 | 
			
		||||
	constructor(list) {
 | 
			
		||||
	constructor(reactive, list) {
 | 
			
		||||
		super("div")
 | 
			
		||||
		this.class("c-message-group")
 | 
			
		||||
		this.reactive = reactive
 | 
			
		||||
		this.list = list
 | 
			
		||||
		this.data = {
 | 
			
		||||
			sender: list[0].data.sender,
 | 
			
		||||
| 
						 | 
				
			
			@ -66,9 +85,20 @@ class EventGroup extends ElemJS {
 | 
			
		|||
 | 
			
		||||
	addEvent(event) {
 | 
			
		||||
		const index = eventSearch(this.list, event).i
 | 
			
		||||
		event.setGroup(this)
 | 
			
		||||
		this.list.splice(index, 0, event)
 | 
			
		||||
		this.messages.childAt(index + 1, event)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	removeEvent(event) {
 | 
			
		||||
		const search = eventSearch(this.list, event)
 | 
			
		||||
		if (!search.success) throw new Error(`Event ${event.data.event_id} not found in this group`)
 | 
			
		||||
		const index = search.i
 | 
			
		||||
		// actually remove the event
 | 
			
		||||
		this.list.splice(index, 1)
 | 
			
		||||
		event.remove() // should get everything else
 | 
			
		||||
		if (this.list.length === 0) this.reactive.removeGroup(this)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class ReactiveTimeline extends ElemJS {
 | 
			
		||||
| 
						 | 
				
			
			@ -90,7 +120,7 @@ class ReactiveTimeline extends ElemJS {
 | 
			
		|||
		const success = indices.some(i => {
 | 
			
		||||
			if (!this.list[i]) {
 | 
			
		||||
				// if (printed++ < 100) console.log("tryadd success, created group")
 | 
			
		||||
				const group = new EventGroup([event])
 | 
			
		||||
				const group = new EventGroup(this, [event])
 | 
			
		||||
				this.list.splice(i, 0, group)
 | 
			
		||||
				this.childAt(i, group)
 | 
			
		||||
				return true
 | 
			
		||||
| 
						 | 
				
			
			@ -103,6 +133,12 @@ class ReactiveTimeline extends ElemJS {
 | 
			
		|||
		if (!success) console.log("tryadd failure", indices, this.list.map(l => l.data.sender), event.data)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	removeGroup(group) {
 | 
			
		||||
		const index = this.list.indexOf(group)
 | 
			
		||||
		this.list.splice(index, 1)
 | 
			
		||||
		group.remove() // should get everything else
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	render() {
 | 
			
		||||
		this.clearChildren()
 | 
			
		||||
		this.list.forEach(group => this.child(group))
 | 
			
		||||
| 
						 | 
				
			
			@ -112,36 +148,84 @@ class ReactiveTimeline extends ElemJS {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
class Timeline extends Subscribable {
 | 
			
		||||
	constructor() {
 | 
			
		||||
	constructor(id) {
 | 
			
		||||
		super()
 | 
			
		||||
		Object.assign(this.events, {
 | 
			
		||||
			beforeChange: []
 | 
			
		||||
			beforeChange: [],
 | 
			
		||||
			afterChange: []
 | 
			
		||||
		})
 | 
			
		||||
		Object.assign(this.eventDeps, {
 | 
			
		||||
			beforeChange: []
 | 
			
		||||
			beforeChange: [],
 | 
			
		||||
			afterChange: []
 | 
			
		||||
		})
 | 
			
		||||
		this.id = id
 | 
			
		||||
		this.list = []
 | 
			
		||||
		this.map = new Map()
 | 
			
		||||
		this.reactiveTimeline = new ReactiveTimeline([])
 | 
			
		||||
		this.latest = 0
 | 
			
		||||
		this.pending = new Set()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	updateEvents(events) {
 | 
			
		||||
		this.broadcast("beforeChange")
 | 
			
		||||
		for (const eventData of events) {
 | 
			
		||||
			this.latest = Math.max(this.latest, eventData.origin_server_ts)
 | 
			
		||||
			if (this.map.has(eventData.event_id)) {
 | 
			
		||||
				this.map.get(eventData.event_id).update(eventData)
 | 
			
		||||
			let id = eventData.event_id
 | 
			
		||||
			if (eventData.sender === lsm.get("mx_user_id") && eventData.content && this.pending.has(eventData.content["chat.carbon.message.pending_id"])) {
 | 
			
		||||
				id = eventData.content["chat.carbon.message.pending_id"]
 | 
			
		||||
			}
 | 
			
		||||
			if (this.map.has(id)) {
 | 
			
		||||
				this.map.get(id).update(eventData)
 | 
			
		||||
			} else {
 | 
			
		||||
				const event = new Event(eventData)
 | 
			
		||||
				this.map.set(id, event)
 | 
			
		||||
				this.reactiveTimeline.addEvent(event)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		this.broadcast("afterChange")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	removeEvent(id) {
 | 
			
		||||
		if (!this.map.has(id)) throw new Error(`Tried to delete event ID ${id} which does not exist`)
 | 
			
		||||
		this.map.get(id).removeEvent()
 | 
			
		||||
		this.map.delete(id)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	getTimeline() {
 | 
			
		||||
		return this.reactiveTimeline
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	send(body) {
 | 
			
		||||
		const tx = getTxnId()
 | 
			
		||||
		const id = `pending$${tx}`
 | 
			
		||||
		this.pending.add(id)
 | 
			
		||||
		const content = {
 | 
			
		||||
			msgtype: "m.text",
 | 
			
		||||
			body,
 | 
			
		||||
			"chat.carbon.message.pending_id": id
 | 
			
		||||
		}
 | 
			
		||||
		const fakeEvent = {
 | 
			
		||||
			origin_server_ts: Date.now(),
 | 
			
		||||
			event_id: id,
 | 
			
		||||
			sender: lsm.get("mx_user_id"),
 | 
			
		||||
			content,
 | 
			
		||||
			pending: true
 | 
			
		||||
		}
 | 
			
		||||
		this.updateEvents([fakeEvent])
 | 
			
		||||
		return fetch(`${lsm.get("domain")}/_matrix/client/r0/rooms/${this.id}/send/m.room.message/${tx}?access_token=${lsm.get("access_token")}`, {
 | 
			
		||||
			method: "PUT",
 | 
			
		||||
			body: JSON.stringify(content),
 | 
			
		||||
			headers: {
 | 
			
		||||
				"Content-Type": "application/json"
 | 
			
		||||
			}
 | 
			
		||||
		})/*.then(() => {
 | 
			
		||||
			const subscription = () => {
 | 
			
		||||
				this.removeEvent(id)
 | 
			
		||||
				this.unsubscribe("afterChange", subscription)
 | 
			
		||||
			}
 | 
			
		||||
			this.subscribe("afterChange", subscription)
 | 
			
		||||
		})*/
 | 
			
		||||
	}
 | 
			
		||||
/*
 | 
			
		||||
	getGroupedEvents() {
 | 
			
		||||
		let currentSender = Symbol("N/A")
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,8 +3,6 @@ import {store} from "./store/store.js"
 | 
			
		|||
import * as lsm from "./lsm.js"
 | 
			
		||||
import {chat} from "./chat.js"
 | 
			
		||||
 | 
			
		||||
let sentIndex = 0
 | 
			
		||||
 | 
			
		||||
const input = q("#c-chat-textarea")
 | 
			
		||||
 | 
			
		||||
store.activeRoom.subscribe("changeSelf", () => {
 | 
			
		||||
| 
						 | 
				
			
			@ -33,21 +31,7 @@ function fixHeight() {
 | 
			
		|||
	input.style.height = (input.scrollHeight + 1) + "px"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getTxnId() {
 | 
			
		||||
	return Date.now() + (sentIndex++)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function send(body) {
 | 
			
		||||
	if (!store.activeRoom.exists()) return
 | 
			
		||||
	const id = store.activeRoom.value().id
 | 
			
		||||
	return fetch(`${lsm.get("domain")}/_matrix/client/r0/rooms/${id}/send/m.room.message/${getTxnId()}?access_token=${lsm.get("access_token")}`, {
 | 
			
		||||
		method: "PUT",
 | 
			
		||||
		body: JSON.stringify({
 | 
			
		||||
			msgtype: "m.text",
 | 
			
		||||
			body
 | 
			
		||||
		}),
 | 
			
		||||
		headers: {
 | 
			
		||||
			"Content-Type": "application/json"
 | 
			
		||||
		}
 | 
			
		||||
	})
 | 
			
		||||
	return store.activeRoom.value().timeline.send(body)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -182,6 +182,11 @@ body {
 | 
			
		|||
 | 
			
		||||
.c-message {
 | 
			
		||||
	margin-top: 4px;
 | 
			
		||||
	opacity: 1;
 | 
			
		||||
	transition: opacity 0.2s ease-out;
 | 
			
		||||
}
 | 
			
		||||
.c-message--pending {
 | 
			
		||||
	opacity: 0.5;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.c-message-event {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -68,7 +68,7 @@ class Room extends ElemJS {
 | 
			
		|||
 | 
			
		||||
		this.id = id
 | 
			
		||||
		this.data = data
 | 
			
		||||
		this.timeline = new Timeline()
 | 
			
		||||
		this.timeline = new Timeline(this.id)
 | 
			
		||||
		this.group = null
 | 
			
		||||
 | 
			
		||||
		this.class("c-room")
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,13 @@
 | 
			
		|||
import {ElemJS, ejs} from "./basic.js"
 | 
			
		||||
import {Subscribable} from "./store/Subscribable.js"
 | 
			
		||||
import {Anchor} from "./Anchor.js"
 | 
			
		||||
import * as lsm from "./lsm.js"
 | 
			
		||||
 | 
			
		||||
let sentIndex = 0
 | 
			
		||||
 | 
			
		||||
function getTxnId() {
 | 
			
		||||
	return Date.now() + (sentIndex++)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function eventSearch(list, event, min = 0, max = -1) {
 | 
			
		||||
	if (list.length === 0) return {success: false, i: 0}
 | 
			
		||||
| 
						 | 
				
			
			@ -28,23 +35,35 @@ class Event extends ElemJS {
 | 
			
		|||
		super("div")
 | 
			
		||||
		this.class("c-message")
 | 
			
		||||
		this.data = null
 | 
			
		||||
		this.group = null
 | 
			
		||||
		this.update(data)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	setGroup(group) {
 | 
			
		||||
		this.group = group
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	update(data) {
 | 
			
		||||
		this.data = data
 | 
			
		||||
		this.render()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	removeEvent() {
 | 
			
		||||
		if (this.group) this.group.removeEvent(this)
 | 
			
		||||
		else this.remove()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	render() {
 | 
			
		||||
		this.child(this.data.content.body)
 | 
			
		||||
		this.element.classList[this.data.pending ? "add" : "remove"]("c-message--pending")
 | 
			
		||||
		this.text(this.data.content.body)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class EventGroup extends ElemJS {
 | 
			
		||||
	constructor(list) {
 | 
			
		||||
	constructor(reactive, list) {
 | 
			
		||||
		super("div")
 | 
			
		||||
		this.class("c-message-group")
 | 
			
		||||
		this.reactive = reactive
 | 
			
		||||
		this.list = list
 | 
			
		||||
		this.data = {
 | 
			
		||||
			sender: list[0].data.sender,
 | 
			
		||||
| 
						 | 
				
			
			@ -66,9 +85,20 @@ class EventGroup extends ElemJS {
 | 
			
		|||
 | 
			
		||||
	addEvent(event) {
 | 
			
		||||
		const index = eventSearch(this.list, event).i
 | 
			
		||||
		event.setGroup(this)
 | 
			
		||||
		this.list.splice(index, 0, event)
 | 
			
		||||
		this.messages.childAt(index + 1, event)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	removeEvent(event) {
 | 
			
		||||
		const search = eventSearch(this.list, event)
 | 
			
		||||
		if (!search.success) throw new Error(`Event ${event.data.event_id} not found in this group`)
 | 
			
		||||
		const index = search.i
 | 
			
		||||
		// actually remove the event
 | 
			
		||||
		this.list.splice(index, 1)
 | 
			
		||||
		event.remove() // should get everything else
 | 
			
		||||
		if (this.list.length === 0) this.reactive.removeGroup(this)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class ReactiveTimeline extends ElemJS {
 | 
			
		||||
| 
						 | 
				
			
			@ -90,7 +120,7 @@ class ReactiveTimeline extends ElemJS {
 | 
			
		|||
		const success = indices.some(i => {
 | 
			
		||||
			if (!this.list[i]) {
 | 
			
		||||
				// if (printed++ < 100) console.log("tryadd success, created group")
 | 
			
		||||
				const group = new EventGroup([event])
 | 
			
		||||
				const group = new EventGroup(this, [event])
 | 
			
		||||
				this.list.splice(i, 0, group)
 | 
			
		||||
				this.childAt(i, group)
 | 
			
		||||
				return true
 | 
			
		||||
| 
						 | 
				
			
			@ -103,6 +133,12 @@ class ReactiveTimeline extends ElemJS {
 | 
			
		|||
		if (!success) console.log("tryadd failure", indices, this.list.map(l => l.data.sender), event.data)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	removeGroup(group) {
 | 
			
		||||
		const index = this.list.indexOf(group)
 | 
			
		||||
		this.list.splice(index, 1)
 | 
			
		||||
		group.remove() // should get everything else
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	render() {
 | 
			
		||||
		this.clearChildren()
 | 
			
		||||
		this.list.forEach(group => this.child(group))
 | 
			
		||||
| 
						 | 
				
			
			@ -112,36 +148,84 @@ class ReactiveTimeline extends ElemJS {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
class Timeline extends Subscribable {
 | 
			
		||||
	constructor() {
 | 
			
		||||
	constructor(id) {
 | 
			
		||||
		super()
 | 
			
		||||
		Object.assign(this.events, {
 | 
			
		||||
			beforeChange: []
 | 
			
		||||
			beforeChange: [],
 | 
			
		||||
			afterChange: []
 | 
			
		||||
		})
 | 
			
		||||
		Object.assign(this.eventDeps, {
 | 
			
		||||
			beforeChange: []
 | 
			
		||||
			beforeChange: [],
 | 
			
		||||
			afterChange: []
 | 
			
		||||
		})
 | 
			
		||||
		this.id = id
 | 
			
		||||
		this.list = []
 | 
			
		||||
		this.map = new Map()
 | 
			
		||||
		this.reactiveTimeline = new ReactiveTimeline([])
 | 
			
		||||
		this.latest = 0
 | 
			
		||||
		this.pending = new Set()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	updateEvents(events) {
 | 
			
		||||
		this.broadcast("beforeChange")
 | 
			
		||||
		for (const eventData of events) {
 | 
			
		||||
			this.latest = Math.max(this.latest, eventData.origin_server_ts)
 | 
			
		||||
			if (this.map.has(eventData.event_id)) {
 | 
			
		||||
				this.map.get(eventData.event_id).update(eventData)
 | 
			
		||||
			let id = eventData.event_id
 | 
			
		||||
			if (eventData.sender === lsm.get("mx_user_id") && eventData.content && this.pending.has(eventData.content["chat.carbon.message.pending_id"])) {
 | 
			
		||||
				id = eventData.content["chat.carbon.message.pending_id"]
 | 
			
		||||
			}
 | 
			
		||||
			if (this.map.has(id)) {
 | 
			
		||||
				this.map.get(id).update(eventData)
 | 
			
		||||
			} else {
 | 
			
		||||
				const event = new Event(eventData)
 | 
			
		||||
				this.map.set(id, event)
 | 
			
		||||
				this.reactiveTimeline.addEvent(event)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		this.broadcast("afterChange")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	removeEvent(id) {
 | 
			
		||||
		if (!this.map.has(id)) throw new Error(`Tried to delete event ID ${id} which does not exist`)
 | 
			
		||||
		this.map.get(id).removeEvent()
 | 
			
		||||
		this.map.delete(id)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	getTimeline() {
 | 
			
		||||
		return this.reactiveTimeline
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	send(body) {
 | 
			
		||||
		const tx = getTxnId()
 | 
			
		||||
		const id = `pending$${tx}`
 | 
			
		||||
		this.pending.add(id)
 | 
			
		||||
		const content = {
 | 
			
		||||
			msgtype: "m.text",
 | 
			
		||||
			body,
 | 
			
		||||
			"chat.carbon.message.pending_id": id
 | 
			
		||||
		}
 | 
			
		||||
		const fakeEvent = {
 | 
			
		||||
			origin_server_ts: Date.now(),
 | 
			
		||||
			event_id: id,
 | 
			
		||||
			sender: lsm.get("mx_user_id"),
 | 
			
		||||
			content,
 | 
			
		||||
			pending: true
 | 
			
		||||
		}
 | 
			
		||||
		this.updateEvents([fakeEvent])
 | 
			
		||||
		return fetch(`${lsm.get("domain")}/_matrix/client/r0/rooms/${this.id}/send/m.room.message/${tx}?access_token=${lsm.get("access_token")}`, {
 | 
			
		||||
			method: "PUT",
 | 
			
		||||
			body: JSON.stringify(content),
 | 
			
		||||
			headers: {
 | 
			
		||||
				"Content-Type": "application/json"
 | 
			
		||||
			}
 | 
			
		||||
		})/*.then(() => {
 | 
			
		||||
			const subscription = () => {
 | 
			
		||||
				this.removeEvent(id)
 | 
			
		||||
				this.unsubscribe("afterChange", subscription)
 | 
			
		||||
			}
 | 
			
		||||
			this.subscribe("afterChange", subscription)
 | 
			
		||||
		})*/
 | 
			
		||||
	}
 | 
			
		||||
/*
 | 
			
		||||
	getGroupedEvents() {
 | 
			
		||||
		let currentSender = Symbol("N/A")
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,8 +3,6 @@ import {store} from "./store/store.js"
 | 
			
		|||
import * as lsm from "./lsm.js"
 | 
			
		||||
import {chat} from "./chat.js"
 | 
			
		||||
 | 
			
		||||
let sentIndex = 0
 | 
			
		||||
 | 
			
		||||
const input = q("#c-chat-textarea")
 | 
			
		||||
 | 
			
		||||
store.activeRoom.subscribe("changeSelf", () => {
 | 
			
		||||
| 
						 | 
				
			
			@ -33,21 +31,7 @@ function fixHeight() {
 | 
			
		|||
	input.style.height = (input.scrollHeight + 1) + "px"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getTxnId() {
 | 
			
		||||
	return Date.now() + (sentIndex++)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function send(body) {
 | 
			
		||||
	if (!store.activeRoom.exists()) return
 | 
			
		||||
	const id = store.activeRoom.value().id
 | 
			
		||||
	return fetch(`${lsm.get("domain")}/_matrix/client/r0/rooms/${id}/send/m.room.message/${getTxnId()}?access_token=${lsm.get("access_token")}`, {
 | 
			
		||||
		method: "PUT",
 | 
			
		||||
		body: JSON.stringify({
 | 
			
		||||
			msgtype: "m.text",
 | 
			
		||||
			body
 | 
			
		||||
		}),
 | 
			
		||||
		headers: {
 | 
			
		||||
			"Content-Type": "application/json"
 | 
			
		||||
		}
 | 
			
		||||
	})
 | 
			
		||||
	return store.activeRoom.value().timeline.send(body)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -68,7 +68,7 @@ class Room extends ElemJS {
 | 
			
		|||
 | 
			
		||||
		this.id = id
 | 
			
		||||
		this.data = data
 | 
			
		||||
		this.timeline = new Timeline()
 | 
			
		||||
		this.timeline = new Timeline(this.id)
 | 
			
		||||
		this.group = null
 | 
			
		||||
 | 
			
		||||
		this.class("c-room")
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -44,6 +44,11 @@
 | 
			
		|||
 | 
			
		||||
.c-message
 | 
			
		||||
  margin-top: 4px
 | 
			
		||||
  opacity: 1
 | 
			
		||||
  transition: opacity 0.2s ease-out
 | 
			
		||||
 | 
			
		||||
  &--pending
 | 
			
		||||
    opacity: 0.5
 | 
			
		||||
 | 
			
		||||
.c-message-event
 | 
			
		||||
  padding-top: 10px
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue