Module: Protege::MessagesHelper
- Included in:
- ApplicationHelper
- Defined in:
- app/helpers/protege/messages_helper.rb
Overview
View helpers for rendering a Message within a thread — sender, timestamp,
recipients, subject, and expandable raw headers. Liveness (processing/reasoning/tool use) is not
shown on the message; it lives in the console's introspection panel.
Instance Method Summary collapse
-
#message_attachments(message) ⇒ ActiveSupport::SafeBuffer
Render a message's attachments as a row of download-link chips, or nothing when there are none.
-
#message_headers(message) ⇒ ActiveSupport::SafeBuffer
Render an expandable
<details>block listing the message's raw headers. -
#message_recipients(message) ⇒ ActiveSupport::SafeBuffer
Render the To line, appending a Cc line only when Cc recipients exist.
-
#message_sender(message) ⇒ ActiveSupport::SafeBuffer
Render the sender line — persona name for outbound mail, local part of the address for inbound mail — followed by the full address.
-
#message_subject(message) ⇒ ActiveSupport::SafeBuffer
Render the subject line, but only when it differs from the thread subject.
-
#message_timestamp(message) ⇒ ActiveSupport::SafeBuffer
Render the message's send time as a
<time>element. -
#search_result_date(message) ⇒ String?
The search-result row's right-aligned date — the email's sent time in short
m/d/yyform. -
#search_result_title(message) ⇒ String
The search-result row title: the email subject, or a placeholder when blank.
Instance Method Details
#message_attachments(message) ⇒ ActiveSupport::SafeBuffer
Render a message's attachments as a row of download-link chips, or nothing when there are none.
Each chip links to the blob via Active Storage's host-app route (+main_app.rails_blob_path+, since
those routes live on the host, not the engine) and shows the filename and a human-readable size.
link_to escapes the filename, which is copied verbatim from attacker-controlled inbound headers.
The link forces a download two ways: disposition: "attachment" makes the service set
Content-Disposition: attachment (so even an .html blob downloads rather than rendering), and
the download attribute both hints the filename and opts the anchor out of Turbo Drive — without
it Turbo intercepts the click and renders an HTML attachment as a page instead of downloading it.
103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
# File 'app/helpers/protege/messages_helper.rb', line 103 def () return ''.html_safe unless ..attached? chips = ..map do || label = "#{.filename} (#{number_to_human_size(.byte_size)})" link_to(label, main_app.rails_blob_path(, disposition: 'attachment', only_path: true), download: .filename.to_s, class: 'inline-flex items-center gap-1 rounded px-1.5 py-0.5 text-xs font-medium hover:underline', style: 'background: var(--surface-subtle); border: 1px solid var(--border)') end tag.div(class: 'mt-3 flex flex-wrap gap-2') { safe_join(chips) } end |
#message_headers(message) ⇒ ActiveSupport::SafeBuffer
Render an expandable <details> block listing the message's raw headers.
83 84 85 86 87 88 |
# File 'app/helpers/protege/messages_helper.rb', line 83 def () tag.details(class: 'mt-1') do tag.summary('Headers', class: 'cursor-pointer text-xs', style: 'color: var(--text-faint)') + () end end |
#message_recipients(message) ⇒ ActiveSupport::SafeBuffer
Render the To line, appending a Cc line only when Cc recipients exist.
56 57 58 59 60 61 62 63 64 65 |
# File 'app/helpers/protege/messages_helper.rb', line 56 def () to = tag.span("To: #{Array(.to_addresses).join(', ')}") cc = if Array(.cc_addresses).any? tag.span("Cc: #{.cc_addresses.join(', ')}", class: 'ml-2') else ''.html_safe end tag.div(class: 'mt-1 text-xs', style: 'color: var(--text-muted)') { safe_join([to, cc]) } end |
#message_sender(message) ⇒ ActiveSupport::SafeBuffer
Render the sender line — persona name for outbound mail, local part of the address for inbound mail — followed by the full address.
29 30 31 32 33 34 35 36 37 |
# File 'app/helpers/protege/messages_helper.rb', line 29 def () name = if .outbound? .persona.name else .from_address.to_s.split('@').first end tag.span("#{name} <#{.from_address}>", class: 'font-semibold') end |
#message_subject(message) ⇒ ActiveSupport::SafeBuffer
Render the subject line, but only when it differs from the thread subject.
71 72 73 74 75 76 77 |
# File 'app/helpers/protege/messages_helper.rb', line 71 def () if .subject.present? && .subject != .email_thread.subject tag.div("Subject: #{.subject}", class: 'mt-1 text-xs font-medium') else ''.html_safe end end |
#message_timestamp(message) ⇒ ActiveSupport::SafeBuffer
Render the message's send time as a <time> element.
43 44 45 46 47 48 49 50 |
# File 'app/helpers/protege/messages_helper.rb', line 43 def () tag.time( .sent_at.strftime('%b %-d, %Y %H:%M'), datetime: .sent_at.iso8601, class: 'flex-shrink-0 text-xs', style: 'color: var(--text-faint)' ) end |
#search_result_date(message) ⇒ String?
The search-result row's right-aligned date — the email's sent time in short m/d/yy form.
20 21 22 |
# File 'app/helpers/protege/messages_helper.rb', line 20 def search_result_date() .sent_at&.strftime('%-m/%-d/%y') end |
#search_result_title(message) ⇒ String
The search-result row title: the email subject, or a placeholder when blank.
12 13 14 |
# File 'app/helpers/protege/messages_helper.rb', line 12 def search_result_title() .subject.presence || '(no subject)' end |