This commit is contained in:
Thomas Forgione 2022-02-05 21:05:41 +01:00
parent a3fb7dd5e4
commit 312f6e3c72
13 changed files with 24947 additions and 5780 deletions

1
.gitignore vendored
View File

@ -1 +1,2 @@
elm-stuff
target

394
Cargo.lock generated Normal file
View File

@ -0,0 +1,394 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "atk-sys"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f530e4af131d94cc4fa15c5c9d0348f0ef28bac64ba660b6b2a1cf2605dedfce"
dependencies = [
"glib-sys",
"gobject-sys",
"libc",
"system-deps",
]
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "boxfnonce"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5988cb1d626264ac94100be357308f29ff7cbdd3b36bda27f450a4ee3f713426"
[[package]]
name = "cairo-sys-rs"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2ed2639b9ad5f1d6efa76de95558e11339e7318426d84ac4890b86c03e828ca7"
dependencies = [
"libc",
"system-deps",
]
[[package]]
name = "cc"
version = "1.0.72"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee"
[[package]]
name = "elmojinput"
version = "0.1.0"
dependencies = [
"web-view",
]
[[package]]
name = "gdk-pixbuf-sys"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3bfe468a7f43e97b8d193a762b6c5cf67a7d36cacbc0b9291dbcae24bfea1e8f"
dependencies = [
"gio-sys",
"glib-sys",
"gobject-sys",
"libc",
"system-deps",
]
[[package]]
name = "gdk-sys"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a9653cfc500fd268015b1ac055ddbc3df7a5c9ea3f4ccef147b3957bd140d69"
dependencies = [
"cairo-sys-rs",
"gdk-pixbuf-sys",
"gio-sys",
"glib-sys",
"gobject-sys",
"libc",
"pango-sys",
"pkg-config",
"system-deps",
]
[[package]]
name = "gio-sys"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e24fb752f8f5d2cf6bbc2c606fd2bc989c81c5e2fe321ab974d54f8b6344eac"
dependencies = [
"glib-sys",
"gobject-sys",
"libc",
"system-deps",
"winapi",
]
[[package]]
name = "glib-sys"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7e9b997a66e9a23d073f2b1abb4dbfc3925e0b8952f67efd8d9b6e168e4cdc1"
dependencies = [
"libc",
"system-deps",
]
[[package]]
name = "gobject-sys"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "952133b60c318a62bf82ee75b93acc7e84028a093e06b9e27981c2b6fe68218c"
dependencies = [
"glib-sys",
"libc",
"system-deps",
]
[[package]]
name = "gtk-sys"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89acda6f084863307d948ba64a4b1ef674e8527dddab147ee4cdcc194c880457"
dependencies = [
"atk-sys",
"cairo-sys-rs",
"gdk-pixbuf-sys",
"gdk-sys",
"gio-sys",
"glib-sys",
"gobject-sys",
"libc",
"pango-sys",
"system-deps",
]
[[package]]
name = "heck"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c"
dependencies = [
"unicode-segmentation",
]
[[package]]
name = "javascriptcore-rs-sys"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f46ada8a08dcd75a10afae872fbfb51275df4a8ae0d46b8cc7c708f08dd2998"
dependencies = [
"libc",
]
[[package]]
name = "libc"
version = "0.2.117"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e74d72e0f9b65b5b4ca49a346af3976df0f9c61d550727f349ecd559f251a26c"
[[package]]
name = "pango-sys"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d2650c8b62d116c020abd0cea26a4ed96526afda89b1c4ea567131fdefc890"
dependencies = [
"glib-sys",
"gobject-sys",
"libc",
"system-deps",
]
[[package]]
name = "pkg-config"
version = "0.3.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe"
[[package]]
name = "proc-macro2"
version = "1.0.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029"
dependencies = [
"unicode-xid",
]
[[package]]
name = "quote"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145"
dependencies = [
"proc-macro2",
]
[[package]]
name = "serde"
version = "1.0.136"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789"
[[package]]
name = "soup-sys"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3c7adf08565630bbb71f955f11f8a68464817ded2703a3549747c235b58a13e"
dependencies = [
"bitflags",
"gio-sys",
"glib-sys",
"gobject-sys",
"libc",
"pkg-config",
"system-deps",
]
[[package]]
name = "strum"
version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57bd81eb48f4c437cadc685403cad539345bf703d78e63707418431cecd4522b"
[[package]]
name = "strum_macros"
version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87c85aa3f8ea653bfd3ddf25f7ee357ee4d204731f6aa9ad04002306f6e2774c"
dependencies = [
"heck",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "syn"
version = "1.0.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b"
dependencies = [
"proc-macro2",
"quote",
"unicode-xid",
]
[[package]]
name = "system-deps"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f3ecc17269a19353b3558b313bba738b25d82993e30d62a18406a24aba4649b"
dependencies = [
"heck",
"pkg-config",
"strum",
"strum_macros",
"thiserror",
"toml",
"version-compare",
]
[[package]]
name = "thiserror"
version = "1.0.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "tinyfiledialogs"
version = "3.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adc577626a3c26e4e1d470dbe5fe33d6fabc14e57114cb377acdb4da1a17dde9"
dependencies = [
"cc",
"libc",
]
[[package]]
name = "toml"
version = "0.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa"
dependencies = [
"serde",
]
[[package]]
name = "unicode-segmentation"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b"
[[package]]
name = "unicode-xid"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
[[package]]
name = "urlencoding"
version = "1.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a1f0175e03a0973cf4afd476bef05c26e228520400eb1fd473ad417b1c00ffb"
[[package]]
name = "version-compare"
version = "0.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d63556a25bae6ea31b52e640d7c41d1ab27faba4ccb600013837a3d0b3994ca1"
[[package]]
name = "web-view"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee1da6aa5f232e7a4f17ae4549772d2e35d0f4ade03e7527b25c4c0b00abafea"
dependencies = [
"boxfnonce",
"tinyfiledialogs",
"urlencoding",
"webview-sys",
]
[[package]]
name = "webkit2gtk-sys"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "389e5138c85a0d111b9bda05b59efa8562315e1d657d72451410e12c858f0619"
dependencies = [
"atk-sys",
"bitflags",
"cairo-sys-rs",
"gdk-pixbuf-sys",
"gdk-sys",
"gio-sys",
"glib-sys",
"gobject-sys",
"gtk-sys",
"javascriptcore-rs-sys",
"libc",
"pango-sys",
"pkg-config",
"soup-sys",
]
[[package]]
name = "webview-sys"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0001f025c1425ffe36270a81cb091eade87dd8d29ac773735ae47e1a8c8066c9"
dependencies = [
"cc",
"gdk-sys",
"gio-sys",
"glib-sys",
"gobject-sys",
"gtk-sys",
"javascriptcore-rs-sys",
"libc",
"pkg-config",
"webkit2gtk-sys",
]
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

9
Cargo.toml Normal file
View File

@ -0,0 +1,9 @@
[package]
name = "elmojinput"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
web-view = "0.7.3"

View File

@ -12,17 +12,23 @@ endif
BUILD_DIR=js
dev: js/main.js
release: js/main.min.js
dev: target/debug/elmojinput
release: target/release/elmojinput
js/main.js: src/**
$(ELM) make src/Main.elm --output $(BUILD_DIR)/main.js
js/main.js: elm/**
$(ELM) make elm/Main.elm --output $(BUILD_DIR)/main.js
js/main.min.js: js/main.tmp.js
@$(UGLIFYJS) $(BUILD_DIR)/main.tmp.js --compress 'pure_funcs="F2,F3,F4,F5,F6,F7,F8,F9,A2,A3,A4,A5,A6,A7,A8,A9",pure_getters,keep_fargs=false,unsafe_comps,unsafe' | $(UGLIFYJS) --mangle > $(BUILD_DIR)/main.min.js
js/main.tmp.js: src/**
@$(ELM) make src/Main.elm --optimize --output $(BUILD_DIR)/main.tmp.js
js/main.tmp.js: elm/**
@$(ELM) make elm/Main.elm --optimize --output $(BUILD_DIR)/main.tmp.js
target/debug/elmojinput: js/main.js src/**
cargo build
target/release/elmojinput: js/main.min.js src/**
cargo build --release
clean:
@rm -rf $(BUILD_DIR)/{main.js,main.min.js}

View File

@ -1,18 +1,19 @@
{
"type": "application",
"source-directories": [
"src"
"elm"
],
"elm-version": "0.19.1",
"dependencies": {
"direct": {
"dasch/levenshtein": "1.0.3",
"elm/browser": "1.0.2",
"elm/core": "1.0.5",
"elm/html": "1.0.0",
"elm/json": "1.1.3",
"mdgriffith/elm-ui": "1.1.8"
},
"indirect": {
"elm/json": "1.1.3",
"elm/time": "1.0.0",
"elm/url": "1.0.0",
"elm/virtual-dom": "1.0.2"

238
elm/Main.elm Normal file
View 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"
)
)
)

View File

@ -22,6 +22,9 @@
el.select();
document.execCommand('copy');
document.body.removeChild(el);
window.webkit.messageHandlers.external.postMessage(str);
// window.external.invoke("test_one");
});
</script>
</body>

12547
js/main.js

File diff suppressed because it is too large Load Diff

1
js/main.min.js vendored Normal file

File diff suppressed because one or more lines are too long

17289
js/main.tmp.js Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,127 +0,0 @@
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
main =
Browser.element
{ init = init
, update = update
, subscriptions = \_ -> Sub.none
, view = view
}
-- MODEL --
type alias Model =
{ category : Emoji.Category
}
init : () -> ( Model, Cmd Msg )
init _ =
( { category = Emoji.Recent }, Cmd.none )
type Msg
= CategoryClicked Emoji.Category
| Copy String
-- UPDATE --
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
CategoryClicked category ->
( { model | category = category }, Cmd.none )
Copy c ->
( model, copy c )
-- VIEW --
view : Model -> Html.Html Msg
view model =
Element.layout []
(Element.column [ Element.width (Element.px 512), Element.height (Element.px 512) ]
[ header, panel (Emoji.getEmojis model.category) ]
)
header : Element Msg
header =
Element.row [ Element.width Element.fill, Element.padding 5, Element.spacing 10 ]
(Emoji.categories
|> List.map
(\x ->
Input.button [ Element.padding 5, Border.color (Element.rgb255 0 0 0), Border.width 1, Border.rounded 5 ]
{ label = Element.el [] (emoji (Emoji.categoryEmoji x))
, onPress = Just (CategoryClicked x)
}
)
)
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

39
src/main.rs Normal file
View File

@ -0,0 +1,39 @@
use std::io::Write;
use std::process::{exit, Command, Stdio};
use web_view::*;
fn main() {
#[cfg(debug_assertions)]
let js = include_str!("../../elmoji/js/main.js");
#[cfg(not(debug_assertions))]
let js = include_str!("../../elmoji/js/main.min.js");
let html_content = include_str!("../../elmoji/index.html").replace(
"<script src=\"js/main.js\"></script>",
&format!("<script>{}</script>", js),
);
web_view::builder()
.title("Elmojinput")
.content(Content::Html(html_content))
.size(512, 512)
.resizable(false)
.debug(true)
.user_data(())
.invoke_handler(|_webview, arg| {
let mut child = Command::new("xclip")
.arg("-selection")
.arg("clipboard")
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.spawn()
.unwrap();
let stdin = child.stdin.as_mut().unwrap();
stdin.write_all(arg.as_bytes()).unwrap();
exit(0);
})
.run()
.unwrap();
}