Skip to content

Commit

Permalink
chore: handle focus
Browse files Browse the repository at this point in the history
  • Loading branch information
nvh0412 committed Apr 20, 2024
1 parent e022057 commit 2aa0330
Show file tree
Hide file tree
Showing 9 changed files with 231 additions and 71 deletions.
81 changes: 70 additions & 11 deletions src/components/add_card.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use gpui::{
div, prelude::*, AnyView, ClickEvent, EventEmitter, Pixels, Render, View, ViewContext,
WindowContext,
div, prelude::*, AnyView, ClickEvent, EventEmitter, FocusHandle, Pixels, Render, View,
ViewContext, WindowContext,
};

use crate::{
Expand All @@ -17,10 +17,14 @@ pub struct AddCardView {
front_input: TextField,
back_input: TextField,
deck_input: TextField,
focus_handle: FocusHandle,
focused_at: usize,
}

impl EventEmitter<TabEvent> for AddCardView {}

const TABBALE_FIELDS: [&str; 3] = ["front", "back", "submit"];

impl AddCardView {
pub fn view(deck_id: u32, cx: &mut WindowContext) -> View<Self> {
cx.new_view(|cx: &mut gpui::ViewContext<'_, AddCardView>| {
Expand All @@ -30,17 +34,24 @@ impl AddCardView {
)
.unwrap();

let deck_input = TextField::new(cx, "".to_string());
let deck_input = TextField::new(cx, "".to_string(), true);

deck_input.view.update(cx, |view, _| {
view.text = deck.name.clone();
});

let front_input = TextField::new(cx, "".to_string(), false);
front_input.focus(cx);

let focus_handle = cx.focus_handle();

Self {
deck,
front_input: TextField::new(cx, "".to_string()),
back_input: TextField::new(cx, "".to_string()),
front_input,
back_input: TextField::new(cx, "".to_string(), false),
deck_input,
focused_at: 0,
focus_handle,
}
})
}
Expand All @@ -61,21 +72,74 @@ impl AddCardView {
}
}
}

fn save_key_down(&mut self, cx: &mut ViewContext<Self>) {
let collection = cx.global::<crate::Collection>();
let front = &self.front_input.view.read(&cx).text;
let back = &self.back_input.view.read(&cx).text;

let mut card =
repositories::flash_card::FlashCard::new(self.deck.id.unwrap(), front, back, None);
match card.save(&collection.storage.conn) {
Ok(_) => {
StackableViewState::update(|state, cx| state.pop(cx), cx);
}
Err(e) => {
log::error!("Error saving card: {:?}", e);
}
}
}
}

