From de62d1389157c7f65223a4e53b5e265824ded0fd Mon Sep 17 00:00:00 2001 From: Akira Matsuda Date: Sat, 25 Oct 2025 23:48:14 +0900 Subject: [PATCH 1/2] Extract thread view queries to a private method --- app/controllers/messages_controller.rb | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/app/controllers/messages_controller.rb b/app/controllers/messages_controller.rb index ae407fa..48a5e9c 100644 --- a/app/controllers/messages_controller.rb +++ b/app/controllers/messages_controller.rb @@ -6,14 +6,7 @@ def index(list_name: nil, yyyymm: nil, q: nil, page: nil) if list_name @list = List.find_by_name list_name - @yyyymms = Message.where(list_id: @list).order('yyyymm').pluck(Arel.sql "distinct to_char(published_at, 'YYYYMM') as yyyymm") - @yyyymm = yyyymm || @yyyymms.last - - root_query = Message.where(list_id: @list, parent_id: nil).where("to_char(published_at, 'YYYYMM') = ?", @yyyymm).order(:id) - messages = Message.with_recursive(parent_and_children: [root_query, Message.joins('inner join parent_and_children on messages.parent_id = parent_and_children.id')]) - .joins('inner join parent_and_children on parent_and_children.id = messages.id') - - @messages = compose_tree(messages) + render_threads yyyymm: yyyymm elsif q search q, page @@ -33,6 +26,19 @@ def show(list_name:, list_seq:) private + def render_threads(yyyymm: nil) + @yyyymms = Message.where(list_id: @list).order('yyyymm').pluck(Arel.sql "distinct to_char(published_at, 'YYYYMM') as yyyymm") + @yyyymm = yyyymm || @yyyymms.last + + root_query = Message.where(list_id: @list, parent_id: nil).where("to_char(published_at, 'YYYYMM') = ?", @yyyymm).order(:id) + messages = Message.with_recursive(parent_and_children: [root_query, Message.joins('inner join parent_and_children on messages.parent_id = parent_and_children.id')]) + .joins('inner join parent_and_children on parent_and_children.id = messages.id') + + @messages = compose_tree(messages) + + render :index + end + def get_list_ids(params) list_ids = [] ['ruby-talk', 'ruby-core', 'ruby-list', 'ruby-dev'].each do |name| From d2ac64a1889381235fd07311c1667ba07c8ae352 Mon Sep 17 00:00:00 2001 From: Akira Matsuda Date: Sat, 25 Oct 2025 23:59:11 +0900 Subject: [PATCH 2/2] Show threads list on messages#show action as well --- app/controllers/messages_controller.rb | 5 +++++ .../controllers/message_list_controller.js | 10 ++++++++++ .../controllers/thread_controller.js | 12 ++++++++++-- app/views/messages/_thread.html.erb | 5 +++-- app/views/messages/index.html.erb | 18 +++++++++++------- 5 files changed, 39 insertions(+), 11 deletions(-) diff --git a/app/controllers/messages_controller.rb b/app/controllers/messages_controller.rb index 48a5e9c..f792d4f 100644 --- a/app/controllers/messages_controller.rb +++ b/app/controllers/messages_controller.rb @@ -22,6 +22,11 @@ def index(list_name: nil, yyyymm: nil, q: nil, page: nil) def show(list_name:, list_seq:) @list = List.find_by_name(list_name) @message = Message.find_by!(list_id: @list, list_seq: list_seq) + + # If this is a turbo frame request, just render the message + return if turbo_frame_request? + + render_threads yyyymm: @message.published_at.strftime('%Y%m') end private diff --git a/app/javascript/controllers/message_list_controller.js b/app/javascript/controllers/message_list_controller.js index 06c9253..0ce0b0f 100644 --- a/app/javascript/controllers/message_list_controller.js +++ b/app/javascript/controllers/message_list_controller.js @@ -1,6 +1,16 @@ import { Controller } from "@hotwired/stimulus" export default class extends Controller { + connect() { + // Scroll to selected message on page load, with a delay to ensure threads are expanded + setTimeout(() => { + const selected = this.element.querySelector('.message-selected') + if (selected) { + selected.scrollIntoView({behavior: 'smooth', block: 'center'}) + } + }, 100) + } + select(event) { // Remove highlight from previously selected message const previousSelected = this.element.querySelector('.message-selected') diff --git a/app/javascript/controllers/thread_controller.js b/app/javascript/controllers/thread_controller.js index 6ace0af..2c1abb7 100644 --- a/app/javascript/controllers/thread_controller.js +++ b/app/javascript/controllers/thread_controller.js @@ -5,9 +5,17 @@ export default class extends Controller { static targets = ["children", "icon"] connect() { - // Initially hide children + // Initially hide children unless one is selected if (this.hasChildrenTarget) { - this.childrenTarget.classList.add("hidden") + const hasSelectedChild = this.childrenTarget.querySelector('.message-selected') + if (hasSelectedChild) { + // Keep expanded and rotate icon + if (this.hasIconTarget) { + this.iconTarget.classList.add("rotate-90") + } + } else { + this.childrenTarget.classList.add("hidden") + } } } diff --git a/app/views/messages/_thread.html.erb b/app/views/messages/_thread.html.erb index c9dfea2..9ac2f31 100644 --- a/app/views/messages/_thread.html.erb +++ b/app/views/messages/_thread.html.erb @@ -1,6 +1,7 @@
data-controller="thread"<% end %>> + <% selected = defined?(@message) && @message&.id == message.id %> <% if depth == 0 %> - <%= link_to [list, message], class: 'message-item block bg-white dark:bg-gray-800 rounded-lg shadow-md border border-gray-200 dark:border-gray-700 overflow-hidden hover:shadow-lg transition-shadow', data: {turbo_frame: 'message_content', turbo_action: 'advance', action: 'click->message-list#select'} do %> + <%= link_to [list, message], class: "message-item block bg-white dark:bg-gray-800 rounded-lg shadow-md border border-gray-200 dark:border-gray-700 overflow-hidden hover:shadow-lg transition-shadow#{' message-selected' if selected}", data: {turbo_frame: 'message_content', turbo_action: 'advance', action: 'click->message-list#select'} do %>
@@ -35,7 +36,7 @@
<% end %> <% else %> - <%= link_to [list, message], class: 'message-item block py-2 border-l-2 border-gray-200 dark:border-gray-700 pl-4 hover:border-red-400 dark:hover:border-red-500 transition-colors', data: {turbo_frame: 'message_content', turbo_action: 'advance', action: 'click->message-list#select'} do %> + <%= link_to [list, message], class: "message-item block py-2 border-l-2 border-gray-200 dark:border-gray-700 pl-4 hover:border-red-400 dark:hover:border-red-500 transition-colors#{' message-selected' if selected}", data: {turbo_frame: 'message_content', turbo_action: 'advance', action: 'click->message-list#select'} do %>
diff --git a/app/views/messages/index.html.erb b/app/views/messages/index.html.erb index 1b563eb..e97cd38 100644 --- a/app/views/messages/index.html.erb +++ b/app/views/messages/index.html.erb @@ -42,14 +42,18 @@
<%= turbo_frame_tag "message_content", class: "block" do %> -
-
- - - -

Select a message to view

+ <% if @message %> + <%= render @message %> + <% else %> +
+
+ + + +

Select a message to view

+
-
+ <% end %> <% end %>