Implement HTML view type.
This commit is contained in:
parent
3623acbd21
commit
de00a4de66
@ -8,6 +8,7 @@ use yew::prelude::*;
|
||||
use crate::{
|
||||
command_handler::command_handler,
|
||||
editor_view::CodeEditorView,
|
||||
html_view::HtmlView,
|
||||
lineengine::line::{Readline, ReadlineEvent},
|
||||
term_split::TermSplit,
|
||||
timer_host::TimerHost,
|
||||
@ -76,6 +77,7 @@ pub struct FrameId(pub u64);
|
||||
pub enum FrameViewType {
|
||||
Terminal,
|
||||
Editor,
|
||||
Html { inner: String },
|
||||
}
|
||||
|
||||
#[derive(Properties)]
|
||||
@ -239,6 +241,9 @@ pub fn term_view(props: &TermViewProps) -> Html {
|
||||
global_memo={props.global_memo.clone()}
|
||||
global_layout={props.global_layout.clone()}/>
|
||||
},
|
||||
FrameViewType::Html { inner } => html! {
|
||||
<HtmlView inner={inner.clone()}/>
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
12
src/html_view.rs
Normal file
12
src/html_view.rs
Normal file
@ -0,0 +1,12 @@
|
||||
use yew::prelude::*;
|
||||
use yew::{function_component, Properties};
|
||||
|
||||
#[derive(Properties, PartialEq)]
|
||||
pub struct HtmlViewProps {
|
||||
pub inner: String,
|
||||
}
|
||||
|
||||
#[function_component(HtmlView)]
|
||||
pub fn html_view(props: &HtmlViewProps) -> Html {
|
||||
html! { <iframe class="htmlview" srcdoc={props.inner.clone()} sandbox=""/> }
|
||||
}
|
@ -221,6 +221,7 @@ pub fn install_lua_globals(
|
||||
register_command!(echo_frame_raw);
|
||||
register_command!(editor);
|
||||
register_stateless_command!(cmd_help, "help");
|
||||
register_command!(html);
|
||||
register_command!(hsplit);
|
||||
register_stateless_command!(cmd_include, "include");
|
||||
register_command!(cmd_list_logs, "listlogs");
|
||||
|
@ -12,6 +12,8 @@ use piccolo::{
|
||||
SequenceReturn, StashedTable, StashedUserData, StashedValue, Table, UserData, Value, Variadic,
|
||||
};
|
||||
use std::{rc::Rc, str};
|
||||
use wasm_bindgen::JsValue;
|
||||
use web_sys::console;
|
||||
use yew::UseStateSetter;
|
||||
|
||||
use super::call_checking_metatable;
|
||||
@ -774,7 +776,57 @@ pub(super) fn editor<'gc>(
|
||||
new_gl
|
||||
.frame_views
|
||||
.insert(cur_frame_id, FrameViewType::Editor);
|
||||
global_layout.set(new_gl.into());
|
||||
let new_gl: Rc<GlobalLayoutState> = new_gl.into();
|
||||
global_layout.set(new_gl.clone());
|
||||
(*global_memo.layout.borrow_mut()) = new_gl;
|
||||
}
|
||||
};
|
||||
Ok(piccolo::CallbackReturn::Return)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn html<'gc>(
|
||||
ctx: Context<'gc>,
|
||||
global_memo: &GlobalMemoCell,
|
||||
global_layout: &UseStateSetter<GlobalLayoutCell>,
|
||||
) -> Callback<'gc> {
|
||||
let global_memo = global_memo.clone();
|
||||
let global_layout = global_layout.clone();
|
||||
Callback::from_fn(&ctx, move |ctx, _ex, mut stack| {
|
||||
let (frame, inner): (u64, String) = stack.consume(ctx)?;
|
||||
let target_frame_id: FrameId = FrameId(frame);
|
||||
let will_have_remaining_terminal = {
|
||||
let layout = global_memo.layout.borrow();
|
||||
layout.term_splits.iter().any(|f| {
|
||||
(*f != target_frame_id)
|
||||
&& matches!(
|
||||
layout
|
||||
.frame_views
|
||||
.get(f)
|
||||
.unwrap_or(&FrameViewType::Terminal),
|
||||
FrameViewType::Terminal
|
||||
)
|
||||
})
|
||||
};
|
||||
if !will_have_remaining_terminal {
|
||||
Err(anyhow::Error::msg(
|
||||
"html command that would leave user with no remaining terminal is invalid",
|
||||
))?
|
||||
}
|
||||
match global_memo
|
||||
.frame_registry
|
||||
.borrow_mut()
|
||||
.get_mut(&target_frame_id)
|
||||
{
|
||||
None => Err(anyhow::Error::msg("Frame no longer exists"))?,
|
||||
Some(_frame_dat) => {
|
||||
let mut new_gl: GlobalLayoutState = (*global_memo.layout.borrow().as_ref()).clone();
|
||||
new_gl
|
||||
.frame_views
|
||||
.insert(target_frame_id, FrameViewType::Html { inner });
|
||||
let new_gl: Rc<GlobalLayoutState> = new_gl.into();
|
||||
global_layout.set(new_gl.clone());
|
||||
(*global_memo.layout.borrow_mut()) = new_gl;
|
||||
}
|
||||
};
|
||||
Ok(piccolo::CallbackReturn::Return)
|
||||
|
@ -11,6 +11,7 @@ use yew::prelude::*;
|
||||
pub mod command_handler;
|
||||
pub mod editor_view;
|
||||
pub mod frame_view;
|
||||
pub mod html_view;
|
||||
pub mod id_intern;
|
||||
pub mod lineengine;
|
||||
pub mod logging;
|
||||
|
@ -1,5 +1,8 @@
|
||||
use itertools::Itertools;
|
||||
use std::{collections::BTreeMap, rc::Rc};
|
||||
use std::{
|
||||
collections::{BTreeMap, VecDeque},
|
||||
rc::Rc,
|
||||
};
|
||||
|
||||
use crate::FrameId;
|
||||
|
||||
@ -19,6 +22,12 @@ pub enum TermSplit {
|
||||
}
|
||||
|
||||
impl TermSplit {
|
||||
pub fn iter<'t>(&'t self) -> AccessibleSplitIter<'t> {
|
||||
AccessibleSplitIter {
|
||||
queue: vec![self].into(),
|
||||
}
|
||||
}
|
||||
|
||||
fn collect_term_frames(&self, into: &mut BTreeMap<FrameId, usize>) {
|
||||
match self {
|
||||
TermSplit::Term { frame } => {
|
||||
@ -136,6 +145,31 @@ impl TermSplit {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct AccessibleSplitIter<'t> {
|
||||
queue: VecDeque<&'t TermSplit>,
|
||||
}
|
||||
|
||||
impl<'t> Iterator for AccessibleSplitIter<'t> {
|
||||
type Item = &'t FrameId;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
loop {
|
||||
match self.queue.pop_back() {
|
||||
Some(TermSplit::Horizontal { left, right }) => {
|
||||
self.queue.push_front(left);
|
||||
self.queue.push_front(right);
|
||||
}
|
||||
Some(TermSplit::Vertical { top, bottom }) => {
|
||||
self.queue.push_front(top);
|
||||
self.queue.push_front(bottom);
|
||||
}
|
||||
Some(TermSplit::Term { frame }) => break Some(frame),
|
||||
None => break None,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@ -237,4 +271,36 @@ mod tests {
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn iterates_termframes() {
|
||||
use TermSplit::*;
|
||||
let t = Vertical {
|
||||
top: Horizontal {
|
||||
left: Horizontal {
|
||||
left: Term { frame: FrameId(42) }.into(),
|
||||
right: Term { frame: FrameId(64) }.into(),
|
||||
}
|
||||
.into(),
|
||||
right: Term { frame: FrameId(42) }.into(),
|
||||
}
|
||||
.into(),
|
||||
bottom: Vertical {
|
||||
top: Term { frame: FrameId(43) }.into(),
|
||||
bottom: Term { frame: FrameId(44) }.into(),
|
||||
}
|
||||
.into(),
|
||||
};
|
||||
let frames: Vec<_> = t.iter().collect();
|
||||
assert_eq!(
|
||||
frames,
|
||||
vec![
|
||||
&FrameId(42),
|
||||
&FrameId(43),
|
||||
&FrameId(44),
|
||||
&FrameId(42),
|
||||
&FrameId(64),
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -85,3 +85,10 @@ body {
|
||||
min-width: 1px;
|
||||
min-height: 1px;
|
||||
}
|
||||
.htmlview {
|
||||
margin: 10px;
|
||||
min-width: 1px;
|
||||
min-height: 1px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user