~singpolyma/jabber-client-demo

ad3bafbe27deef4d8152130297a14aee22b4a165 — Stephen Paul Weber 24 days ago be7302d
Delivery receipts
1 files changed, 50 insertions(+), 11 deletions(-)

M client.rb
M client.rb => client.rb +50 -11
@@ 26,13 26,20 @@ if DB.user_version < 1
	DB.user_version = 1
end

if DB.user_version < 2
	DB.execute(<<~SQL)
		ALTER TABLE messages ADD COLUMN delivered INTEGER NOT NULL DEFAULT 0
	SQL
	DB.user_version = 2
end

BLATHER = self
include Glimmer

set_caps(
	"https://git.singpolyma.net/jabber-client-demo",
	[],
	["urn:xmpp:avatar:metadata+notify"]
	["urn:xmpp:avatar:metadata+notify", "urn:xmpp:receipts"]
)

$avatars = {}


@@ 56,11 63,11 @@ class Conversation

	def initialize(jid)
		@jid = jid
		@messages = [[default_avatar(""), "", ""]]
		@messages = [[default_avatar(""), "", "", false, nil]]
		EM.defer do
			mam_messages = []
			DB.execute(<<~SQL, [@jid]) do |row|
				SELECT stanza
				SELECT stanza,delivered
				FROM messages
				WHERE conversation=?
				ORDER BY created_at


@@ 68,11 75,11 @@ class Conversation
				m = Blather::XMPPNode.import(
					Nokogiri::XML.parse(row[0]).root
				)
				mam_messages << m
				mam_messages << [m, row[1]]
			end

			LibUI.queue_main do
				mam_messages.map! { |m| message_row(m) }
				mam_messages.map! { |args| message_row(*args) }
				@messages.replace(mam_messages + @messages)
			end
		end


@@ 99,9 106,10 @@ class Conversation
					image_column("Avatar")
					text_column("Sender")
					text_column("Message")
					checkbox_column("Delivered")
					editable false
					cell_rows @messages
					@messages.clear if @messages.length == 1 && @messages.first.last == ""
					@messages.clear if @messages.length == 1 && @messages.first.last.nil?
				}

				horizontal_box {


@@ 113,6 121,7 @@ class Conversation

						on_clicked do
							m = message
							xml_child(m, :request, "urn:xmpp:receipts")
							EM.defer do
								BLATHER << m
								DB.execute(<<~SQL, [nil, m.id, @jid, m.to_s])


@@ 121,7 130,7 @@ class Conversation
									VALUES (?,?,?,unixepoch(),?)
								SQL
							end
							@messages << message_row(m)
							@messages << message_row(m, false)
							@message_entry.text = ""
						end
					}


@@ 153,17 162,26 @@ class Conversation
		image { image_part(rgba * 32 * 32, 32, 32, 4) }
	end

	def message_row(m)
	def message_row(m, delivered)
		from = m.from&.stripped || BLATHER.jid.stripped
		[
			$avatars[from.to_s] || default_avatar(from.to_s),
			format_sender(from),
			m.body
			m.body,
			delivered,
			m.id
		]
	end

	def new_message(m)
		@messages << message_row(m)
		@messages << message_row(m, true)
	end

	def delivered_message(id)
		row = @messages.find_index { |r| r.last == id }
		return unless row

		@messages[row] = @messages[row][0..-3] + [true, id]
	end
end



@@ 271,7 289,7 @@ def handle_live_message(m, counterpart: m.from.stripped.to_s)
	}&.[]("id")
	delay = m.delay&.stamp&.to_i || Time.now.to_i
	DB.execute(<<~SQL, [mam_id, m.id, counterpart, delay, m.to_s])
		INSERT INTO messages (mam_id, stanza_id, conversation, created_at, stanza) VALUES (?,?,?,?,?)
		INSERT INTO messages (mam_id, stanza_id, conversation, created_at, stanza, delivered) VALUES (?,?,?,?,?,1)
	SQL

	if mam_id


@@ 365,6 383,14 @@ end

message :body do |m|
	handle_live_message(m)

	if m.id && m.at("./ns:request", ns: "urn:xmpp:receipts")
		self << m.reply(remove_children: true).tap { |receipt|
			xml_child(receipt, :received, "urn:xmpp:receipts").tap { |received|
				received["id"] = m.id
			}
		}
	end
end

pubsub_event(


@@ 394,6 420,19 @@ pubsub_event(
	end
end

message "./ns:received", ns: "urn:xmpp:receipts" do |m, received|
	DB.execute(<<~SQL, [received.first["id"].to_s])
		UPDATE messages SET delivered=1 WHERE stanza_id=?
	SQL

	conversation = $conversations[m.from.stripped.to_s]
	return unless conversation

	LibUI.queue_main do
		conversation.delivered_message(received.first["id"].to_s)
	end
end

after(:roster) do
	LibUI.queue_main do
		$roster.clear