bh 6.3.0 → 6.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +17 -0
- data/app/stylesheets/bh/chat.css +27 -0
- data/config/locales/bh.en.yml +1 -0
- data/lib/bh/helpers/chats.rb +32 -5
- data/lib/bh/message.rb +10 -7
- data/lib/bh/version.rb +1 -1
- data/package.json +1 -1
- data/public/bh/css/bh.css +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e56ebe3dc708d2c24faa0ce9419a73432bf56a2a89e30c4e43238c17a3212bfc
|
|
4
|
+
data.tar.gz: 787d7c455cded498c4e53ce624eca61981f7cc9a0522d9f743cf748bc95c09b6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 84fb271ca162d32df5eb64e4aeb9bff20752391e4c107a51259bcc9995431d5f6c4d0ff0160dfdc4da8deb080aed74197b0c3930f38e08ef2ccdb3984ff877d1
|
|
7
|
+
data.tar.gz: b7601d8739cdb4e21cb98d52aad08681a95f2366e19e7196028bfa8a9e30c47812826dee5a5a405f6862475474c8dd7f087f0a887051d9f0526d8acdf5ad6603
|
data/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,23 @@ For more information about changelogs, check
|
|
|
8
8
|
|
|
9
9
|
## [Unreleased]
|
|
10
10
|
|
|
11
|
+
## 6.4.0 - 2026-09-18
|
|
12
|
+
|
|
13
|
+
* [FEATURE] A message carries its `photos`, drawn in the bubble under its words
|
|
14
|
+
|
|
15
|
+
`Bh::Message` takes a list of addresses beside its text. Each is drawn under the words in
|
|
16
|
+
the same bubble, linking to itself in a tab of its own: what fits beside words is rarely
|
|
17
|
+
what somebody wants to look at. A message carrying pictures and no words is a message all
|
|
18
|
+
the same, rather than one still being typed.
|
|
19
|
+
|
|
20
|
+
* [FEATURE] `chat_with` takes a `note:`, said over the thread rather than in it
|
|
21
|
+
|
|
22
|
+
What the conversation is about, or the other way to reach whoever is on the far end of it.
|
|
23
|
+
Over rather than in, because nobody in the conversation said it and a bubble would claim
|
|
24
|
+
somebody had. It holds the top while the thread scrolls under it, and carries the page's
|
|
25
|
+
own background for that reason: a tint would read as somebody's turn, and without one the
|
|
26
|
+
bubbles would show through.
|
|
27
|
+
|
|
11
28
|
## 6.3.0 - 2026-09-18
|
|
12
29
|
|
|
13
30
|
* [FEATURE] The nine palettes, served at `/bh/theme/<name>.css`
|
data/app/stylesheets/bh/chat.css
CHANGED
|
@@ -7,6 +7,33 @@
|
|
|
7
7
|
overflows pushes its first message clean out of the top with no way to scroll back. */
|
|
8
8
|
.chat > :first-child { margin-block-start: auto }
|
|
9
9
|
|
|
10
|
+
/* What the whole thread is about, or the other way to reach whoever is on the far end of
|
|
11
|
+
it: said over the conversation rather than in it, quiet and in the page's own words,
|
|
12
|
+
because nobody in the conversation said it. It holds the top while the thread scrolls
|
|
13
|
+
under it, which is why it carries the page's background and not a band of its own: a
|
|
14
|
+
tint here would read as somebody's turn, and bubbles would show through without one. */
|
|
15
|
+
.chat-note {
|
|
16
|
+
position: sticky;
|
|
17
|
+
inset-block-start: 0;
|
|
18
|
+
z-index: 1;
|
|
19
|
+
background-color: var(--bs-body-bg);
|
|
20
|
+
font-size: var(--bs-font-size-sm);
|
|
21
|
+
color: var(--bs-fg-2);
|
|
22
|
+
margin: 0;
|
|
23
|
+
padding-block: 0.25rem 0.75rem;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/* A picture a message carries, under its words and no wider than the bubble holding it. */
|
|
27
|
+
.chat-photo {
|
|
28
|
+
display: block;
|
|
29
|
+
max-width: 100%;
|
|
30
|
+
height: auto;
|
|
31
|
+
border-radius: 0.5rem;
|
|
32
|
+
margin-block-start: 0.5rem;
|
|
33
|
+
}
|
|
34
|
+
/* The first thing in a bubble has the bubble's own padding over it already. */
|
|
35
|
+
.chat-bubble > a:first-child .chat-photo { margin-block-start: 0 }
|
|
36
|
+
|
|
10
37
|
/* Who said it and when, small, over the bubble it belongs to and on its side. */
|
|
11
38
|
.chat-aside { font-size: var(--bs-font-size-sm); color: var(--bs-fg-2); margin: 0 0.75rem }
|
|
12
39
|
.chat-aside-out { align-self: flex-end; margin-inline-end: 1.25rem }
|
data/config/locales/bh.en.yml
CHANGED
data/lib/bh/helpers/chats.rb
CHANGED
|
@@ -8,12 +8,16 @@ module Bh
|
|
|
8
8
|
include Asides, Asks
|
|
9
9
|
|
|
10
10
|
# `messages` as a thread that opens at its newest and, where `url` is given, a field
|
|
11
|
-
# under it that posts the next message there, suggesting `hints` one at a time.
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
# under it that posts the next message there, suggesting `hints` one at a time. A
|
|
12
|
+
# `note` stands over the whole thread: what this conversation is about, or the other
|
|
13
|
+
# way to reach whoever is on the far end of it.
|
|
14
|
+
def chat_with(messages:, url: nil, hints: [], note: nil)
|
|
15
|
+
parts = [bh_chat_note(note), bh_chat_messages(messages)]
|
|
14
16
|
parts.push bh_chat_ask(url, hints) if url
|
|
15
17
|
|
|
16
|
-
|
|
18
|
+
said = safe_join parts.compact, "\n"
|
|
19
|
+
|
|
20
|
+
tag.div said, class: 'chat-thread', data: { controller: 'thread' }
|
|
17
21
|
end
|
|
18
22
|
|
|
19
23
|
private
|
|
@@ -30,13 +34,36 @@ module Bh
|
|
|
30
34
|
safe_join parts.compact, "\n"
|
|
31
35
|
end
|
|
32
36
|
|
|
37
|
+
# Said over the thread rather than in it, so it is not one of the turns: nobody
|
|
38
|
+
# said this, and a bubble would claim somebody had.
|
|
39
|
+
def bh_chat_note(note)
|
|
40
|
+
tag.p note, class: 'chat-note' if note.present?
|
|
41
|
+
end
|
|
42
|
+
|
|
33
43
|
def bh_chat_bubble(message)
|
|
34
44
|
side = Asides::SIDES.fetch message.side
|
|
35
|
-
|
|
45
|
+
said = bh_chat_said message
|
|
46
|
+
return tag.p said, class: "chat-bubble chat-#{side}" if said
|
|
36
47
|
|
|
37
48
|
tag.p safe_join(Array.new(3) { tag.span }), class: "chat-bubble chat-#{side} chat-typing",
|
|
38
49
|
aria: { label: t('bh.typing') }
|
|
39
50
|
end
|
|
51
|
+
|
|
52
|
+
# The words and then the pictures, which is the order a phone lays a picture
|
|
53
|
+
# message out in -- and nothing at all where a message has neither yet.
|
|
54
|
+
def bh_chat_said(message)
|
|
55
|
+
pictures = Array(message.photos).map { |photo| bh_chat_photo photo }
|
|
56
|
+
|
|
57
|
+
safe_join([message.text, *pictures].compact_blank, "\n").presence
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# A picture in the bubble, opening full size in a tab of its own: what fits beside
|
|
61
|
+
# words is rarely what somebody wants to look at.
|
|
62
|
+
def bh_chat_photo(url)
|
|
63
|
+
tag.a href: url, target: :_blank, rel: 'noopener' do
|
|
64
|
+
tag.img src: url, alt: t('bh.photo'), class: 'chat-photo', loading: :lazy
|
|
65
|
+
end
|
|
66
|
+
end
|
|
40
67
|
end
|
|
41
68
|
end
|
|
42
69
|
end
|
data/lib/bh/message.rb
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
module Bh
|
|
2
2
|
# One message of a chat, as `chat_with` draws it: which `side` its bubble is on (`:left`
|
|
3
|
-
# for the other party, `:right` for the reader), its `text`,
|
|
4
|
-
# was said (`at`), how its `delivery`
|
|
5
|
-
# `:undelivered` or nil) and what it `cost` in
|
|
6
|
-
# answering the same
|
|
7
|
-
# model to hang them on. A message with
|
|
8
|
-
|
|
9
|
-
|
|
3
|
+
# for the other party, `:right` for the reader), its `text`, the `photos` it carries as
|
|
4
|
+
# a list of addresses, who the `sender` was, when it was said (`at`), how its `delivery`
|
|
5
|
+
# went (`:delivered`, `:sent`, `:failed`, `:undelivered` or nil) and what it `cost` in
|
|
6
|
+
# dollars, where anything did. Any object answering the same seven is a message too;
|
|
7
|
+
# this is for a host that has the facts and no model to hang them on. A message with
|
|
8
|
+
# neither words nor pictures yet is drawn as being typed.
|
|
9
|
+
Message = Data.define :side, :text, :photos, :sender, :at, :delivery, :cost do
|
|
10
|
+
def initialize(side:, text: nil, photos: [], sender: nil, at: nil, delivery: nil, cost: nil)
|
|
11
|
+
super
|
|
12
|
+
end
|
|
10
13
|
end
|
|
11
14
|
end
|
data/lib/bh/version.rb
CHANGED
data/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bh6",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.4.0",
|
|
4
4
|
"private": true,
|
|
5
5
|
"description": "Bootstrap 6 in a Rails app: the form builder that dresses every field, the components Bootstrap ships behavior for and no markup, and the Stimulus controllers behind them.",
|
|
6
6
|
"license": "MIT",
|