Skip to content

Commit

Permalink
fix: Illias shitcode
Browse files Browse the repository at this point in the history
fix: state inconsistensy
  • Loading branch information
Ddystopia committed Feb 10, 2024
1 parent a986a00 commit 01baafb
Show file tree
Hide file tree
Showing 9 changed files with 155 additions and 70 deletions.
File renamed without changes.
12 changes: 11 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,17 @@ serde = { version = "1.0.193", features = ["derive"] }

[dependencies.web-sys]
version = "0.3.61"
features = ['Document', 'Window', 'Element', 'HtmlElement', 'Node', 'CssStyleDeclaration', 'HtmlAnchorElement']
features = [
'Document',
'Window',
'Element',
'HtmlElement',
'Node',
'CssStyleDeclaration',
'HtmlAnchorElement',
'Navigator',
'Clipboard',
]

[dependencies.monaco]
git = "https://github.com/siku2/rust-monaco/"
Expand Down
16 changes: 5 additions & 11 deletions js/copyToClipboard.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
// Copy to the clipboard

export function copyToClipboard(text) {
var textArea = document.createElement("textarea");
textArea.value = text;
document.body.appendChild(textArea);
textArea.select();
document.execCommand("copy");
textArea.remove();
alert("Copied to clipboard");
}
export function copyToClipboard(text, callback) {
window.navigator.clipboard.writeText(text)
.then(() => callback(true))
.catch(() => callback(false))
}
47 changes: 30 additions & 17 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,18 @@ use std::rc::Rc;
use yew::prelude::*;
use yewdux::prelude::*;

#[cfg(not(feature = "ssr"))]
use crate::monaco_tweaks::EditorStoreListener;
use crate::{
code_editor::CustomEditor,
code_runner::{CodeRunner, DebugAction},
header::Header,
memory::Memory,
store::{dispatch, Store},
utils::{copy_to_clipboard, HydrationGate},
utils::HydrationGate,
};
#[cfg(not(feature = "ssr"))]
use crate::{
monaco_tweaks::EditorStoreListener,
utils::{copy_to_clipboard, get_author},
};