impl Render for AddCardView {
fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> impl gpui::prelude::IntoElement {
let view = cx.view().clone();
let theme = cx.global::<Theme>();

let mut submit_btn =
Button::new("create", "Create card", None).on_click(cx.listener(Self::save_click));

let focused_at = self.focused_at;
let front_input = self.front_input.clone();
let back_input = self.back_input.clone();

if self.focused_at == 2 {
submit_btn.focus();
}

div().flex().size_full().justify_center().child(
div().mt_20().child(
div()
.track_focus(&self.focus_handle)
.flex()
.w_full()
.flex_col()
.text_color(theme.text)
.relative()
.h_full()
.on_key_down(move |event, wc| {
view.update(wc, |add_view, vc| {
let keystroke = &event.keystroke.key;

match keystroke.as_str() {
"tab" => {
let next = (focused_at + 1) % TABBALE_FIELDS.len();

match TABBALE_FIELDS[next] {
"front" => front_input.focus(vc),
"back" => back_input.focus(vc),
"submit" => vc.focus(&add_view.focus_handle),
_ => {}
}
add_view.focused_at = next;
}
"enter" => {
add_view.save_key_down(vc);
}
_ => {}
}
});
})
.child(
div()
.w(Pixels(500.0))
Expand Down Expand Up @@ -111,12 +175,7 @@ impl Render for AddCardView {
.child("Back"),
)
.child(self.back_input.clone())
.child(
div().mt_5().flex().justify_end().child(
Button::new("create", "Create card", None)
.on_click(cx.listener(Self::save_click)),
),
),
.child(div().mt_5().flex().justify_end().child(submit_btn)),
),
),
),
Expand Down
77 changes: 54 additions & 23 deletions src/components/deck/deck_detail.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
use gpui::{
div, AnyView, FontWeight, IntoElement, ParentElement, Pixels, Render, Styled, ViewContext,
VisualContext, WindowContext,
div, AnyView, FocusHandle, FontWeight, InteractiveElement, IntoElement, KeyDownEvent,
ParentElement, Pixels, Render, Styled, ViewContext, VisualContext, WindowContext,
};

use crate::{
models::{
builder::Builder,
collection::{self, Collection, CollectionBuilder},
queue::QueueBuilder,
queue::{self, Queue, QueueBuilder},
},
repositories::deck::DeckStat,
state::{StackableView, StackableViewState},
Expand All @@ -19,21 +19,57 @@ use crate::{
use super::flash_card::FlashCardBuilder;

pub struct DeckDetail {
pub focus_handle: FocusHandle,
pub deck_id: u32,
pub queue: Queue,
}

impl DeckDetail {
pub fn view(deck_id: u32, cx: &mut WindowContext) -> AnyView {
cx.new_view(|_vc| Self { deck_id }).into()
let focus_handle = cx.focus_handle();
let col = cx.global::<collection::Collection>();

let mut queue_builder = QueueBuilder::new(deck_id);
queue_builder.collect_cards(&col);
let queue = queue_builder.build().unwrap();

cx.new_view(|_vc| Self {
deck_id,
focus_handle,
queue,
})
.into()
}

fn get_deck(&self, collection: &Collection) -> Deck {
Deck::load(self.deck_id, &collection.storage.conn).unwrap()
}

fn key_down(&mut self, event: &KeyDownEvent, cx: &mut ViewContext<Self>) {
match event.keystroke.key.as_str() {
"enter" | "space" => {
StackableViewState::update(
|state, cx| {
state.push(
FlashCardBuilder {
card_queue: &self.queue,
},
cx,
)
},
cx,
);

cx.notify();
}
_ => {}
};
}
}

impl Render for DeckDetail {
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
cx.focus(&self.focus_handle);
let theme = cx.global::<Theme>();
let col = cx.global::<collection::Collection>();
let mut deck = self.get_deck(col);
Expand All @@ -55,10 +91,6 @@ impl Render for DeckDetail {
});
}

let mut queue_builder = QueueBuilder::new(self.deck_id);
queue_builder.collect_cards(&col);
let card_queue = queue_builder.build().unwrap();

let stats = match deck.stats {
Some(stats) => stats,
None => DeckStat {
Expand All @@ -69,12 +101,25 @@ impl Render for DeckDetail {
},
};

let queue = self.queue.clone();

let mut study_btn = Button::new("study-btn", "Study Now", None).on_click(move |_e, cx| {
StackableViewState::update(
|state, cx| state.push(FlashCardBuilder { card_queue: &queue }, cx),
cx,
);
});

study_btn.focus();

div()
.track_focus(&self.focus_handle)
.flex()
.w_full()
.flex_col()
.pt_20()
.text_color(theme.text)
.on_key_down(cx.listener(Self::key_down))
.child(
div()
.flex()
Expand Down Expand Up @@ -127,21 +172,7 @@ impl Render for DeckDetail {
),
),
)
.child(div().mt_5().flex().justify_center().child(
Button::new("study-btn", "Study Now", None).on_click(move |_e, cx| {
StackableViewState::update(
|state, cx| {
state.push(
FlashCardBuilder {
card_queue: &card_queue,
},
cx,
)
},
cx,
);
}),
)),
.child(div().mt_5().flex().justify_center().child(study_btn)),
),
)
}
Expand Down
41 changes: 37 additions & 4 deletions src/components/deck/deck_list.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use std::fmt::format;

use gpui::{
div, AnchorCorner, AnyView, AppContext, Context, EventEmitter, FocusHandle, InteractiveElement,
IntoElement, KeyDownEvent, Model, ParentElement, Pixels, Render, RenderOnce, SharedString,
Expand All @@ -9,7 +7,7 @@ use gpui::{
use crate::{
components::{add_card::AddCardBuilder, shared::icon::Icon},
models::{
collection::{self, Collection, CollectionBuilder},
collection::{Collection, CollectionBuilder},
deck::get_decks,
},
repositories::deck::DeckStat,
Expand Down Expand Up @@ -55,7 +53,7 @@ impl DeckListView {
};

let view = cx.new_view(move |cx| {
cx.observe(&list.selected, move |this: &mut DeckListView, _, cx| {
cx.observe(&list.selected, move |_this: &mut DeckListView, _, cx| {
cx.notify();
})
.detach();
Expand Down Expand Up @@ -112,6 +110,41 @@ impl DeckListView {
cx.notify();
});
}
"tab" => {
let index = if let Some((index, _)) = self.selected(cx) {
let size = self.items.len() - 1;
if index < size {
index + 1
} else {
0
}
} else {
0
};

self.selected.update(cx, |this, cx| {
*this = self.items[index].id.unwrap();

cx.notify();
});
}
"enter" | "space" => {
if let Some((_index, deck)) = self.selected(cx) {
StackableViewState::update(
|state, cx| {
state.push(
DeckDetailBuilder {
deck_id: deck.id.unwrap(),
},
cx,
)
},
cx,
);

cx.notify();
}
}
_ => {}
}
}
Expand Down
Loading

0 comments on commit 2aa0330

Please sign in to comment.