diff options
Diffstat (limited to 'examples/markdown/src/main.rs')
-rw-r--r-- | examples/markdown/src/main.rs | 111 |
1 files changed, 99 insertions, 12 deletions
diff --git a/examples/markdown/src/main.rs b/examples/markdown/src/main.rs index 5605478f..5b9a3b4a 100644 --- a/examples/markdown/src/main.rs +++ b/examples/markdown/src/main.rs @@ -1,23 +1,37 @@ use iced::highlighter; -use iced::widget::{self, markdown, row, scrollable, text_editor}; -use iced::{Element, Fill, Font, Task, Theme}; +use iced::time::{self, milliseconds}; +use iced::widget::{ + self, hover, markdown, right, row, scrollable, text_editor, toggler, +}; +use iced::{Element, Fill, Font, Subscription, Task, Theme}; pub fn main() -> iced::Result { iced::application("Markdown - Iced", Markdown::update, Markdown::view) + .subscription(Markdown::subscription) .theme(Markdown::theme) .run_with(Markdown::new) } struct Markdown { content: text_editor::Content, - items: Vec<markdown::Item>, + mode: Mode, theme: Theme, } +enum Mode { + Preview(Vec<markdown::Item>), + Stream { + pending: String, + parsed: markdown::Content, + }, +} + #[derive(Debug, Clone)] enum Message { Edit(text_editor::Action), LinkClicked(markdown::Url), + ToggleStream(bool), + NextToken, } impl Markdown { @@ -29,14 +43,14 @@ impl Markdown { ( Self { content: text_editor::Content::with_text(INITIAL_CONTENT), - items: markdown::parse(INITIAL_CONTENT).collect(), + mode: Mode::Preview(markdown::parse(INITIAL_CONTENT).collect()), theme, }, widget::focus_next(), ) } - fn update(&mut self, message: Message) { + fn update(&mut self, message: Message) -> Task<Message> { match message { Message::Edit(action) => { let is_edit = action.is_edit(); @@ -44,12 +58,56 @@ impl Markdown { self.content.perform(action); if is_edit { - self.items = - markdown::parse(&self.content.text()).collect(); + self.mode = Mode::Preview( + markdown::parse(&self.content.text()).collect(), + ); } + + Task::none() } Message::LinkClicked(link) => { let _ = open::that_in_background(link.to_string()); + + Task::none() + } + Message::ToggleStream(enable_stream) => { + if enable_stream { + self.mode = Mode::Stream { + pending: self.content.text(), + parsed: markdown::Content::new(), + }; + + scrollable::snap_to( + "preview", + scrollable::RelativeOffset::END, + ) + } else { + self.mode = Mode::Preview( + markdown::parse(&self.content.text()).collect(), + ); + + Task::none() + } + } + Message::NextToken => { + match &mut self.mode { + Mode::Preview(_) => {} + Mode::Stream { pending, parsed } => { + if pending.is_empty() { + self.mode = Mode::Preview(parsed.items().to_vec()); + } else { + let mut tokens = pending.split(' '); + + if let Some(token) = tokens.next() { + parsed.push_str(&format!("{token} ")); + } + + *pending = tokens.collect::<Vec<_>>().join(" "); + } + } + } + + Task::none() } } } @@ -63,20 +121,49 @@ impl Markdown { .font(Font::MONOSPACE) .highlight("markdown", highlighter::Theme::Base16Ocean); + let items = match &self.mode { + Mode::Preview(items) => items.as_slice(), + Mode::Stream { parsed, .. } => parsed.items(), + }; + let preview = markdown( - &self.items, + items, markdown::Settings::default(), markdown::Style::from_palette(self.theme.palette()), ) .map(Message::LinkClicked); - row![editor, scrollable(preview).spacing(10).height(Fill)] - .spacing(10) - .padding(10) - .into() + row![ + editor, + hover( + scrollable(preview) + .spacing(10) + .width(Fill) + .height(Fill) + .id("preview"), + right( + toggler(matches!(self.mode, Mode::Stream { .. })) + .label("Stream") + .on_toggle(Message::ToggleStream) + ) + .padding([0, 20]) + ) + ] + .spacing(10) + .padding(10) + .into() } fn theme(&self) -> Theme { self.theme.clone() } + + fn subscription(&self) -> Subscription<Message> { + match self.mode { + Mode::Preview(_) => Subscription::none(), + Mode::Stream { .. } => { + time::every(milliseconds(20)).map(|_| Message::NextToken) + } + } + } } |