From 852d17e30cb44a75cabe6d0462499c236d0b2853 Mon Sep 17 00:00:00 2001 From: bigfoodk Date: Mon, 28 Oct 2024 03:53:01 +0900 Subject: [PATCH 1/2] Add text editor for character line --- .../new-client/src/episode_editor/mod.rs | 1 + .../src/episode_editor/text_editor.rs | 66 +++++++++++++++---- 2 files changed, 54 insertions(+), 13 deletions(-) diff --git a/luda-editor/new-client/src/episode_editor/mod.rs b/luda-editor/new-client/src/episode_editor/mod.rs index 9a1508428..b2dffa5e4 100644 --- a/luda-editor/new-client/src/episode_editor/mod.rs +++ b/luda-editor/new-client/src/episode_editor/mod.rs @@ -321,6 +321,7 @@ impl Component for LoadedEpisodeEditor<'_> { ctx.add(text_editor::TextEditor { wh, text, + scene_id: &scene.id, on_edit_done: on_text_edit_done, }); }), diff --git a/luda-editor/new-client/src/episode_editor/text_editor.rs b/luda-editor/new-client/src/episode_editor/text_editor.rs index a55935d3c..d20158276 100644 --- a/luda-editor/new-client/src/episode_editor/text_editor.rs +++ b/luda-editor/new-client/src/episode_editor/text_editor.rs @@ -3,6 +3,7 @@ use namui::*; pub struct TextEditor<'a> { pub wh: Wh, pub text: &'a String, + pub scene_id: &'a String, pub on_edit_done: &'a dyn Fn(String), } @@ -11,22 +12,61 @@ impl Component for TextEditor<'_> { let Self { wh, text, + scene_id, on_edit_done, } = self; - ctx.add(text_input::TextInput { - rect: Rect::zero_wh(wh), - start_text: text, - text_align: TextAlign::Left, - text_baseline: TextBaseline::Top, - font: Font { - size: 16.int_px(), - name: "NotoSansKR-Regular".to_string(), - }, - style: Default::default(), - prevent_default_codes: &[], - focus: None, - on_edit_done, + let start_text = ctx.track_eq(text); + let (delayed_update, set_delayed_update) = ctx.state::>(|| None); + + ctx.interval("text edit observer", 250.ms(), |_| { + let Some((updated_at, text)) = delayed_update.as_ref() else { + return; + }; + if time::now() - updated_at < 1.sec() { + return; + } + on_edit_done(text.to_string()); + set_delayed_update.set(None); + }); + + ctx.compose(|ctx| { + ctx.add_with_key( + scene_id.clone(), + text_input::TextInput { + rect: Rect::zero_wh(wh), + start_text: start_text.as_ref(), + text_align: TextAlign::Left, + text_baseline: TextBaseline::Top, + font: Font { + size: 16.int_px(), + name: "NotoSansKR-Regular".to_string(), + }, + style: text_input::Style { + rect: RectStyle { + stroke: Some(RectStroke { + border_position: BorderPosition::Inside, + color: Color::from_u8(0xEE, 0xEE, 0xEE, 0xFF), + width: px(1.0), + }), + fill: Some(RectFill { + color: Color::from_u8(0x44, 0x44, 0x44, 0xFF), + }), + ..Default::default() + }, + text: namui::TextStyle { + color: namui::Color::WHITE, + ..Default::default() + }, + padding: Ltrb::all(8.px()), + }, + prevent_default_codes: &[Code::Enter], + focus: None, + on_edit_done: &|text| { + set_delayed_update.set(Some((time::now(), text.clone()))); + }, + }, + ); }); } } From 155fc588354bfcfad31285e836fe1a6cf9652e28 Mon Sep 17 00:00:00 2001 From: bigfoodk Date: Mon, 28 Oct 2024 04:21:13 +0900 Subject: [PATCH 2/2] Update previous editing text on scene chage --- .../new-client/src/episode_editor/mod.rs | 5 +- .../src/episode_editor/text_editor.rs | 57 ++++++++++++++++--- 2 files changed, 51 insertions(+), 11 deletions(-) diff --git a/luda-editor/new-client/src/episode_editor/mod.rs b/luda-editor/new-client/src/episode_editor/mod.rs index b2dffa5e4..10c1167d1 100644 --- a/luda-editor/new-client/src/episode_editor/mod.rs +++ b/luda-editor/new-client/src/episode_editor/mod.rs @@ -272,10 +272,9 @@ impl Component for LoadedEpisodeEditor<'_> { }); }; - let on_text_edit_done = &|text: String| { - let Some(scene) = scene else { return }; + let on_text_edit_done = &|scene_id: String, text: String| { edit_episode(EpisodeEditAction::EditText { - scene_id: scene.id.clone(), + scene_id, language_code: "kor".to_string(), text, }); diff --git a/luda-editor/new-client/src/episode_editor/text_editor.rs b/luda-editor/new-client/src/episode_editor/text_editor.rs index d20158276..db67f84eb 100644 --- a/luda-editor/new-client/src/episode_editor/text_editor.rs +++ b/luda-editor/new-client/src/episode_editor/text_editor.rs @@ -4,7 +4,7 @@ pub struct TextEditor<'a> { pub wh: Wh, pub text: &'a String, pub scene_id: &'a String, - pub on_edit_done: &'a dyn Fn(String), + pub on_edit_done: &'a dyn Fn(String, String), } impl Component for TextEditor<'_> { @@ -16,26 +16,57 @@ impl Component for TextEditor<'_> { on_edit_done, } = self; - let start_text = ctx.track_eq(text); - let (delayed_update, set_delayed_update) = ctx.state::>(|| None); + let scene_id = ctx.track_eq(scene_id); + + let (last_updated, set_last_updated) = ctx.state(|| text.clone()); + let (delayed_update, set_delayed_update) = ctx.state::>(|| None); + + let delayed_update = delayed_update.as_ref(); + let last_updated = last_updated.as_ref(); + ctx.effect("update previous scene text if needed", { + || { + scene_id.record_as_used(); + let Some(DelayedUpdate { scene_id, text, .. }) = delayed_update else { + return; + }; + if last_updated == text { + return; + } + on_edit_done(scene_id.to_string(), text.to_string()); + set_delayed_update.set(None); + } + }); + + ctx.effect("init last updated", { + || { + scene_id.record_as_used(); + set_last_updated.set(text.to_string()); + } + }); ctx.interval("text edit observer", 250.ms(), |_| { - let Some((updated_at, text)) = delayed_update.as_ref() else { + let Some(DelayedUpdate { + updated_at, + scene_id, + text, + }) = delayed_update + else { return; }; if time::now() - updated_at < 1.sec() { return; } - on_edit_done(text.to_string()); + on_edit_done(scene_id.to_string(), text.to_string()); + set_last_updated.set(text.to_string()); set_delayed_update.set(None); }); ctx.compose(|ctx| { ctx.add_with_key( - scene_id.clone(), + scene_id.to_string(), text_input::TextInput { rect: Rect::zero_wh(wh), - start_text: start_text.as_ref(), + start_text: text.as_ref(), text_align: TextAlign::Left, text_baseline: TextBaseline::Top, font: Font { @@ -63,10 +94,20 @@ impl Component for TextEditor<'_> { prevent_default_codes: &[Code::Enter], focus: None, on_edit_done: &|text| { - set_delayed_update.set(Some((time::now(), text.clone()))); + set_delayed_update.set(Some(DelayedUpdate { + updated_at: time::now(), + scene_id: scene_id.to_string(), + text, + })); }, }, ); }); } } + +struct DelayedUpdate { + updated_at: Instant, + scene_id: String, + text: String, +}