main
Thomas Forgione 8 months ago
parent a3fb7dd5e4
commit 312f6e3c72
  1. 1
      .gitignore
  2. 394
      Cargo.lock
  3. 9
      Cargo.toml
  4. 18
      Makefile
  5. 5
      elm.json
  6. 0
      elm/Emoji.elm
  7. 238
      elm/Main.elm
  8. 3
      index.html
  9. 13387
      js/main.js
  10. 1
      js/main.min.js
  11. 17289
      js/main.tmp.js
  12. 127
      src/Main.elm
  13. 39
      src/main.rs

1
.gitignore vendored

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

394
Cargo.lock generated

@ -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"

@ -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"

@ -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}

@ -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"

@ -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"
)
)
)

@ -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>

File diff suppressed because it is too large Load Diff

1
js/main.min.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

@ -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

@ -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();
}
Loading…
Cancel
Save