Detect platform and label the correct hotkey shortcut

Yes, Platform Agent is overkill for just this but there isn't a one-size JS solution for updating both input placeholders and other HTML text and we're likely to need it later for other things like displaying platform-specific PWA prompts.
This commit is contained in:
Jason Zimdars
2025-05-27 12:14:24 -05:00
parent c2c3a8d8ab
commit d17134cb5c
9 changed files with 72 additions and 7 deletions
+1
View File
@@ -27,6 +27,7 @@ gem "rqrcode"
gem "redcarpet"
gem "rouge"
gem "jbuilder"
gem "platform_agent"
# Telemetry and logging
gem "sentry-ruby"
+4
View File
@@ -272,6 +272,9 @@ GEM
parser (3.3.8.0)
ast (~> 2.4.1)
racc
platform_agent (1.0.1)
activesupport (>= 5.2.0)
useragent (~> 0.16.3)
pp (0.6.2)
prettyprint
prettyprint (0.2.0)
@@ -456,6 +459,7 @@ DEPENDENCIES
importmap-rails
jbuilder
kamal
platform_agent
propshaft
puma (>= 5.0)
rails!
+1 -1
View File
@@ -1,5 +1,5 @@
class ApplicationController < ActionController::Base
include Authentication, CurrentTimezone
include Authentication, CurrentTimezone, SetPlatform
stale_when_importmap_changes
allow_browser versions: :modern
+12
View File
@@ -0,0 +1,12 @@
module SetPlatform
extend ActiveSupport::Concern
included do
helper_method :platform
end
private
def platform
@platform ||= ApplicationPlatform.new(request.user_agent)
end
end
+19
View File
@@ -0,0 +1,19 @@
module HotkeysHelper
def hotkey_label(hotkey)
hotkey.split(",").first if hotkey
case hotkey
when Array
hotkey.map { |key|
if key == "ctrl" && platform.mac?
""
elsif key == "enter"
platform.mac? ? "return" : "enter"
else
key
end
}.join("+")
else
hotkey.split(",").first if hotkey
end
end
end
+29
View File
@@ -0,0 +1,29 @@
class ApplicationPlatform < PlatformAgent
def ios?
match? /iPhone|iPad/
end
def android?
match? /Android/
end
def mac?
match? /Macintosh/
end
def chrome?
user_agent.browser.match? /Chrome/
end
def safari?
user_agent.browser.match? /Safari/
end
def mobile?
ios? || android?
end
def desktop?
!mobile?
end
end
+2 -2
View File
@@ -7,7 +7,7 @@
<div class="card-filter--collection flex-inline flex-column align-center center position-relative" data-controller="dialog" data-action="click@document->dialog#closeOnClickOutside">
<%= tag.button class: "txt-align-center input input--select borderless txt-medium",
data: {
action: "click->dialog#open:stop keydown.meta+j@document->hotkey#click",
action: "click->dialog#open:stop keydown.meta+j@document->hotkey#click keydown.ctrl+j@document->hotkey#click",
controller: "hotkey" } do %>
<h1 class="txt-large overflow-ellipsis margin-none">
<span><%= filter_title filter %></span>
@@ -38,7 +38,7 @@
<%= render "cards/index/collections_filter", filter: filter %>
</menu>
<p class="txt-small txt-nowrap txt-align-center margin-block-half full-width">
Press <kbd class="kbd">⌘j</kbd> anytime to open this, <kbd class="kbd">esc</kbd> to close.
Press <kbd class="kbd"><%= hotkey_label(["ctrl", "J"]) -%></kbd> anytime to open this, <kbd class="kbd">esc</kbd> to close.
</p>
<% end %>
</div>
+2 -2
View File
@@ -4,7 +4,7 @@
data: {
controller: "form",
terminal_target: "form",
action: "turbo:submit-start->terminal#commandSubmitted turbo:submit-end->terminal#focus keydown.meta+k@document->terminal#focus keydown.enter->terminal#executeCommand keydown.esc->terminal#hideMenus turbo:submit-end->terminal#handleCommandResponse"
action: "turbo:submit-start->terminal#commandSubmitted turbo:submit-end->terminal#focus keydown.meta+k@document->terminal#focus keydown.ctrl+k@document->terminal#focus keydown.enter->terminal#executeCommand keydown.esc->terminal#hideMenus turbo:submit-end->terminal#handleCommandResponse"
} do %>
<label class="terminal__label txt-nowrap" for="fizzy_do">Fizzy do &gt;</label>
@@ -17,7 +17,7 @@
terminal_target: "input",
action: "keydown.up->toggle-class#add:prevent keydown.up->navigable-list#selectCurrentOrLast terminal#hideError"
},
placeholder: "Press ⌘+K to search or type commands…",
placeholder: "Press #{ hotkey_label(["ctrl", "K"]) } to search or type commands…",
spellcheck: "false" %>
<%= hidden_field_tag "confirmed", nil, data: { terminal_target: "confirmation" } %>
+2 -2
View File
@@ -2,7 +2,7 @@
data-controller="dialog" data-action="keydown.esc->dialog#close click@document->dialog#closeOnClickOutside">
<%= tag.button class:"events__filter-btn input input--select flex-inline center min-width max-width txt-small",
data: {
action: "click->dialog#open:stop keydown.meta+j@document->hotkey#click",
action: "click->dialog#open:stop keydown.meta+j@document->hotkey#click keydown.ctrl+j@document->hotkey#click",
controller: "hotkey" } do %>
<span class="overflow-ellipsis center">
<%= filter_selected_collections_label(filter) %>
@@ -35,7 +35,7 @@
<% end %>
<p class="txt-small txt-nowrap txt-align-center margin-block-half full-width">
Press <kbd class="kbd">⌘j</kbd> anytime to open this, <kbd class="kbd">esc</kbd> to close.
Press <kbd class="kbd"><%= hotkey_label(["ctrl", "K"]) -%></kbd> anytime to open this, <kbd class="kbd">esc</kbd> to close.
</p>
<% end %>
</div>