From 881bf42fbd8a1c39fca1b45c302bd0b65efafd59 Mon Sep 17 00:00:00 2001 From: Guillaume Hivert Date: Sat, 27 Jul 2024 10:18:44 +0200 Subject: [PATCH] fix: use s to trigger search instead of Cmd + K --- apps/frontend/src/data/msg.gleam | 3 ++- apps/frontend/src/frontend.gleam | 19 ++++++++++++------ apps/frontend/src/frontend/ffi.gleam | 12 ++++++----- .../view/search_input/search_input.gleam | 7 +------ apps/frontend/src/gloogle.ffi.mjs | 20 +++++++++---------- 5 files changed, 33 insertions(+), 28 deletions(-) diff --git a/apps/frontend/src/data/msg.gleam b/apps/frontend/src/data/msg.gleam index 81401a4..32780a2 100644 --- a/apps/frontend/src/data/msg.gleam +++ b/apps/frontend/src/data/msg.gleam @@ -2,6 +2,7 @@ import data/package import data/search_result.{type SearchResults} import frontend/router import lustre_http as http +import plinth/browser/event.{type Event} pub type Filter { Functions @@ -15,7 +16,7 @@ pub type Filter { pub type Msg { None - OnSearchFocus + OnSearchFocus(event: Event) SubmitSearch UpdateIsMobile(is_mobile: Bool) SearchResults(input: String, result: Result(SearchResults, http.HttpError)) diff --git a/apps/frontend/src/frontend.gleam b/apps/frontend/src/frontend.gleam index d8ae206..c512689 100644 --- a/apps/frontend/src/frontend.gleam +++ b/apps/frontend/src/frontend.gleam @@ -11,6 +11,7 @@ import frontend/view/body/search_result as sr import gleam/bool import gleam/dict import gleam/dynamic +import gleam/io import gleam/option.{None, Some} import gleam/result import gleam/uri.{type Uri} @@ -23,13 +24,16 @@ import lustre/lazy import lustre/update import lustre_http as http import modem +import plinth/browser/event.{type Event} import sketch/lustre as sketch import sketch/options as sketch_options import toast/error as toast_error -fn focus(on id: String) { +fn focus(on id: String, event event: Event) { use _ <- effect.from() - ffi.focus(on: id) + use <- bool.guard(when: ffi.is_active(id), return: Nil) + event.prevent_default(event) + ffi.focus(on: id, event: event) } fn unfocus() { @@ -39,10 +43,10 @@ fn unfocus() { fn subscribe_focus() { use dispatch <- effect.from() - use key <- ffi.subscribe_focus() - case key { + use event <- ffi.subscribe_focus() + case event.key(event) { "Escape" -> dispatch(msg.OnEscape) - _ -> dispatch(msg.OnSearchFocus) + _ -> dispatch(msg.OnSearchFocus(event)) } } @@ -99,7 +103,8 @@ fn update(model: Model, msg: Msg) { msg.ScrollTo(id) -> scroll_to(model, id) msg.OnRouteChange(route) -> handle_route_change(model, route) msg.Trendings(trendings) -> handle_trendings(model, trendings) - msg.OnSearchFocus -> update.effect(model, focus(on: "search-input")) + msg.OnSearchFocus(event) -> + update.effect(model, focus(on: "search-input", event: event)) msg.OnEscape -> update.effect(model, unfocus()) msg.UpdateIsMobile(is_mobile) -> model @@ -153,12 +158,14 @@ fn submit_search(model: Model) { Some("q=" <> new_model.submitted_input) |> modem.push("search", _, None) }) + |> update.add_effect(unfocus()) } Error(_) -> msg.SearchResults(input: model.input, result: _) |> http.expect_json(search_result.decode_search_results, _) |> http.get(config.api_endpoint() <> "/search?q=" <> model.input, _) |> update.effect(model.toggle_loading(new_model), _) + |> update.add_effect(unfocus()) } } diff --git a/apps/frontend/src/frontend/ffi.gleam b/apps/frontend/src/frontend/ffi.gleam index 44ff2a1..d8f2118 100644 --- a/apps/frontend/src/frontend/ffi.gleam +++ b/apps/frontend/src/frontend/ffi.gleam @@ -1,3 +1,5 @@ +import plinth/browser/event.{type Event} + @external(javascript, "../gloogle.ffi.mjs", "scrollTo") pub fn scroll_to(element id: String) -> fn(dispatch) -> Nil @@ -5,16 +7,16 @@ pub fn scroll_to(element id: String) -> fn(dispatch) -> Nil pub fn suscribe_is_mobile(callback: fn(Bool) -> Nil) -> Nil @external(javascript, "../gloogle.ffi.mjs", "subscribeFocus") -pub fn subscribe_focus(callback: fn(String) -> Nil) -> Nil +pub fn subscribe_focus(callback: fn(Event) -> Nil) -> Nil @external(javascript, "../gloogle.ffi.mjs", "focus") -pub fn focus(on id: String) -> Nil +pub fn focus(on id: String, event event: a) -> Nil + +@external(javascript, "../gloogle.ffi.mjs", "isActive") +pub fn is_active(element id: String) -> Bool @external(javascript, "../gloogle.ffi.mjs", "unfocus") pub fn unfocus() -> Nil -@external(javascript, "../gloogle.ffi.mjs", "isMac") -pub fn is_mac() -> Bool - @external(javascript, "../gloogle.ffi.mjs", "updateTitle") pub fn update_title(title: String) -> Nil diff --git a/apps/frontend/src/frontend/view/search_input/search_input.gleam b/apps/frontend/src/frontend/view/search_input/search_input.gleam index df3bdf6..ae2f05f 100644 --- a/apps/frontend/src/frontend/view/search_input/search_input.gleam +++ b/apps/frontend/src/frontend/view/search_input/search_input.gleam @@ -1,15 +1,10 @@ import data/msg -import frontend/ffi import frontend/view/search_input/styles as s import lustre/attribute as a import lustre/element as el import lustre/event as e pub fn view(loading loading: Bool, input input: String, small small: Bool) { - let modifier = case ffi.is_mac() { - True -> "Cmd" - False -> "Ctrl" - } s.search_with_filters([], [ s.search_input_wrapper(loading, [ s.search_input(loading, small, [ @@ -21,7 +16,7 @@ pub fn view(loading loading: Bool, input input: String, small small: Bool) { a.attribute("autocorrect", "off"), a.attribute("autocapitalize", "none"), ]), - s.shortcut_hint([], [el.text(modifier <> " + K")]), + s.shortcut_hint([], [el.text("s")]), ]), ]), ]) diff --git a/apps/frontend/src/gloogle.ffi.mjs b/apps/frontend/src/gloogle.ffi.mjs index 4397ebe..9a6644c 100644 --- a/apps/frontend/src/gloogle.ffi.mjs +++ b/apps/frontend/src/gloogle.ffi.mjs @@ -46,14 +46,20 @@ export function coerceEvent(a) { export function subscribeFocus(callback) { document.addEventListener('keydown', event => { - if (event.key === 'Escape') return callback(event.key) - if ((!event.metaKey && !event.ctrlKey) || event.key !== 'k') return - callback(event.key) + if (event.key === 'Escape') return callback(event) + if (event.key !== 's') return + callback(event) }) } -export function focus(id) { +export function isActive(id) { const element = document.getElementById(id) + return element === document.activeElement +} + +export function focus(id, event) { + const element = document.getElementById(id) + event.preventDefault() if (element) { element.focus() element.select() @@ -67,12 +73,6 @@ export function unfocus() { } } -export function isMac() { - return ( - navigator.platform.indexOf('Mac') === 0 || navigator.platform === 'iPhone' - ) -} - export function isMobile() { return window.matchMedia('(max-width: 700px)').matches }