Refactor to further split into more files.
This commit is contained in:
		
							parent
							
								
									180ffda98b
								
							
						
					
					
						commit
						77feb4734d
					
				@ -3,7 +3,8 @@ use std::{ops::Deref, rc::Rc};
 | 
			
		||||
use crate::{FrameId, GlobalLayoutState, GlobalMemoCell, PanelDirection, SplitPanel};
 | 
			
		||||
use anyhow::Error;
 | 
			
		||||
use editor_area::EditorArea;
 | 
			
		||||
use itertools::Itertools;
 | 
			
		||||
use editor_nav::EditorNav;
 | 
			
		||||
use storage::fetch_initial_editor_state;
 | 
			
		||||
use wasm_bindgen::{closure::Closure, JsCast};
 | 
			
		||||
use web_sys::{window, HtmlInputElement, KeyboardEvent};
 | 
			
		||||
use yew::{
 | 
			
		||||
@ -11,7 +12,11 @@ use yew::{
 | 
			
		||||
    Callback, Html, Properties, UseStateHandle,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
use self::storage::load_file_contents;
 | 
			
		||||
 | 
			
		||||
mod editor_area;
 | 
			
		||||
mod editor_nav;
 | 
			
		||||
mod storage;
 | 
			
		||||
 | 
			
		||||
#[derive(Properties, PartialEq, Clone)]
 | 
			
		||||
pub struct EditorViewProps {
 | 
			
		||||
@ -43,77 +48,6 @@ pub struct EditorViewState {
 | 
			
		||||
    show_delete_dialog: Option<String>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn fetch_initial_editor_state_or_fail() -> anyhow::Result<EditorViewState> {
 | 
			
		||||
    let win = window().ok_or_else(|| Error::msg("Can't get window"))?;
 | 
			
		||||
    let local = win
 | 
			
		||||
        .local_storage()
 | 
			
		||||
        .map_err(|_| Error::msg("Error retrieving localStorage"))?
 | 
			
		||||
        .ok_or_else(|| Error::msg("Local storage not available"))?;
 | 
			
		||||
 | 
			
		||||
    let n_keys = local
 | 
			
		||||
        .length()
 | 
			
		||||
        .map_err(|_| Error::msg("localStorage broken"))?;
 | 
			
		||||
    let mut available_files: Vec<AttrValue> = vec![];
 | 
			
		||||
    for i in 0..n_keys {
 | 
			
		||||
        if let Some(key) = local
 | 
			
		||||
            .key(i)
 | 
			
		||||
            .map_err(|_| Error::msg("localStorage broken"))?
 | 
			
		||||
        {
 | 
			
		||||
            match key.strip_prefix("scriptfile_") {
 | 
			
		||||
                None => {}
 | 
			
		||||
                Some(filename) => {
 | 
			
		||||
                    available_files.push(filename.to_owned().into());
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let init_str: AttrValue = "init.lua".into();
 | 
			
		||||
    if !available_files.contains(&init_str) {
 | 
			
		||||
        available_files.push(init_str);
 | 
			
		||||
        local
 | 
			
		||||
            .set(
 | 
			
		||||
                "scriptfile_init.lua",
 | 
			
		||||
                "-- Put any code to run on every client load here.\n",
 | 
			
		||||
            )
 | 
			
		||||
            .map_err(|_| Error::msg("localStorage broken"))?;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Ok(EditorViewState {
 | 
			
		||||
        error_msg: None,
 | 
			
		||||
        available_files,
 | 
			
		||||
        open_file: "init.lua".into(),
 | 
			
		||||
        show_create_dialog: false,
 | 
			
		||||
        show_delete_dialog: None,
 | 
			
		||||
    })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn fetch_initial_editor_state() -> Rc<EditorViewState> {
 | 
			
		||||
    match fetch_initial_editor_state_or_fail() {
 | 
			
		||||
        Ok(s) => s.into(),
 | 
			
		||||
        Err(e) => EditorViewState {
 | 
			
		||||
            error_msg: Some(format!("Can't load editor data: {}", e).into()),
 | 
			
		||||
            available_files: vec![],
 | 
			
		||||
            open_file: "init.lua".into(),
 | 
			
		||||
            show_create_dialog: false,
 | 
			
		||||
            show_delete_dialog: None,
 | 
			
		||||
        }
 | 
			
		||||
        .into(),
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn load_file_contents(file: &str) -> anyhow::Result<String> {
 | 
			
		||||
    let win = window().ok_or_else(|| Error::msg("Can't get window"))?;
 | 
			
		||||
    let local = win
 | 
			
		||||
        .local_storage()
 | 
			
		||||
        .map_err(|_| Error::msg("Error retrieving localStorage"))?
 | 
			
		||||
        .ok_or_else(|| Error::msg("Local storage not available"))?;
 | 
			
		||||
    Ok(local
 | 
			
		||||
        .get(&format!("scriptfile_{}", file))
 | 
			
		||||
        .map_err(|_| Error::msg("Error retrieving localStorage"))?
 | 
			
		||||
        .unwrap_or_else(|| "".to_owned()))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn try_run_script(script: &str, global_memo: &GlobalMemoCell) -> anyhow::Result<()> {
 | 
			
		||||
    let script = load_file_contents(script)?;
 | 
			
		||||
    global_memo
 | 
			
		||||
@ -138,62 +72,6 @@ where
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn show_create_dialog(state: &UseStateHandle<Rc<EditorViewState>>) {
 | 
			
		||||
    let mut new_state: EditorViewState = (*state.deref().deref()).clone();
 | 
			
		||||
    new_state.show_create_dialog = true;
 | 
			
		||||
    state.set(new_state.into());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[function_component(EditorNav)]
 | 
			
		||||
fn editor_nav(props: &EditorViewDetailProps) -> Html {
 | 
			
		||||
    let global_memo = props.global_memo.clone();
 | 
			
		||||
    let global_layout = props.global_layout.clone();
 | 
			
		||||
    let frame = props.frame.clone();
 | 
			
		||||
    let current_script = props.editor_state.open_file.clone();
 | 
			
		||||
 | 
			
		||||
    let set_err_state = props.editor_state.clone();
 | 
			
		||||
    let set_err = Rc::new(move |msg: Option<&str>| {
 | 
			
		||||
        let mut new_state = (*set_err_state.as_ref()).clone();
 | 
			
		||||
        new_state.error_msg = msg.map(|v| AttrValue::from(String::from(v)));
 | 
			
		||||
        set_err_state.set(new_state.into());
 | 
			
		||||
    });
 | 
			
		||||
    let editor_state = props.editor_state.clone();
 | 
			
		||||
    html! {
 | 
			
		||||
        <div class="editornav">
 | 
			
		||||
          <nav class="navbar navbar-expand-lg bg-body-tertiary">
 | 
			
		||||
            <button class="btn" aria-label="Run" title="Run"
 | 
			
		||||
              onclick={move |_ev| run_script(¤t_script, &global_memo, set_err.clone())}>
 | 
			
		||||
              <i class="bi bi-file-earmark-play"></i></button>
 | 
			
		||||
            <button class="btn" aria-label="New file" title="New file"
 | 
			
		||||
              onclick={move |_ev| show_create_dialog(&editor_state) }
 | 
			
		||||
            ><i class="bi bi-file-earmark-plus"></i></button>
 | 
			
		||||
            <div class="flex-fill"/>
 | 
			
		||||
            <button class="btn" onclick={move |_ev| close_editor(&frame, &global_layout)} aria-label="Close Editor" title="Close editor"><i class="bi bi-arrow-return-left"></i></button>
 | 
			
		||||
          </nav>
 | 
			
		||||
          <ul class="p-2 list-group">
 | 
			
		||||
        {props
 | 
			
		||||
         .editor_state
 | 
			
		||||
         .available_files
 | 
			
		||||
         .iter()
 | 
			
		||||
         .map(|f| {
 | 
			
		||||
             let mut classes = vec!["list-group-item", "pe-auto"];
 | 
			
		||||
             let mut aria_current = None;
 | 
			
		||||
             if *f == props.editor_state.open_file {
 | 
			
		||||
                 aria_current = Some("true");
 | 
			
		||||
                 classes.push("active");
 | 
			
		||||
             }
 | 
			
		||||
             html! { <li aria-current={aria_current} tabindex={0}
 | 
			
		||||
                      class={classes.iter().join(" ")}
 | 
			
		||||
                      style="cursor: pointer"
 | 
			
		||||
                      >{f}</li>}
 | 
			
		||||
         })
 | 
			
		||||
         .collect::<Vec<Html>>()
 | 
			
		||||
        }
 | 
			
		||||
          </ul>
 | 
			
		||||
        </div>
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Properties, PartialEq, Clone)]
 | 
			
		||||
pub struct ErrorBarProps {
 | 
			
		||||
    pub msg: AttrValue,
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										62
									
								
								src/editor_view/editor_nav.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								src/editor_view/editor_nav.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,62 @@
 | 
			
		||||
use std::{ops::Deref, rc::Rc};
 | 
			
		||||
 | 
			
		||||
use itertools::Itertools;
 | 
			
		||||
use yew::{function_component, html, AttrValue, Html, UseStateHandle};
 | 
			
		||||
 | 
			
		||||
use super::{close_editor, run_script, EditorViewDetailProps, EditorViewState};
 | 
			
		||||
 | 
			
		||||
fn show_create_dialog(state: &UseStateHandle<Rc<EditorViewState>>) {
 | 
			
		||||
    let mut new_state: EditorViewState = (*state.deref().deref()).clone();
 | 
			
		||||
    new_state.show_create_dialog = true;
 | 
			
		||||
    state.set(new_state.into());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[function_component(EditorNav)]
 | 
			
		||||
pub(super) fn editor_nav(props: &EditorViewDetailProps) -> Html {
 | 
			
		||||
    let global_memo = props.global_memo.clone();
 | 
			
		||||
    let global_layout = props.global_layout.clone();
 | 
			
		||||
    let frame = props.frame.clone();
 | 
			
		||||
    let current_script = props.editor_state.open_file.clone();
 | 
			
		||||
 | 
			
		||||
    let set_err_state = props.editor_state.clone();
 | 
			
		||||
    let set_err = Rc::new(move |msg: Option<&str>| {
 | 
			
		||||
        let mut new_state = (*set_err_state.as_ref()).clone();
 | 
			
		||||
        new_state.error_msg = msg.map(|v| AttrValue::from(String::from(v)));
 | 
			
		||||
        set_err_state.set(new_state.into());
 | 
			
		||||
    });
 | 
			
		||||
    let editor_state = props.editor_state.clone();
 | 
			
		||||
    html! {
 | 
			
		||||
        <div class="editornav">
 | 
			
		||||
          <nav class="navbar navbar-expand-lg bg-body-tertiary">
 | 
			
		||||
            <button class="btn" aria-label="Run" title="Run"
 | 
			
		||||
              onclick={move |_ev| run_script(¤t_script, &global_memo, set_err.clone())}>
 | 
			
		||||
              <i class="bi bi-file-earmark-play"></i></button>
 | 
			
		||||
            <button class="btn" aria-label="New file" title="New file"
 | 
			
		||||
              onclick={move |_ev| show_create_dialog(&editor_state) }
 | 
			
		||||
            ><i class="bi bi-file-earmark-plus"></i></button>
 | 
			
		||||
            <div class="flex-fill"/>
 | 
			
		||||
            <button class="btn" onclick={move |_ev| close_editor(&frame, &global_layout)} aria-label="Close Editor" title="Close editor"><i class="bi bi-arrow-return-left"></i></button>
 | 
			
		||||
          </nav>
 | 
			
		||||
          <ul class="p-2 list-group">
 | 
			
		||||
        {props
 | 
			
		||||
         .editor_state
 | 
			
		||||
         .available_files
 | 
			
		||||
         .iter()
 | 
			
		||||
         .map(|f| {
 | 
			
		||||
             let mut classes = vec!["list-group-item", "pe-auto"];
 | 
			
		||||
             let mut aria_current = None;
 | 
			
		||||
             if *f == props.editor_state.open_file {
 | 
			
		||||
                 aria_current = Some("true");
 | 
			
		||||
                 classes.push("active");
 | 
			
		||||
             }
 | 
			
		||||
             html! { <li aria-current={aria_current} tabindex={0}
 | 
			
		||||
                      class={classes.iter().join(" ")}
 | 
			
		||||
                      style="cursor: pointer"
 | 
			
		||||
                      >{f}</li>}
 | 
			
		||||
         })
 | 
			
		||||
         .collect::<Vec<Html>>()
 | 
			
		||||
        }
 | 
			
		||||
          </ul>
 | 
			
		||||
        </div>
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										77
									
								
								src/editor_view/storage.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								src/editor_view/storage.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,77 @@
 | 
			
		||||
use std::rc::Rc;
 | 
			
		||||
 | 
			
		||||
use super::EditorViewState;
 | 
			
		||||
use anyhow::Error;
 | 
			
		||||
use web_sys::window;
 | 
			
		||||
use yew::AttrValue;
 | 
			
		||||
 | 
			
		||||
fn fetch_initial_editor_state_or_fail() -> anyhow::Result<EditorViewState> {
 | 
			
		||||
    let win = window().ok_or_else(|| Error::msg("Can't get window"))?;
 | 
			
		||||
    let local = win
 | 
			
		||||
        .local_storage()
 | 
			
		||||
        .map_err(|_| Error::msg("Error retrieving localStorage"))?
 | 
			
		||||
        .ok_or_else(|| Error::msg("Local storage not available"))?;
 | 
			
		||||
 | 
			
		||||
    let n_keys = local
 | 
			
		||||
        .length()
 | 
			
		||||
        .map_err(|_| Error::msg("localStorage broken"))?;
 | 
			
		||||
    let mut available_files: Vec<AttrValue> = vec![];
 | 
			
		||||
    for i in 0..n_keys {
 | 
			
		||||
        if let Some(key) = local
 | 
			
		||||
            .key(i)
 | 
			
		||||
            .map_err(|_| Error::msg("localStorage broken"))?
 | 
			
		||||
        {
 | 
			
		||||
            match key.strip_prefix("scriptfile_") {
 | 
			
		||||
                None => {}
 | 
			
		||||
                Some(filename) => {
 | 
			
		||||
                    available_files.push(filename.to_owned().into());
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let init_str: AttrValue = "init.lua".into();
 | 
			
		||||
    if !available_files.contains(&init_str) {
 | 
			
		||||
        available_files.push(init_str);
 | 
			
		||||
        local
 | 
			
		||||
            .set(
 | 
			
		||||
                "scriptfile_init.lua",
 | 
			
		||||
                "-- Put any code to run on every client load here.\n",
 | 
			
		||||
            )
 | 
			
		||||
            .map_err(|_| Error::msg("localStorage broken"))?;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Ok(EditorViewState {
 | 
			
		||||
        error_msg: None,
 | 
			
		||||
        available_files,
 | 
			
		||||
        open_file: "init.lua".into(),
 | 
			
		||||
        show_create_dialog: false,
 | 
			
		||||
        show_delete_dialog: None,
 | 
			
		||||
    })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub(super) fn fetch_initial_editor_state() -> Rc<EditorViewState> {
 | 
			
		||||
    match fetch_initial_editor_state_or_fail() {
 | 
			
		||||
        Ok(s) => s.into(),
 | 
			
		||||
        Err(e) => EditorViewState {
 | 
			
		||||
            error_msg: Some(format!("Can't load editor data: {}", e).into()),
 | 
			
		||||
            available_files: vec![],
 | 
			
		||||
            open_file: "init.lua".into(),
 | 
			
		||||
            show_create_dialog: false,
 | 
			
		||||
            show_delete_dialog: None,
 | 
			
		||||
        }
 | 
			
		||||
        .into(),
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn load_file_contents(file: &str) -> anyhow::Result<String> {
 | 
			
		||||
    let win = window().ok_or_else(|| Error::msg("Can't get window"))?;
 | 
			
		||||
    let local = win
 | 
			
		||||
        .local_storage()
 | 
			
		||||
        .map_err(|_| Error::msg("Error retrieving localStorage"))?
 | 
			
		||||
        .ok_or_else(|| Error::msg("Local storage not available"))?;
 | 
			
		||||
    Ok(local
 | 
			
		||||
        .get(&format!("scriptfile_{}", file))
 | 
			
		||||
        .map_err(|_| Error::msg("Error retrieving localStorage"))?
 | 
			
		||||
        .unwrap_or_else(|| "".to_owned()))
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user