Working
This commit is contained in:
1525
elm/Emoji.elm
Normal file
1525
elm/Emoji.elm
Normal file
File diff suppressed because it is too large
Load Diff
238
elm/Main.elm
Normal file
238
elm/Main.elm
Normal file
@@ -0,0 +1,238 @@
|
||||
port module Main exposing (..)
|
||||
|
||||
import Browser
|
||||
import Element exposing (Element)
|
||||
import Element.Border as Border
|
||||
import Element.Input as Input
|
||||
import Emoji
|
||||
import Html
|
||||
import Html.Attributes
|
||||
import Html.Events
|
||||
import Json.Decode as Decode
|
||||
import Levenshtein
|
||||
|
||||
|
||||
main =
|
||||
Browser.element
|
||||
{ init = init
|
||||
, update = update
|
||||
, subscriptions = \_ -> Sub.none
|
||||
, view = view
|
||||
}
|
||||
|
||||
|
||||
|
||||
-- MODEL --
|
||||
|
||||
|
||||
type Model
|
||||
= Search String
|
||||
| Category Emoji.Category
|
||||
|
||||
|
||||
modelCategory : Model -> Maybe Emoji.Category
|
||||
modelCategory model =
|
||||
case model of
|
||||
Category c ->
|
||||
Just c
|
||||
|
||||
_ ->
|
||||
Nothing
|
||||
|
||||
|
||||
modelSearch : Model -> Maybe String
|
||||
modelSearch model =
|
||||
case model of
|
||||
Search s ->
|
||||
Just s
|
||||
|
||||
_ ->
|
||||
Nothing
|
||||
|
||||
|
||||
modelEmojis : Model -> List Emoji.Emoji
|
||||
modelEmojis model =
|
||||
case model of
|
||||
Category c ->
|
||||
Emoji.getEmojis c
|
||||
|
||||
Search s ->
|
||||
Emoji.categories
|
||||
|> List.concatMap Emoji.getEmojis
|
||||
|> List.map (\x -> ( x, minimum ( Levenshtein.distance s x.name, List.map (\v -> Levenshtein.distance s v + 1) x.tags ) ))
|
||||
|> List.sortBy Tuple.second
|
||||
|> List.map Tuple.first
|
||||
|
||||
|
||||
init : () -> ( Model, Cmd Msg )
|
||||
init _ =
|
||||
( Category Emoji.Recent, Cmd.none )
|
||||
|
||||
|
||||
type Msg
|
||||
= CategoryClicked Emoji.Category
|
||||
| SearchChanged String
|
||||
| EnterPressed
|
||||
| Copy String
|
||||
|
||||
|
||||
|
||||
-- UPDATE --
|
||||
|
||||
|
||||
update : Msg -> Model -> ( Model, Cmd Msg )
|
||||
update msg model =
|
||||
case msg of
|
||||
CategoryClicked category ->
|
||||
( Category category, Cmd.none )
|
||||
|
||||
SearchChanged search ->
|
||||
( Search search, Cmd.none )
|
||||
|
||||
EnterPressed ->
|
||||
( model
|
||||
, List.head (modelEmojis model)
|
||||
|> Maybe.map .unicode
|
||||
|> Maybe.map copy
|
||||
|> Maybe.withDefault Cmd.none
|
||||
)
|
||||
|
||||
Copy c ->
|
||||
( model, copy c )
|
||||
|
||||
|
||||
|
||||
-- VIEW --
|
||||
|
||||
|
||||
view : Model -> Html.Html Msg
|
||||
view model =
|
||||
[ header model, panel (modelEmojis model) ]
|
||||
|> Element.column [ Element.width (Element.px 512), Element.height (Element.px 512) ]
|
||||
|> Element.layout []
|
||||
|
||||
|
||||
header : Model -> Element Msg
|
||||
header model =
|
||||
Element.row [ Element.width Element.fill, Element.padding 5, Element.spacing 10 ]
|
||||
[ Element.row [ Element.width Element.fill, Element.spacing 10 ]
|
||||
(Emoji.categories
|
||||
|> List.map
|
||||
(\x ->
|
||||
Input.button
|
||||
[ Element.padding 5
|
||||
, Border.color (Element.rgb255 0 0 0)
|
||||
, if modelCategory model == Just x then
|
||||
Border.width 5
|
||||
|
||||
else
|
||||
Border.width 1
|
||||
, Border.rounded 5
|
||||
]
|
||||
{ label = Element.el [] (emoji (Emoji.categoryEmoji x))
|
||||
, onPress = Just (CategoryClicked x)
|
||||
}
|
||||
)
|
||||
)
|
||||
, Input.text
|
||||
[ Element.width Element.fill
|
||||
, Input.focusedOnLoad
|
||||
, onEnter EnterPressed
|
||||
]
|
||||
{ label = Input.labelHidden "input"
|
||||
, onChange = SearchChanged
|
||||
, placeholder = Just (Input.placeholder [] (Element.text "search"))
|
||||
, text = modelSearch model |> Maybe.withDefault ""
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
panel : List Emoji.Emoji -> Element Msg
|
||||
panel em =
|
||||
em
|
||||
|> regroup 10
|
||||
|> List.map (\x -> List.map maybeEmoji x)
|
||||
|> List.map (Element.row [ Element.width Element.fill ])
|
||||
|> Element.column [ Element.width (Element.px 512), Element.height (Element.px 512), Element.scrollbarY ]
|
||||
|
||||
|
||||
emoji : Emoji.Emoji -> Element Msg
|
||||
emoji e =
|
||||
Input.button [ Element.htmlAttribute (Html.Attributes.title e.name), Element.centerX, Element.centerY ]
|
||||
{ label = Element.text e.unicode, onPress = Just (Copy e.unicode) }
|
||||
|
||||
|
||||
maybeEmoji : Maybe Emoji.Emoji -> Element Msg
|
||||
maybeEmoji e =
|
||||
Element.el [ Element.width Element.fill, Element.padding 10 ] (Maybe.map emoji e |> Maybe.withDefault Element.none)
|
||||
|
||||
|
||||
regroup : Int -> List Emoji.Emoji -> List (List (Maybe Emoji.Emoji))
|
||||
regroup num input =
|
||||
List.reverse (regroupAux [] [] num input)
|
||||
|
||||
|
||||
regroupAux : List (List (Maybe Emoji.Emoji)) -> List (Maybe Emoji.Emoji) -> Int -> List Emoji.Emoji -> List (List (Maybe Emoji.Emoji))
|
||||
regroupAux currentTotal currentPart num input =
|
||||
case input of
|
||||
[] ->
|
||||
if List.length currentPart < num then
|
||||
regroupAux currentTotal (Nothing :: currentPart) num []
|
||||
|
||||
else
|
||||
List.reverse currentPart :: currentTotal
|
||||
|
||||
h :: t ->
|
||||
if List.length currentPart >= num then
|
||||
regroupAux (List.reverse currentPart :: currentTotal) [ Just h ] num t
|
||||
|
||||
else
|
||||
regroupAux currentTotal (Just h :: currentPart) num t
|
||||
|
||||
|
||||
|
||||
-- PORTS --
|
||||
|
||||
|
||||
port copy : String -> Cmd msg
|
||||
|
||||
|
||||
|
||||
-- UTILS --
|
||||
|
||||
|
||||
minimum : ( comparable, List comparable ) -> comparable
|
||||
minimum ( h, t ) =
|
||||
case List.minimum t of
|
||||
Nothing ->
|
||||
h
|
||||
|
||||
Just v ->
|
||||
min h v
|
||||
|
||||
|
||||
maximum : ( comparable, List comparable ) -> comparable
|
||||
maximum ( h, t ) =
|
||||
case List.maximum t of
|
||||
Nothing ->
|
||||
h
|
||||
|
||||
Just v ->
|
||||
max h v
|
||||
|
||||
|
||||
onEnter : msg -> Element.Attribute msg
|
||||
onEnter msg =
|
||||
Element.htmlAttribute
|
||||
(Html.Events.on "keyup"
|
||||
(Decode.field "key" Decode.string
|
||||
|> Decode.andThen
|
||||
(\key ->
|
||||
if key == "Enter" then
|
||||
Decode.succeed msg
|
||||
|
||||
else
|
||||
Decode.fail "Not the enter key"
|
||||
)
|
||||
)
|
||||
)
|
||||
Reference in New Issue
Block a user