Skip to content

Commit 36298b2

Browse files
committed
wip
1 parent f6816b9 commit 36298b2

File tree

9 files changed

+338
-166
lines changed

9 files changed

+338
-166
lines changed

rust/cryptonote/Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

rust/cryptonote/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ web-sys = { version = "0.3", features = [
2424
"Clipboard",
2525
] }
2626
derive_more = { version = "2.1.0", features = ["display"] }
27+
urlencoding = "2.1.3"
2728

2829
[features]
2930
default = ["web"]

rust/cryptonote/src/i18n.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ pub struct Translations {
4545
pub your_note_title: &'static str,
4646
pub error_title: &'static str,
4747
pub loading: &'static str,
48+
pub create_new_note: &'static str,
49+
pub edit_note: &'static str,
4850
pub password_required: &'static str,
4951
pub no_note_in_url: &'static str,
5052
pub invalid_utf8: &'static str,
@@ -80,6 +82,8 @@ pub fn get_translations(lang: Language) -> Translations {
8082
your_note_title: "Your Note",
8183
error_title: "Error",
8284
loading: "Loading note...",
85+
create_new_note: "Create a new note",
86+
edit_note: "Edit Note",
8387
password_required: "Password is required for encryption",
8488
no_note_in_url: "No note found in URL",
8589
invalid_utf8: "Decrypted data is not valid UTF-8",
@@ -112,6 +116,8 @@ pub fn get_translations(lang: Language) -> Translations {
112116
your_note_title: "Tu Nota",
113117
error_title: "Error",
114118
loading: "Cargando nota...",
119+
create_new_note: "Crear una nueva nota",
120+
edit_note: "Editar Nota",
115121
password_required: "Se requiere contraseña para el cifrado",
116122
no_note_in_url: "No se encontró nota en la URL",
117123
invalid_utf8: "Los datos descifrados no son UTF-8 válidos",
@@ -144,6 +150,8 @@ pub fn get_translations(lang: Language) -> Translations {
144150
your_note_title: "Ваша Заметка",
145151
error_title: "Ошибка",
146152
loading: "Загрузка заметки...",
153+
create_new_note: "Создать новую заметку",
154+
edit_note: "Редактировать Заметку",
147155
password_required: "Для шифрования требуется пароль",
148156
no_note_in_url: "Заметка не найдена в URL",
149157
invalid_utf8: "Расшифрованные данные не являются допустимым UTF-8",

rust/cryptonote/src/main.rs

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
1-
// The dioxus prelude contains a ton of common items used in dioxus apps. It's a good idea to import wherever you
2-
// need dioxus
31
use dioxus::prelude::*;
4-
5-
use views::{Home, Navbar, View};
2+
use views::{Home, Navbar, Share, View};
63

74
mod components;
85
mod crypto;
@@ -19,39 +16,44 @@ enum Route {
1916
Home {},
2017
#[route("/view")]
2118
View {},
19+
#[route("/share")]
20+
Share {},
2221
}
2322

24-
// We can import assets in dioxus with the `asset!` macro. This macro takes a path to an asset relative to the crate root.
25-
// The macro returns an `Asset` type that will display as the path to the asset in the browser or a local path in desktop bundles.
2623
const FAVICON: Asset = asset!("/assets/favicon.ico");
2724

2825
fn main() {
29-
// The `launch` function is the main entry point for a dioxus app. It takes a component and renders it with the platform feature
30-
// you have enabled
3126
dioxus::launch(App);
3227
}
3328

34-
/// App is the main component of our app. Components are the building blocks of dioxus apps. Each component is a function
35-
/// that takes some props and returns an Element. In this case, App takes no props because it is the root of our app.
36-
///
37-
/// Components should be annotated with `#[component]` to support props, better error messages, and autocomplete
29+
#[derive(Clone, Debug)]
30+
pub struct AppContext {
31+
pub content: Option<String>,
32+
pub password: String,
33+
pub cipher: Option<crypto::CipherType>,
34+
pub share_url: Option<String>,
35+
pub qr_code: Option<String>,
36+
}
37+
3838
#[component]
3939
fn App() -> Element {
4040
let language =
4141
use_signal(|| i18n::detect_browser_language());
4242

43+
let app_context = use_signal(|| AppContext {
44+
content: None,
45+
password: String::new(),
46+
cipher: None,
47+
share_url: None,
48+
qr_code: None,
49+
});
50+
4351
use_context_provider(|| language);
52+
use_context_provider(|| app_context);
4453

45-
// The `rsx!` macro lets us define HTML inside of rust. It expands to an Element with all of our HTML inside.
46-
// The `rsx!` macro lets us define HTML inside of rust. It expands to an Element with all of our HTML inside.
4754
rsx! {
48-
// In addition to element and text (which we will see later), rsx can contain other components. In this case,
49-
// we are using the `document::Link` component to add a link to our favicon and main CSS file into the head of our app.
5055
document::Link { rel: "icon", href: FAVICON }
5156
document::Link { rel: "stylesheet", href: asset!("/assets/bare.min.css") }
52-
53-
// The router component renders the route enum we defined above. It will handle synchronization of the URL and render
54-
// the layouts and components for the active route.
5557
Router::<Route> {}
5658
}
5759
}

rust/cryptonote/src/views/home.rs

Lines changed: 45 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -4,36 +4,49 @@ use crate::encoding::{
44
};
55
use crate::i18n::{Language, get_translations};
66
use dioxus::prelude::*;
7+
use dioxus_router::prelude::navigator;
78

89
#[component]
910
pub fn Home() -> Element {
1011
let language = use_context::<Signal<Language>>();
1112
let t = get_translations(language());
13+
let nav = navigator();
14+
let mut app_context =
15+
use_context::<Signal<crate::AppContext>>();
1216

1317
let mut note_text = use_signal(|| String::new());
1418
let mut encryption =
1519
use_signal(|| Option::<CipherType>::None);
1620
let mut password = use_signal(|| String::new());
17-
let mut generated_url =
18-
use_signal(|| Option::<String>::None);
19-
let mut qr_code_svg =
20-
use_signal(|| Option::<String>::None);
2121
let mut error_message =
2222
use_signal(|| Option::<String>::None);
2323

24+
use_effect(move || {
25+
let ctx = app_context.read();
26+
if let Some(content) = &ctx.content {
27+
note_text.set(content.clone());
28+
}
29+
if !ctx.password.is_empty() {
30+
password.set(ctx.password.clone());
31+
}
32+
if let Some(cipher) = ctx.cipher {
33+
encryption.set(Some(cipher));
34+
}
35+
});
36+
2437
let generate_note = move |_| {
2538
let t = get_translations(language());
2639
error_message.set(None);
27-
generated_url.set(None);
28-
qr_code_svg.set(None);
2940

3041
let note_content = note_text.read().clone();
3142
let enc_option = encryption.read().clone();
43+
let pwd = password.read().clone();
3244

3345
let note_data = match enc_option {
34-
None => NoteData::PlainText(note_content),
46+
None => {
47+
NoteData::PlainText(note_content.clone())
48+
}
3549
Some(cipher) => {
36-
let pwd = password.read().clone();
3750
if pwd.is_empty() {
3851
error_message.set(Some(
3952
t.password_required.to_string(),
@@ -57,28 +70,33 @@ pub fn Home() -> Element {
5770
}
5871
};
5972

60-
let base_url = web_sys::window()
61-
.and_then(|w| w.location().href().ok())
62-
.unwrap_or_else(|| {
63-
"http://localhost:8080".to_string()
64-
})
65-
.split('#')
66-
.next()
67-
.unwrap_or("http://localhost:8080")
68-
.to_string()
69-
+ "view";
70-
71-
match build_url(&base_url, &note_data) {
72-
Ok(url) => {
73-
match generate_qr_code(&url) {
74-
Ok(svg) => qr_code_svg.set(Some(svg)),
73+
if let Some(window) = web_sys::window() {
74+
if let Ok(origin) = window.location().origin() {
75+
let view_url = format!("{}/view", origin);
76+
match build_url(&view_url, &note_data) {
77+
Ok(url) => match generate_qr_code(&url)
78+
{
79+
Ok(qr) => {
80+
app_context.set(
81+
crate::AppContext {
82+
content: Some(
83+
note_content,
84+
),
85+
password: pwd,
86+
cipher: enc_option,
87+
share_url: Some(url),
88+
qr_code: Some(qr),
89+
},
90+
);
91+
92+
nav.push("/share");
93+
}
94+
Err(e) => error_message
95+
.set(Some(e.localized(&t))),
96+
},
7597
Err(e) => error_message
7698
.set(Some(e.localized(&t))),
7799
}
78-
generated_url.set(Some(url));
79-
}
80-
Err(e) => {
81-
error_message.set(Some(e.localized(&t)))
82100
}
83101
}
84102
};
@@ -158,33 +176,5 @@ pub fn Home() -> Element {
158176
}
159177
}
160178
}
161-
162-
163-
if let Some(url) = generated_url() {
164-
section {
165-
h2 { "{t.share_title}" }
166-
div {
167-
input {
168-
r#type: "text",
169-
readonly: true,
170-
value: "{url}",
171-
onclick: move |_| {
172-
if let Some(window) = web_sys::window() {
173-
let clipboard = window.navigator().clipboard();
174-
let _ = clipboard.write_text(&url);
175-
}
176-
},
177-
}
178-
p { "{t.click_to_copy}" }
179-
}
180-
181-
if let Some(svg) = qr_code_svg() {
182-
figure {
183-
h3 { "{t.qr_code}" }
184-
div { dangerous_inner_html: "{svg}" }
185-
}
186-
}
187-
}
188-
}
189179
}
190180
}

rust/cryptonote/src/views/mod.rs

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,9 @@
1-
//! The views module contains the components for all Layouts and Routes for our app. Each layout and route in our [`Route`]
2-
//! enum will render one of these components.
3-
//!
4-
//!
5-
//! The [`Home`] and [`Blog`] components will be rendered when the current route is [`Route::Home`] or [`Route::Blog`] respectively.
6-
//!
7-
//!
8-
//! The [`Navbar`] component will be rendered on all pages of our app since every page is under the layout. The layout defines
9-
//! a common wrapper around all child routes.
10-
111
mod home;
122
mod navbar;
3+
mod share;
134
mod view;
145

156
pub use home::Home;
167
pub use navbar::Navbar;
8+
pub use share::Share;
179
pub use view::View;

rust/cryptonote/src/views/navbar.rs

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,35 @@
11
use crate::Route;
2-
use crate::i18n::{Language, get_translations};
2+
use crate::i18n::Language;
33
use dioxus::prelude::*;
4+
use dioxus_router::prelude::navigator;
45

56
#[component]
67
pub fn Navbar() -> Element {
78
let mut language = use_context::<Signal<Language>>();
8-
let _t = get_translations(language());
9+
let mut app_context =
10+
use_context::<Signal<crate::AppContext>>();
11+
let nav = navigator();
912

1013
rsx! {
1114
nav {
1215
label {
1316
input { r#type: "checkbox" }
1417
header {
15-
Link { to: Route::Home {}, "🔐 Cryptonote" }
18+
a {
19+
href: "#",
20+
onclick: move |_| {
21+
app_context
22+
.set(crate::AppContext {
23+
content: None,
24+
password: String::new(),
25+
cipher: None,
26+
share_url: None,
27+
qr_code: None,
28+
});
29+
nav.push("/");
30+
},
31+
"🔐 Cryptonote"
32+
}
1633
}
1734
ul {
1835
li { class: if language() == Language::English { "selected" },

0 commit comments

Comments
 (0)