summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYorhel <git@yorhel.nl>2020-11-28 19:36:09 +0100
committerYorhel <git@yorhel.nl>2020-11-28 19:36:14 +0100
commitdd2762e6afab7cf33794c3d95bcfc8c9506702a1 (patch)
treeff3f2a0ffe7c964a65a719f14c3d25ab1d4fa930
parent8323430e739893d0899e92aa77097120861d1c43 (diff)
AdvSearch: Add resolution autocomplete
Using a lazily loaded static list
-rw-r--r--elm/AdvSearch/Fields.elm10
-rw-r--r--elm/AdvSearch/Resolution.elm49
-rw-r--r--elm/Lib/Api.elm1
-rw-r--r--elm/Lib/Autocomplete.elm41
-rw-r--r--lib/VNWeb/Elm.pm4
-rw-r--r--lib/VNWeb/Releases/Elm.pm8
6 files changed, 83 insertions, 30 deletions
diff --git a/elm/AdvSearch/Fields.elm b/elm/AdvSearch/Fields.elm
index b73e6cd9..2fea6be7 100644
--- a/elm/AdvSearch/Fields.elm
+++ b/elm/AdvSearch/Fields.elm
@@ -350,10 +350,10 @@ fieldUpdate dat msg_ (num, dd, model) =
-- Called when opening a dropdown, can be used to focus an input element
focus =
case model of
- FMTag m -> Cmd.map FSTag (A.refocus m.conf)
- FMTrait m -> Cmd.map FSTrait (A.refocus m.conf)
- FMDeveloper m -> Cmd.map FSDeveloper (A.refocus m.conf)
- FMResolution m -> Cmd.none -- TODO: Focus input field
+ FMTag m -> Cmd.map FSTag (A.refocus m.conf)
+ FMTrait m -> Cmd.map FSTrait (A.refocus m.conf)
+ FMDeveloper m -> Cmd.map FSDeveloper (A.refocus m.conf)
+ FMResolution m -> Cmd.map FSResolution (A.refocus m.conf)
_ -> Cmd.none
in case (msg_, model) of
-- Move to parent node is tricky, needs to be intercepted at this point so that we can access the parent NestModel.
@@ -395,7 +395,7 @@ fieldUpdate dat msg_ (num, dd, model) =
(FSVotecount msg,FMVotecount m)-> maps FMVotecount (AR.update msg m)
(FSDeveloper msg,FMDeveloper m)-> mapf FMDeveloper FSDeveloper (AP.update dat msg m)
(FSRDate msg, FMRDate m) -> maps FMRDate (AD.update msg m)
- (FSResolution msg,FMResolution m)->maps FMResolution (AE.update msg m)
+ (FSResolution msg,FMResolution m)->mapf FMResolution FSResolution (AE.update dat msg m)
(FSTag msg, FMTag m) -> mapf FMTag FSTag (AG.update dat msg m)
(FSTrait msg, FMTrait m) -> mapf FMTrait FSTrait (AI.update dat msg m)
(FToggle b, _) -> (dat, (num, DD.toggle dd b, model), if b then focus else Cmd.none)
diff --git a/elm/AdvSearch/Resolution.elm b/elm/AdvSearch/Resolution.elm
index bf059d17..323d8081 100644
--- a/elm/AdvSearch/Resolution.elm
+++ b/elm/AdvSearch/Resolution.elm
@@ -2,22 +2,25 @@ module AdvSearch.Resolution exposing (..)
import Html exposing (..)
import Html.Attributes exposing (..)
+import Lib.Autocomplete as A
import Lib.Html exposing (..)
import Lib.Util exposing (..)
+import Gen.Api as GApi
import AdvSearch.Lib exposing (..)
type alias Model =
{ op : Op
, reso : Maybe (Int,Int)
- , value : String
+ , conf : A.Config Msg GApi.ApiResolutions
+ , search : A.Model GApi.ApiResolutions
, aspect : Bool
}
type Msg
= MOp Op
- | Reso String
+ | Search (A.Msg GApi.ApiResolutions)
| Aspect Bool
@@ -25,21 +28,29 @@ onlyEq : Maybe (Int,Int) -> Bool
onlyEq reso = reso == Just (0,0) || reso == Just (0,1)
-update : Msg -> Model -> Model
-update msg model =
+update : Data -> Msg -> Model -> (Data, Model, Cmd Msg)
+update dat msg model =
case msg of
- MOp o -> { model | op = o }
- Reso s -> { model | op = if onlyEq (resoParse False s) && model.op /= Eq && model.op /= Ne then Eq else model.op, value = s, reso = resoParse False s }
- Aspect b -> { model | aspect = b }
+ MOp o -> (dat, { model | op = o, aspect = o /= Eq && o /= Ne && model.aspect }, Cmd.none)
+ Aspect b -> (dat, { model | aspect = b }, Cmd.none)
+ Search m ->
+ let (nm, c, en) = A.update model.conf m model.search
+ search = Maybe.withDefault nm <| Maybe.map (\e -> A.clear nm e.resolution) en
+ reso = resoParse True search.value
+ op = if onlyEq reso && model.op /= Eq && model.op /= Ne then Eq else model.op
+ in (dat, { model | search = search, reso = reso, op = op, aspect = op /= Eq && op /= Ne && model.aspect }, c)
init : Data -> (Data, Model)
-init dat = (dat,
- { op = Ge
- , reso = Nothing
- , value = ""
- , aspect = False
- })
+init dat =
+ ( { dat | objid = dat.objid+1 }
+ , { op = Ge
+ , reso = Nothing
+ , conf = { wrap = Search, id = "advsearch_reso" ++ String.fromInt dat.objid, source = A.resolutionSource }
+ , search = A.init ""
+ , aspect = False
+ }
+ )
toQuery : Model -> Maybe Query
@@ -47,9 +58,11 @@ toQuery model = Maybe.map (\(x,y) -> QTuple (if model.aspect then 9 else 8) mode
fromQuery : Data -> Query -> Maybe (Data, Model)
fromQuery dat q =
+ let m op x y aspect = Just <| Tuple.mapSecond (\mod -> { mod | op = op, reso = Just (x,y), search = A.init (resoFmt False x y), aspect = aspect }) <| init dat
+ in
case q of
- QTuple 8 op x y -> Just (dat, { op = op, reso = Just (x,y), value = resoFmt False x y, aspect = False })
- QTuple 9 op x y -> Just (dat, { op = op, reso = Just (x,y), value = resoFmt False x y, aspect = True })
+ QTuple 8 op x y -> m op x y False
+ QTuple 9 op x y -> m op x y True
_ -> Nothing
@@ -59,14 +72,14 @@ view model =
Nothing -> b [ class "grayedout" ] [ text "Resolution" ]
Just (x,y) -> span [ class "nowrap" ] [ text <| (if x > 0 && model.aspect then "A " else "R ") ++ showOp model.op ++ " " ++ resoFmt False x y ]
, \() ->
- [ div [ class "advheader", style "width" "250px" ]
+ [ div [ class "advheader" ]
[ h3 [] [ text "Resolution" ]
, div [ class "opts" ]
[ div [ class "opselect" ] [ inputOp (onlyEq model.reso) model.op MOp ]
, if model.op == Eq || model.op == Ne then text "" else
- linkRadio model.aspect Aspect [ span [ title "Match the aspect ratio of the given resolution" ] [ text "aspect" ] ]
+ linkRadio model.aspect Aspect [ span [ title "Aspect ratio must be the same" ] [ text "aspect" ] ]
]
]
- , inputText "" model.value Reso [style "width" "200px"] -- TODO: autocomplete
+ , A.view model.conf model.search [ placeholder "width x height" ]
]
)
diff --git a/elm/Lib/Api.elm b/elm/Lib/Api.elm
index b1e22193..a598b9d3 100644
--- a/elm/Lib/Api.elm
+++ b/elm/Lib/Api.elm
@@ -47,6 +47,7 @@ showResponse res =
ImgFormat -> "Unrecognized image format, only JPEG and PNG are accepted."
DupNames _ -> "Name or alias already in the database."
Releases _ -> unexp
+ Resolutions _ -> unexp
BoardResult _ -> unexp
TagResult _ -> unexp
TraitResult _ -> unexp
diff --git a/elm/Lib/Autocomplete.elm b/elm/Lib/Autocomplete.elm
index 3e47e06d..aea614db 100644
--- a/elm/Lib/Autocomplete.elm
+++ b/elm/Lib/Autocomplete.elm
@@ -12,6 +12,7 @@ module Lib.Autocomplete exposing
, staffSource
, charSource
, animeSource
+ , resolutionSource
, init
, clear
, refocus
@@ -41,6 +42,7 @@ import Gen.Producers as GP
import Gen.Staff as GS
import Gen.Chars as GC
import Gen.Anime as GA
+import Gen.Resolutions as GR
type alias Config m a =
@@ -56,6 +58,8 @@ type alias Config m a =
type SearchSource m a
-- API endpoint to query for completion results + Function to decode results from the API
= Endpoint (String -> (GApi.Response -> m) -> Cmd m) (GApi.Response -> Maybe (List a))
+ -- API endpoint that returns the full list of possible results + Function to decode results from the API + Function to match results against a query
+ | LazyList ((GApi.Response -> m) -> Cmd m) (GApi.Response -> Maybe (List a)) (String -> List a -> List a)
-- Pure function for instant completion results
| Func (String -> List a)
@@ -195,10 +199,24 @@ animeSource =
}
+resolutionSource : SourceConfig m GApi.ApiResolutions
+resolutionSource =
+ { source = LazyList
+ (GR.send {})
+ (\x -> case x of
+ GApi.Resolutions e -> Just e
+ _ -> Nothing)
+ (\s l -> List.filter (\v -> String.contains (String.toLower s) (String.toLower v.resolution)) l |> List.take 10)
+ , view = \i -> [ text i.resolution, b [ class "grayedout" ] [ text <| " (" ++ String.fromInt i.count ++ ")" ] ]
+ , key = \i -> i.resolution
+ }
+
+
type alias Model a =
{ visible : Bool
, value : String
, results : List a
+ , all : Maybe (List a) -- Used by LazyList
, sel : String
, default : String
, loading : Bool
@@ -211,6 +229,7 @@ init s =
{ visible = False
, value = s
, results = []
+ , all = Nothing
, sel = ""
, default = s
, loading = False
@@ -281,26 +300,34 @@ update cfg msg model =
Key _ -> mod model
Input s ->
+ let m = { model | value = s, default = "" }
+ in
if String.trim s == ""
- then mod { model | value = s, default = "", loading = False, results = [] }
- else case cfg.source.source of
+ then mod { m | loading = False, results = [] }
+ else case (cfg.source.source) of
Endpoint _ _ ->
- ( { model | value = s, default = "", loading = True, wait = model.wait + 1 }
+ ( { m | loading = True, wait = model.wait + 1 }
, Task.perform (always <| cfg.wrap <| Search <| model.wait + 1) (Process.sleep 500)
, Nothing )
- Func f -> mod { model | value = s, default = "", results = f s }
+ LazyList e _ f ->
+ case (model.loading, model.all) of
+ (_, Just l) -> mod { m | results = f s l }
+ (True, _) -> mod m
+ (False, _) -> ({ m | loading = True }, e (cfg.wrap << Results ""), Nothing)
+ Func f -> mod { m | results = f s }
Search i ->
if model.value == "" || model.wait /= i
then mod model
else case cfg.source.source of
Endpoint e _ -> (model, e model.value (cfg.wrap << Results model.value), Nothing)
+ LazyList _ _ _ -> mod model
Func _ -> mod model
Results s r -> mod <|
- if s /= model.value then model -- Discard stale results
- else case cfg.source.source of
- Endpoint _ d -> { model | loading = False, results = d r |> Maybe.withDefault [] }
+ case cfg.source.source of
+ Endpoint _ d -> if s /= model.value then model else { model | loading = False, results = d r |> Maybe.withDefault [] }
+ LazyList _ d f -> let all = d r in { model | loading = False, all = all, results = Maybe.map (\l -> f model.value l) all |> Maybe.withDefault [] }
Func _ -> model
diff --git a/lib/VNWeb/Elm.pm b/lib/VNWeb/Elm.pm
index 4e9d435b..1dd2e93f 100644
--- a/lib/VNWeb/Elm.pm
+++ b/lib/VNWeb/Elm.pm
@@ -66,6 +66,10 @@ our %apis = (
lang => { type => 'array', values => {} },
platforms=> { type => 'array', values => {} },
} } ],
+ Resolutions => [ { aoh => { # Response to 'Resolutions'
+ resolution => {},
+ count => { uint => 1 },
+ } } ],
BoardResult => [ { aoh => { # Response to 'Boards'
btype => {},
iid => { required => 0, default => 0, id => 1 },
diff --git a/lib/VNWeb/Releases/Elm.pm b/lib/VNWeb/Releases/Elm.pm
index f4ab8975..7f0578e4 100644
--- a/lib/VNWeb/Releases/Elm.pm
+++ b/lib/VNWeb/Releases/Elm.pm
@@ -10,4 +10,12 @@ elm_api Release => undef, { vid => { id => 1 } }, sub {
elm_Releases releases_by_vn $data->{vid};
};
+
+elm_api Resolutions => undef, {}, sub {
+ elm_Resolutions [ map +{ resolution => resolution($_), count => $_->{count} }, tuwf->dbAlli(q{
+ SELECT reso_x, reso_y, count(*) AS count FROM releases WHERE NOT hidden AND NOT (reso_x = 0 AND reso_y = 0)
+ GROUP BY reso_x, reso_y ORDER BY count(*) DESC
+ })->@* ];
+};
+
1;