on master help sign in
Show search sources with filtering
commit4841a52fad9ec0535fdb87f67bd661a4ef8ac0b3 authoriko <mail@iko.soy> dateThu 3 Aug 2023, 22:29 (3 years ago) parent3de0c04
5 files changed+192−25
dev/elm-live.sh+1−1 frontend/index.html+16 frontend/src/Main.elm+155−18 zod/seax/app/seax.hoon+16−2 zod/seax/lib/rank.hoon+4−4
dev/elm-live.sh+1−1
@@ -4,4 +4,4 @@ set -e
44
55cd "$(dirname "$0")/../frontend"
66
7−nix run nixpkgs#elmPackages.elm-live -- src/Main.elm --start-page=index.html -- --output=elm.js "$@"
7+nix run nixpkgs#elmPackages.elm-live -- src/Main.elm --start-page=index.html -- --debug --output=elm.js "$@"
frontend/index.html+16
@@ -6,6 +6,22 @@
66 <style>
77 body {
88 font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
9+ margin: 0;
10+ }
11+ @keyframes bobbing {
12+ from {
13+ transform: translateY(-30px);
14+ }
15+ to {
16+ transform: traslateY(0);
17+ }
18+ }
19+ .bobbing {
20+ animation-duration: 2s;
21+ animation-name: bobbing;
22+ animation-iteration-count: infinite;
23+ animation-direction: alternate;
24+ animation-timing-function: ease-in-out;
925 }
1026 </style>
1127 </head>
frontend/src/Main.elm+155−18
@@ -1,26 +1,27 @@
11port module Main exposing (main)
22
33import Animator
4+import Browser.Events exposing (onAnimationFrameDelta)
45import Dict exposing (Dict)
56import Element exposing (..)
67import Element.Background as Background
78import Element.Border as Border
8−import Element.Events as Events
9+import Element.Events as Events exposing (onClick)
910import Element.Font as Font
1011import Element.Input as Input
1112import Element.Keyed as Keyed
12−import Heroicons.Outline
1313import Html.Attributes
14−import Html.Events
1514import Json.Decode as JD
1615import List.Extra
17−import Svg.Attributes exposing (opacity)
16+import Set exposing (Set)
1817import Time exposing (Posix)
1918import Ur
2019import Ur.Cmd
2120import Ur.Deconstructor as D
21+import Ur.Jam exposing (isSig)
2222import Ur.Run
2323import Ur.Sub
24+import Ur.Types exposing (Noun(..))
2425
2526
2627url : String
@@ -28,18 +29,36 @@ url =
2829 "http://localhost:8080"
2930
3031
32+type SearchEngineState
33+ = Loading
34+ | Failed
35+ | Completed
36+
37+
38+deconstructSearchEngineState : D.Deconstructor SearchEngineState
39+deconstructSearchEngineState =
40+ D.oneOf
41+ [ D.const D.cord "loading" |> D.map (\_ -> Loading)
42+ , D.const D.cord "failed" |> D.map (\_ -> Failed)
43+ , D.const D.cord "completed" |> D.map (\_ -> Completed)
44+ ]
45+
46+
3147type alias Model =
3248 { ship : Maybe String
3349 , search : String
3450 , initiatedSearch : Maybe String
3551 , searchResults : List SearchResult
3652 , resultTimelines : Dict String ( Animator.Timeline Int, Animator.Timeline Bool )
53+ , engines : List ( String, SearchEngineState )
54+ , selectedEngines : Set String
3755 }
3856
3957
4058type alias SearchResult =
4159 { title : String
4260 , link : String
61+ , engines : Set String
4362 }
4463
4564
@@ -48,9 +67,10 @@ type Msg
4867 | GotShipName String
4968 | UpdateSearch String
5069 | Search String
51− | UpdateSearchResults (List SearchResult)
70+ | UpdateSearchResults (List SearchResult) (List ( String, SearchEngineState ))
5271 | OpenResult String
5372 | Tick Posix
73+ | ToggleSearchEngine String
5474
5575
5676main : Ur.Run.Program Model Msg
@@ -59,9 +79,11 @@ main =
5979 { init =
6080 ( { ship = Nothing
6181 , search = ""
62− , initiatedSearch = Nothing
82+ , initiatedSearch = Just "urbit"
6383 , searchResults = []
6484 , resultTimelines = Dict.empty
85+ , engines = []
86+ , selectedEngines = Set.empty
6587 }
6688 , Cmd.batch
6789 [ Ur.logIn url "lidlut-tabwed-pillex-ridrup"
@@ -83,13 +105,19 @@ main =
83105 , path = [ "search", query ]
84106 , ship = ship_
85107 , deconstructor =
86− D.list (D.cell D.cord D.cord)
108+ D.cell
109+ (D.list (D.cell D.cord deconstructSearchEngineState))
110+ (D.list (D.cell (D.list D.cord) (D.cell D.cord D.cord)))
87111 |> D.map
88− (List.map
89− (\( title, link ) ->
90− { title = title, link = link }
91− )
92− >> UpdateSearchResults
112+ (\( engines, results ) ->
113+ UpdateSearchResults
114+ (List.map
115+ (\( resultEngines, ( title, link ) ) ->
116+ { engines = Set.fromList resultEngines, title = title, link = link }
117+ )
118+ results
119+ )
120+ engines
93121 )
94122 }
95123
@@ -100,6 +128,42 @@ main =
100128 }
101129
102130
131+debug : (String -> String) -> D.Deconstructor a -> D.Deconstructor a
132+debug log f noun =
133+ case f noun of
134+ Just x ->
135+ Just x
136+
137+ Nothing ->
138+ let
139+ _ =
140+ log (prettyNoun noun)
141+ in
142+ Nothing
143+
144+
145+prettyNoun : Noun -> String
146+prettyNoun noun =
147+ let
148+ go isRhs n =
149+ case n of
150+ Atom a ->
151+ if isSig a then
152+ "~"
153+
154+ else
155+ "@"
156+
157+ Cell ( lhs, rhs ) ->
158+ if isRhs then
159+ go False lhs ++ " " ++ go True rhs
160+
161+ else
162+ "[" ++ go False lhs ++ " " ++ go True rhs ++ "]"
163+ in
164+ go False noun
165+
166+
103167view : Model -> Element Msg
104168view model =
105169 case model.initiatedSearch of
@@ -110,10 +174,65 @@ view model =
110174 ]
111175
112176 Just query ->
113− column [ width fill, padding 8, spacing 16 ]
114− [ searchView model
115− , Keyed.column [ width fill ]
177+ column [ width fill, spacing 16 ]
178+ [ row [ spacing 16, width fill ]
179+ [ searchView model |> el [ padding 8 ]
180+ , model.engines
181+ |> List.filter (\( _, state ) -> state /= Failed)
182+ |> List.map
183+ (\( name, state ) ->
184+ text ("%" ++ name)
185+ |> el
186+ ([ Font.size 43
187+ , Font.bold
188+ ]
189+ ++ (if Set.isEmpty model.selectedEngines then
190+ []
191+
192+ else if Set.member name model.selectedEngines then
193+ []
194+
195+ else
196+ [ Font.color (rgb 0.8 0.8 0.8)
197+ ]
198+ )
199+ ++ (case state of
200+ Loading ->
201+ [ Html.Attributes.class "bobbing" |> htmlAttribute
202+ , Font.color (rgb 0.8 0.8 0.8)
203+ ]
204+
205+ Completed ->
206+ [ mouseOver
207+ [ Font.color (rgb 0.6 0.6 0.6)
208+ ]
209+ , pointer
210+ , Events.onClick (ToggleSearchEngine name)
211+ ]
212+
213+ Failed ->
214+ []
215+ )
216+ )
217+ )
218+ |> row
219+ [ spacing 16
220+ , clipX
221+ , scrollbarX
222+ , width fill
223+ , height (px 62)
224+ ]
225+ ]
226+ , Keyed.column [ width fill, padding 8 ]
116227 (model.searchResults
228+ |> List.filter
229+ (\{ engines } ->
230+ if Set.isEmpty model.selectedEngines then
231+ True
232+
233+ else
234+ Set.intersect engines model.selectedEngines |> Set.isEmpty |> not
235+ )
117236 |> List.map
118237 (\{ title, link } ->
119238 ( link
@@ -172,7 +291,7 @@ view model =
172291searchView : { a | search : String } -> Element Msg
173292searchView model =
174293 row [ spacing 8 ]
175− [ Input.text []
294+ [ Input.text [ width (px 250) ]
176295 { onChange = UpdateSearch
177296 , placeholder = Nothing
178297 , text = model.search
@@ -214,7 +333,7 @@ update msg model =
214333 Search query ->
215334 ( { model | initiatedSearch = Just query }, Ur.Cmd.none )
216335
217− UpdateSearchResults results ->
336+ UpdateSearchResults results engines ->
218337 let
219338 foo =
220339 List.Extra.zip (List.range 0 (List.length results - 1)) results
@@ -231,7 +350,13 @@ update msg model =
231350 )
232351 |> Dict.fromList
233352 in
234− ( { model | resultTimelines = foo, searchResults = results }, Ur.Cmd.none )
353+ ( { model
354+ | resultTimelines = foo
355+ , searchResults = results
356+ , engines = engines
357+ }
358+ , Ur.Cmd.none
359+ )
235360
236361 OpenResult url_ ->
237362 ( model, Ur.Cmd.none )
@@ -239,6 +364,13 @@ update msg model =
239364 Tick time ->
240365 ( Animator.update time (animator model) model, Ur.Cmd.none )
241366
367+ ToggleSearchEngine name ->
368+ if Set.member name model.selectedEngines then
369+ ( { model | selectedEngines = Set.remove name model.selectedEngines }, Ur.Cmd.none )
370+
371+ else
372+ ( { model | selectedEngines = Set.insert name model.selectedEngines }, Ur.Cmd.none )
373+
242374
243375animator : Model -> Animator.Animator Model
244376animator model =
@@ -273,6 +405,11 @@ result f g res =
273405 f a
274406
275407
408+listsHaveElementsInCommon : List comparable -> List comparable -> Bool
409+listsHaveElementsInCommon a b =
410+ Set.intersect (Set.fromList a) (Set.fromList b) |> Set.isEmpty |> not
411+
412+
276413port createEventSource : String -> Cmd msg
277414
278415
zod/seax/app/seax.hoon+16−2
@@ -42,15 +42,29 @@ $:
4242--
4343
4444=/ state *state-0
45+=* current-engines
46+ |= =query
47+ ^- (list [term ?(%loading %failed %completed)])
48+ %+ turn ~(tap in ~(key by engines))
49+ |= engine=term
50+ :- engine
51+ =/ results
52+ (~(get by search-results:(~(got by search-subscriptions.state) query)) engine)
53+ ?~ results %loading
54+ ?~ +.results %failed
55+ %completed
4556=* search-results
4657 |= =query
4758 %- rank-results
4859 =/ search-state=search-state
4960 (~(got by search-subscriptions.state) query)
5061 search-results.search-state
62+=* sink-for-query
63+ |= =query
64+ [(current-engines query) (search-results query)]
5165=* sink
5266 |= =query
53− ((sink:^sink ~[~[%search query]]) (search-results query))
67+ ((sink:^sink ~[~[%search query]]) (sink-for-query query))
5468
5569^- agent:gall
5670%- agent:dbug
@@ -130,7 +144,7 @@ $:
130144 (~(put by search-results.search-subscription) engine-name results)
131145 =. search-subscriptions.state
132146 (~(put by search-subscriptions.state) query search-subscription)
133− =^ card sink (sync:sink (search-results query))
147+ =^ card sink (sync:sink (sink-for-query query))
134148 [~[card] this]
135149 ==
136150++ on-fail |=([term tang] `..on-init)
zod/seax/lib/rank.hoon+4−4
@@ -3,7 +3,7 @@
33
44=<
55|= results=(list [engine=term results=(list search-result)])
6−^- (list search-result)
6+^- (list [engines=(list term) =search-result])
77=/ url-to-engine-map
88 ^- (list (map @t [engines=(list term) ords=(list @u) result=search-result]))
99 %- zing
@@ -29,7 +29,7 @@
2929 ==
3030 [(weld engines-lhs engines-rhs) (weld ords-lhs ords-rhs) result]
3131=/ ranking
32− ^- (list [ord=@rs result=search-result])
32+ ^- (list [ord=@rs result=[engines=(list term) =search-result]])
3333 %+ turn ~(val by url-to-engines-map)
3434 |= [engines=(list term) ords=(list @u) result=search-result]
3535 =/ engine-weights
@@ -52,13 +52,13 @@
5252 =/ rank
5353 ^- @rs
5454 (mul:rs engine-weights position-weights)
55− [ord=rank result=result]
55+ [ord=rank result=[engines result]]
5656=/ sorted-results
5757 %+ sort ranking
5858 |= [[lhs=@rs *] [rhs=@rs *]]
5959 %+ gth lhs rhs
6060%+ turn sorted-results
61−|= [* result=search-result]
61+|= [* result=[(list term) search-result]]
6262result
6363
6464|%