pub struct App {
Expand Down Expand Up @@ -46,8 +49,7 @@ impl Component for App {
let line = store.current_debug_line;
let read_only = store.read_only;

html! {
<YewduxRoot>
let main = html! {
<main id="ram-web">
<Header {on_run} {on_step} {on_stop} {on_copy} />

Expand All @@ -63,7 +65,15 @@ impl Component for App {
<CodeRunner dispatch_setter={ctx.link().callback(Msg::SetRunnerDispatch)} />

</main>
</YewduxRoot>
};

#[cfg(not(feature = "ssr"))]
{
main
}
#[cfg(feature = "ssr")]
html! {
<YewduxRoot>{main}</YewduxRoot>
}
}

Expand Down Expand Up @@ -93,11 +103,9 @@ impl Component for App {
self.store = store;
return true;
}

#[cfg(feature = "ssr")]
Msg::DebugStep | Msg::DebugStart => {
panic!("Debugging is not supported in server side rendering")
}
Msg::CopyToClipboard | Msg::DebugStep | Msg::DebugStart => unreachable!(),

#[cfg(not(feature = "ssr"))]
Msg::DebugStart => {
let text_model = &self.store.get_model();
Expand All @@ -113,17 +121,22 @@ impl Component for App {
Msg::DebugStop => {
self.code_runner_dispatch.emit(DebugAction::Stop);
}
#[cfg(not(feature = "ssr"))]
Msg::CopyToClipboard => {
let text_model = &self.store.get_model();
let value = text_model.get_value();
let encoded_value = urlencoding::encode(&value);
let current_page = web_sys::window()
.expect("no global window")
.location()
.href()
.expect("no href");
let url = format!("{}?code={}", current_page, encoded_value);
log::info!("Copying to clipboard: {}", url);
let author = get_author().map(|it| urlencoding::encode(&it).into_owned());
let current_page = gloo::utils::window().location().origin();
let current_page = current_page.expect("no origin");
let mut url = format!("{}?code={}", current_page, encoded_value);

if let Some(author) = author {
url += "&author=";
url += &author;
}

log::debug!("Copying to clipboard: {}", url);
copy_to_clipboard(&url);
}
}
Expand Down
26 changes: 15 additions & 11 deletions src/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ use gloo::events::EventListener;
use wasm_bindgen::JsCast;
use web_sys::Node;
use yew::prelude::*;
use yewdux::use_selector;

use crate::about_popup::AboutPopup;
use crate::{about_popup::AboutPopup, store::Store, utils::get_author};

#[derive(Default, Clone, PartialEq, Properties)]
pub struct Props {
Expand All @@ -19,6 +20,7 @@ pub fn header(props: &Props) -> Html {
let popup_button_ref = use_node_ref();
let show_popup = use_state_eq(|| false);
let event_listener = use_state(|| None);
let copy_button_state = *use_selector(|store: &Store| store.copy_button_state);

let callback = use_callback(
(
Expand Down Expand Up @@ -55,15 +57,7 @@ pub fn header(props: &Props) -> Html {
let on_stop = props.on_stop.clone();
let on_copy = props.on_copy.clone();

let author = gloo::utils::window()
.location()
.search()
.expect("No search in URL!")
.replace('?', "")
.split('&')
.find(|x| x.starts_with("author="))
.map(|x| x.replace("author=", ""))
.map(|x| x.replace("%20", " "));
let author = get_author();

// we should fix style for this
#[allow(unused_variables)]
Expand All @@ -73,6 +67,14 @@ pub fn header(props: &Props) -> Html {
.expect("no search in url!")
.contains("code=");

log::debug!("{copy_button_state:?}");

let copy_button_class = match copy_button_state {
Some(true) => "btn--success",
Some(false) => "btn--error",
None => "",
};

html! {
<header>
if *show_popup {
Expand All @@ -97,7 +99,9 @@ pub fn header(props: &Props) -> Html {
<button onclick={move |_| on_start.emit(())} class="control-btn"><div class="start-btn"/></button>
<button onclick={move |_| on_step.emit(())} class="control-btn"><div class="step-btn"/></button>
<button onclick={move |_| on_stop.emit(())} class="control-btn"><div class="stop-btn"/></button>
<button onclick={move |_| on_copy.emit(())} class="control-btn"><div class="copy-btn"/></button>
<button onclick={move |_| on_copy.emit(())} class={classes!("control-btn", copy_button_class)}>
<div class="copy-btn"/>
</button>
</div>
<div class="help">
<button
Expand Down
1 change: 0 additions & 1 deletion src/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ const STEP_SIZE: usize = 50;
pub fn Memory() -> Html {
let registers = use_selector(|s: &Store| s.get_registers().clone());

// TODO: Should it be in store? So we can persist it?
let starting_index = use_state(|| 0);

let register_entries = (0..WINDOW_LENGTH)
Expand Down
18 changes: 13 additions & 5 deletions src/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,22 @@ use monaco::api::TextModel;
use monaco::yew::CodeEditorLink;
use ramemu::registers::Registers;
use serde::{Deserialize, Serialize};
use yewdux::{prelude::*, Context};
use yewdux::prelude::*;

use crate::{code_editor::DEFAULT_CODE, io::output::OutputComponentErrors};

thread_local! {
static CONTEXT: Context = Default::default();
}
// #[cfg(target = "wasm32-unknown-unknown")]
// pub fn dispatch() -> Dispatch<Store> {
// use yewdux::Context;
// thread_local! {
// static CONTEXT: Context = Default::default();
// }
//
// Dispatch::new(&CONTEXT.with(|context| context.clone()))
// }

pub fn dispatch() -> Dispatch<Store> {
Dispatch::new(&CONTEXT.with(|context| context.clone()))
Dispatch::global()
}

#[derive(Default, PartialEq, Store, Clone, Serialize, Deserialize)]
Expand All @@ -31,6 +37,8 @@ pub struct Store {
pub current_debug_line: usize,
#[serde(skip)]
registers: Registers<i64>,
#[serde(skip)]
pub copy_button_state: Option<bool>,

#[cfg(not(feature = "ssr"))]
text_model: TextModelWrapper,
Expand Down
63 changes: 56 additions & 7 deletions src/utils.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
use wasm_bindgen::{prelude::*, JsValue};

#[cfg(not(feature = "ssr"))]
use js_sys::{Array, Object};
use wasm_bindgen::{prelude::*, JsCast, JsValue};
#[cfg(not(feature = "ssr"))]
use web_sys::HtmlAnchorElement;

use monaco::api::{CodeEditor, TextModel};
use monaco::sys::editor::{ICodeEditor, IEditor, IIdentifiedSingleEditOperation, ITextModel};
use monaco::sys::{Position, Range};
#[cfg(not(feature = "ssr"))]
use monaco::{
api::{CodeEditor, TextModel},
sys::{
editor::{ICodeEditor, IEditor, IIdentifiedSingleEditOperation, ITextModel},
Position, Range,
},
};

use yew::function_component;
use yew::prelude::*;

#[function_component]
Expand All @@ -29,6 +36,7 @@ pub struct Props {
pub placeholder: Html,
}

#[cfg(not(feature = "ssr"))]
fn get_selection_or_cursor_range(ieditor: &ICodeEditor) -> Option<Range> {
let selection = ieditor.get_selection()?;

Expand All @@ -48,6 +56,7 @@ fn get_selection_or_cursor_range(ieditor: &ICodeEditor) -> Option<Range> {
}
}

#[cfg(not(feature = "ssr"))]
pub fn comment_code(editor: &CodeEditor, model: &TextModel) -> Result<(), ()> {
let ieditor: &ICodeEditor = editor.as_ref();
let range = get_selection_or_cursor_range(ieditor).ok_or(())?;
Expand Down Expand Up @@ -93,6 +102,26 @@ pub fn comment_code(editor: &CodeEditor, model: &TextModel) -> Result<(), ()> {
Ok(())
}

pub fn get_author() -> Option<String> {
gloo::utils::window()
.location()
.search()
.unwrap_or_default()
.replace('?', "")
.split('&')
.find_map(|x| x.strip_prefix("author="))
.map(|x| x.replace('+', "%20"))
.and_then(|x| Some(urlencoding::decode(&x).ok()?.into_owned()))
.and_then(|x| {
let res: String = x
.chars()
.filter(|c| c.is_alphanumeric() || *c == ',' || *c == '.' || *c == ' ')
.collect();
(!res.is_empty()).then_some(res)
})
}

#[cfg(not(feature = "ssr"))]
pub fn download_code(content: &str) -> Result<(), JsValue> {
let document = gloo::utils::document();
let body = gloo::utils::body();
Expand All @@ -115,12 +144,32 @@ pub fn download_code(content: &str) -> Result<(), JsValue> {
Ok(())
}

#[cfg(not(feature = "ssr"))]
fn clipboard_callback(success: bool) {
use crate::store::dispatch;
use std::time::Duration;
use yew::platform::time::sleep;

dispatch().reduce_mut(|store| store.copy_button_state = Some(success));
yew::platform::spawn_local(async {
sleep(Duration::from_secs(3)).await;
dispatch().reduce_mut(|store| store.copy_button_state = None)
})
}

#[cfg(not(feature = "ssr"))]
pub fn copy_to_clipboard(text: &str) {
copy_to_clipboard_js(text);
thread_local! {
static CLOSURE: Closure<dyn FnMut(JsValue)> = Closure::wrap(Box::new(|v| {
clipboard_callback(v.as_bool().unwrap_or_default());
}));
}

CLOSURE.with(|c| copy_to_clipboard_js(text, c))
}

#[wasm_bindgen(module = "/js/copyToClipboard.js")]
extern "C" {
#[wasm_bindgen(js_name = "copyToClipboard")]
fn copy_to_clipboard_js(text: &str);
fn copy_to_clipboard_js(text: &str, callback: &Closure<dyn FnMut(JsValue)>);
}
Loading

0 comments on commit 01baafb

Please sign in to comment.