Browse Source

First draft of working app

Concerned about performance due to repeatedly cloning a Vec with over
200k elements
master
Dylan Baker 1 year ago
parent
commit
f3d9ef89d4
9 changed files with 236280 additions and 56 deletions
  1. 1
    0
      Cargo.toml
  2. 86
    43
      src/lib.rs
  3. 251
    0
      src/tlds.rs
  4. 2
    2
      start-debug-mode.sh
  5. 2
    2
      start-profiling.sh
  6. 2
    2
      start-release-mode.sh
  7. 3
    7
      www/index.html
  8. 47
    0
      www/style.css
  9. 235886
    0
      www/words.txt

+ 1
- 0
Cargo.toml View File

@@ -13,6 +13,7 @@ console_error_panic_hook = "0.1"
13 13
 console_log = { version = "0.2", features = ["color"] }
14 14
 log = "0.4"
15 15
 sauron = "0.31.2"
16
+rand = { version = "0.7", features = ["wasm-bindgen"] }
16 17
 
17 18
 [features]
18 19
 with-measure = ["sauron/with-measure"]

+ 86
- 43
src/lib.rs View File

@@ -1,71 +1,114 @@
1
-#![deny(warnings)]
2
-use log::trace;
3
-use sauron::html::attributes::{attr, class, id, key, type_, value};
1
+use rand::seq::SliceRandom;
2
+use sauron::html::attributes::{class, id};
4 3
 use sauron::html::events::on_click;
5
-use sauron::html::{div, h1, input, text};
4
+use sauron::html::{div, text};
6 5
 use sauron::prelude::*;
7 6
 use sauron::{Cmd, Component, Node, Program};
8 7
 
8
+mod tlds;
9
+
9 10
 pub enum Msg {
10 11
     Click,
12
+    ReceivedWords(Result<Vec<String>, JsValue>),
11 13
 }
12 14
 
13 15
 pub struct App {
14
-    click_count: u32,
16
+    output: Option<String>,
17
+    words: Vec<String>,
15 18
 }
16 19
 
17 20
 impl App {
18 21
     pub fn new() -> Self {
19
-        App { click_count: 0 }
22
+        App {
23
+            output: None,
24
+            words: vec![],
25
+        }
26
+    }
27
+
28
+    fn generate_domain(&mut self) -> String {
29
+        let mut domain: String = String::from("");
30
+
31
+        while domain.is_empty() {
32
+            let tld = self.get_random_tld();
33
+            tld.map(|tld| {
34
+                let word = self.get_random_word(&tld);
35
+                if word.is_some() {
36
+                    let mut word = word.unwrap();
37
+                    word.truncate(word.len() - 2);
38
+                    domain = format!("{}.{}", word, tld);
39
+                }
40
+            });
41
+        }
42
+
43
+        domain
44
+    }
45
+
46
+    fn get_random_tld(&mut self) -> Option<String> {
47
+        crate::tlds::tlds()
48
+            .choose(&mut rand::thread_rng())
49
+            .map(|v| String::from(v))
50
+    }
51
+
52
+    fn get_random_word(&self, tld: &str) -> Option<String> {
53
+        self.words
54
+            .clone()
55
+            .into_iter()
56
+            .filter(|word| word.ends_with(tld))
57
+            .collect::<Vec<String>>()
58
+            .choose(&mut rand::thread_rng())
59
+            .map(|v| v.to_string().to_lowercase())
20 60
     }
21 61
 }
22 62
 
23 63
 impl Component<Msg> for App {
64
+    fn init(&self) -> Cmd<Self, Msg> {
65
+        Http::fetch_with_text_response_decoder(
66
+            "/words.txt",
67
+            |r: String| r.lines().map(|l| l.to_string()).collect(),
68
+            Msg::ReceivedWords,
69
+        )
70
+    }
71
+
24 72
     fn view(&self) -> Node<Msg> {
73
+        let output = match &self.output {
74
+            Some(s) => vec![text(s)],
75
+            None => vec![],
76
+        };
77
+
78
+        let loading = self.words.len() == 0;
79
+
25 80
         sauron::html::main(
26 81
             vec![],
27
-            vec![
28
-                h1(vec![], vec![text("Minimal example")]),
29
-                div(
30
-                    vec![
31
-                        class("some-class"),
32
-                        id("some-id"),
33
-                        attr("data-id", 1),
34
-                    ],
35
-                    vec![
36
-                        input(
37
-                            vec![
38
-                                class("client"),
39
-                                type_("button"),
40
-                                value("Click me!"),
41
-                                key(1),
42
-                                on_click(|_| {
43
-                                    trace!("Button is clicked");
44
-                                    Msg::Click
45
-                                }),
46
-                            ],
47
-                            vec![],
48
-                        ),
49
-                        div(
50
-                            vec![],
51
-                            vec![text(format!(
52
-                                "Clicked: {}",
53
-                                self.click_count
54
-                            ))],
55
-                        ),
56
-                        input(
57
-                            vec![type_("text"), value(self.click_count)],
58
-                            vec![],
59
-                        ),
60
-                    ],
61
-                ),
62
-            ],
82
+            vec![div(
83
+                vec![class("container")],
84
+                vec![
85
+                    h1(vec![class("heading")], vec![text("Domain Hack Generator")]),
86
+                    div(
87
+                        vec![class("button-container")],
88
+                        vec![
89
+                            button(
90
+                                vec![
91
+                                    class("button"),
92
+                                    disabled(loading),
93
+                                    on_click(|_: MouseEvent| Msg::Click),
94
+                                ],
95
+                                vec![text(if loading { "Loading..." } else { "Generate" })],
96
+                            ),
97
+                            p(vec![id("result")], output),
98
+                        ],
99
+                    ),
100
+                ],
101
+            )],
63 102
         )
64 103
     }
65 104
 
66 105
     fn update(&mut self, msg: Msg) -> Cmd<Self, Msg> {
67 106
         match msg {
68
-            Msg::Click => self.click_count += 1,
107
+            Msg::Click => self.output = Some(self.generate_domain()),
108
+            Msg::ReceivedWords(result) => match result {
109
+                Ok(words) => self.words = words,
110
+                Err(_) => {}
111
+            },
69 112
         }
70 113
         Cmd::none()
71 114
     }

+ 251
- 0
src/tlds.rs View File

@@ -0,0 +1,251 @@
1
+pub fn tlds() -> Vec<String> {
2
+  vec![
3
+      String::from("ac"),
4
+      String::from("ad"),
5
+      String::from("ae"),
6
+      String::from("af"),
7
+      String::from("ag"),
8
+      String::from("ai"),
9
+      String::from("al"),
10
+      String::from("am"),
11
+      String::from("ao"),
12
+      String::from("aq"),
13
+      String::from("ar"),
14
+      String::from("as"),
15
+      String::from("at"),
16
+      String::from("au"),
17
+      String::from("aw"),
18
+      String::from("ax"),
19
+      String::from("az"),
20
+      String::from("ba"),
21
+      String::from("bb"),
22
+      String::from("bd"),
23
+      String::from("be"),
24
+      String::from("bf"),
25
+      String::from("bg"),
26
+      String::from("bh"),
27
+      String::from("bi"),
28
+      String::from("bj"),
29
+      String::from("bm"),
30
+      String::from("bn"),
31
+      String::from("bo"),
32
+      String::from("bq"),
33
+      String::from("br"),
34
+      String::from("bs"),
35
+      String::from("bt"),
36
+      String::from("bw"),
37
+      String::from("by"),
38
+      String::from("bz"),
39
+      String::from("ca"),
40
+      String::from("cc"),
41
+      String::from("cd"),
42
+      String::from("cf"),
43
+      String::from("cg"),
44
+      String::from("ch"),
45
+      String::from("ci"),
46
+      String::from("ck"),
47
+      String::from("cl"),
48
+      String::from("cm"),
49
+      String::from("cn"),
50
+      String::from("co"),
51
+      String::from("cr"),
52
+      String::from("cu"),
53
+      String::from("cv"),
54
+      String::from("cw"),
55
+      String::from("cx"),
56
+      String::from("cy"),
57
+      String::from("cz"),
58
+      String::from("de"),
59
+      String::from("dj"),
60
+      String::from("dk"),
61
+      String::from("dm"),
62
+      String::from("do"),
63
+      String::from("dz"),
64
+      String::from("ec"),
65
+      String::from("ee"),
66
+      String::from("eg"),
67
+      String::from("eh"),
68
+      String::from("er"),
69
+      String::from("es"),
70
+      String::from("et"),
71
+      String::from("eu"),
72
+      String::from("fi"),
73
+      String::from("fj"),
74
+      String::from("fk"),
75
+      String::from("fm"),
76
+      String::from("fo"),
77
+      String::from("fr"),
78
+      String::from("ga"),
79
+      String::from("gd"),
80
+      String::from("ge"),
81
+      String::from("gf"),
82
+      String::from("gg"),
83
+      String::from("gh"),
84
+      String::from("gi"),
85
+      String::from("gl"),
86
+      String::from("gm"),
87
+      String::from("gn"),
88
+      String::from("gp"),
89
+      String::from("gq"),
90
+      String::from("gr"),
91
+      String::from("gs"),
92
+      String::from("gt"),
93
+      String::from("gu"),
94
+      String::from("gw"),
95
+      String::from("gy"),
96
+      String::from("hk"),
97
+      String::from("hm"),
98
+      String::from("hn"),
99
+      String::from("hr"),
100
+      String::from("ht"),
101
+      String::from("hu"),
102
+      String::from("id"),
103
+      String::from("ie"),
104
+      String::from("il"),
105
+      String::from("im"),
106
+      String::from("in"),
107
+      String::from("io"),
108
+      String::from("iq"),
109
+      String::from("ir"),
110
+      String::from("is"),
111
+      String::from("it"),
112
+      String::from("je"),
113
+      String::from("jm"),
114
+      String::from("jo"),
115
+      String::from("jp"),
116
+      String::from("ke"),
117
+      String::from("kg"),
118
+      String::from("kh"),
119
+      String::from("ki"),
120
+      String::from("km"),
121
+      String::from("kn"),
122
+      String::from("kp"),
123
+      String::from("kr"),
124
+      String::from("kw"),
125
+      String::from("ky"),
126
+      String::from("kz"),
127
+      String::from("la"),
128
+      String::from("lb"),
129
+      String::from("lc"),
130
+      String::from("li"),
131
+      String::from("lk"),
132
+      String::from("lr"),
133
+      String::from("ls"),
134
+      String::from("lt"),
135
+      String::from("lu"),
136
+      String::from("lv"),
137
+      String::from("ly"),
138
+      String::from("ma"),
139
+      String::from("mc"),
140
+      String::from("md"),
141
+      String::from("me"),
142
+      String::from("mg"),
143
+      String::from("mh"),
144
+      String::from("mk"),
145
+      String::from("ml"),
146
+      String::from("mm"),
147
+      String::from("mn"),
148
+      String::from("mo"),
149
+      String::from("mp"),
150
+      String::from("mq"),
151
+      String::from("mr"),
152
+      String::from("ms"),
153
+      String::from("mt"),
154
+      String::from("mu"),
155
+      String::from("mv"),
156
+      String::from("mw"),
157
+      String::from("mx"),
158
+      String::from("my"),
159
+      String::from("mz"),
160
+      String::from("na"),
161
+      String::from("nc"),
162
+      String::from("ne"),
163
+      String::from("nf"),
164
+      String::from("ng"),
165
+      String::from("ni"),
166
+      String::from("nl"),
167
+      String::from("no"),
168
+      String::from("np"),
169
+      String::from("nr"),
170
+      String::from("nu"),
171
+      String::from("nz"),
172
+      String::from("om"),
173
+      String::from("pa"),
174
+      String::from("pe"),
175
+      String::from("pf"),
176
+      String::from("pg"),
177
+      String::from("ph"),
178
+      String::from("pk"),
179
+      String::from("pl"),
180
+      String::from("pm"),
181
+      String::from("pn"),
182
+      String::from("pr"),
183
+      String::from("ps"),
184
+      String::from("pt"),
185
+      String::from("pw"),
186
+      String::from("py"),
187
+      String::from("qa"),
188
+      String::from("re"),
189
+      String::from("ro"),
190
+      String::from("rs"),
191
+      String::from("ru"),
192
+      String::from("rw"),
193
+      String::from("sa"),
194
+      String::from("sb"),
195
+      String::from("sc"),
196
+      String::from("sd"),
197
+      String::from("se"),
198
+      String::from("sg"),
199
+      String::from("sh"),
200
+      String::from("si"),
201
+      String::from("sk"),
202
+      String::from("sl"),
203
+      String::from("sm"),
204
+      String::from("sn"),
205
+      String::from("so"),
206
+      String::from("sr"),
207
+      String::from("ss"),
208
+      String::from("st"),
209
+      String::from("su"),
210
+      String::from("sv"),
211
+      String::from("sx"),
212
+      String::from("sy"),
213
+      String::from("sz"),
214
+      String::from("tc"),
215
+      String::from("td"),
216
+      String::from("tf"),
217
+      String::from("tg"),
218
+      String::from("th"),
219
+      String::from("tj"),
220
+      String::from("tk"),
221
+      String::from("tl"),
222
+      String::from("tm"),
223
+      String::from("tn"),
224
+      String::from("to"),
225
+      String::from("tr"),
226
+      String::from("tt"),
227
+      String::from("tv"),
228
+      String::from("tw"),
229
+      String::from("tz"),
230
+      String::from("ua"),
231
+      String::from("ug"),
232
+      String::from("uk"),
233
+      String::from("us"),
234
+      String::from("uy"),
235
+      String::from("uz"),
236
+      String::from("va"),
237
+      String::from("vc"),
238
+      String::from("ve"),
239
+      String::from("vg"),
240
+      String::from("vi"),
241
+      String::from("vn"),
242
+      String::from("vu"),
243
+      String::from("wf"),
244
+      String::from("ws"),
245
+      String::from("ye"),
246
+      String::from("yt"),
247
+      String::from("za"),
248
+      String::from("zm"),
249
+      String::from("zw"),
250
+    ]
251
+}

+ 2
- 2
start-debug-mode.sh View File

@@ -5,6 +5,6 @@ set -v
5 5
 . ./bootstrap.sh
6 6
 
7 7
 
8
-wasm-pack build --target web --dev -- --features "with-measure"
8
+wasm-pack build --target web --dev --out-dir www/pkg -- --features "with-measure"
9 9
 
10
-basic-http-server ./ -a 0.0.0.0:4001
10
+basic-http-server ./www -a 0.0.0.0:4001

+ 2
- 2
start-profiling.sh View File

@@ -4,6 +4,6 @@ set -v
4 4
 
5 5
 . ./bootstrap.sh
6 6
 
7
-wasm-pack build --target web --profiling
7
+wasm-pack build --target web --profiling --out-dir www/pkg
8 8
 
9
-basic-http-server ./ -a 0.0.0.0:4001
9
+basic-http-server ./www -a 0.0.0.0:4001

+ 2
- 2
start-release-mode.sh View File

@@ -4,6 +4,6 @@ set -v
4 4
 
5 5
 . ./bootstrap.sh
6 6
 
7
-wasm-pack build --target web --release
7
+wasm-pack build --target web --release --out-dir www/pkg
8 8
 
9
-basic-http-server ./ -a 0.0.0.0:4001
9
+basic-http-server ./www -a 0.0.0.0:4001

index.html → www/index.html View File

@@ -1,12 +1,8 @@
1 1
 <html>
2 2
   <head>
3
-    <meta content="text/html;charset=utf-8" http-equiv="Content-Type"/>
4
-    <title>Minimal sauron app</title>
5
-    <style type="text/css">
6
-        body {
7
-            font-family: "Fira Sans", "Courier New", Courier,"Lucida Sans Typewriter","Lucida Typewriter",monospace;
8
-        }
9
-    </style>
3
+    <meta content="text/html;charset=utf-8" http-equiv="Content-Type" />
4
+    <title>Domain Hack Generator</title>
5
+    <link rel="stylesheet" href="/style.css" />
10 6
   </head>
11 7
   <body>
12 8
     <script type="module">

+ 47
- 0
www/style.css View File

@@ -0,0 +1,47 @@
1
+* {
2
+  box-sizing: border-box;
3
+  margin: 0;
4
+  padding: 0;
5
+}
6
+
7
+body {
8
+  background: #333333;
9
+  color: #efefef;
10
+  font-family: Helvetica Neue;
11
+  line-height: 1.5;
12
+}
13
+
14
+.container {
15
+  margin: auto;
16
+  max-width: 768px;
17
+}
18
+
19
+.heading {
20
+  padding: 2em;
21
+  text-align: center;
22
+}
23
+
24
+.button-container {
25
+  text-align: center;
26
+}
27
+
28
+.button {
29
+  background: #486f48;
30
+  border: 2px solid #5d8c56;
31
+  border-radius: 5px;
32
+  color: #efefef;
33
+  cursor: pointer;
34
+  font-size: 24px;
35
+  padding: 10px 20px;
36
+}
37
+
38
+.button[disabled] {
39
+  background: transparent;
40
+  border: none;
41
+  opacity: 0.5;
42
+}
43
+
44
+#result {
45
+  font-size: 56px;
46
+  padding: 2.5em;
47
+}

+ 235886
- 0
www/words.txt
File diff suppressed because it is too large
View File


Loading…
Cancel
Save