Skip to content

Commit c3dd527

Browse files
committed
Merge branch 'dev'
2 parents 52a75c0 + 0b41044 commit c3dd527

File tree

17 files changed

+562
-299
lines changed

17 files changed

+562
-299
lines changed

CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,18 @@ All notable changes to this project will be documented in this file.
2222

2323
- Invalidate questions cache through `userSessionProgress`
2424

25+
## [0.2.1] - [Unreleased]
26+
27+
### Added
28+
29+
- Neetcode 75 question list.
30+
31+
### Changed
32+
33+
- Not null constraints on the fields that are never null from the server.
34+
- `QuestionModelContainer { question: RefCell<QuestionModel> }` changed to `Rc<RefCell<QuestionModel>>`
35+
- As prior implemented hash. Hashables should not be mutable.
36+
2537
## [0.2.0] - 2023-07-30
2638

2739
### Added

src/app_ui/async_task_channel.rs

Lines changed: 50 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -22,47 +22,37 @@ pub enum TaskRequest {
2222
DbUpdateQuestion(Request<QuestionModel>),
2323
}
2424

25-
impl TaskRequest {
26-
pub async fn execute(
27-
self,
28-
client: &reqwest::Client,
29-
conn: &DatabaseConnection,
30-
) -> TaskResponse {
31-
match self {
32-
TaskRequest::QuestionDetail(Request {
33-
content: slug,
34-
widget_name,
35-
request_id,
36-
}) => get_question_details(request_id, widget_name, slug, client).await,
37-
TaskRequest::GetAllQuestionsMap(Request {
38-
widget_name,
39-
request_id,
40-
..
41-
}) => get_all_questions(request_id, widget_name, conn).await,
42-
TaskRequest::GetAllTopicTags(Request {
43-
widget_name,
44-
request_id,
45-
..
46-
}) => get_all_topic_tags(request_id, widget_name, conn).await,
47-
TaskRequest::GetQuestionEditorData(Request {
48-
request_id,
49-
content,
50-
widget_name,
51-
}) => get_editor_data(request_id, widget_name, content, client).await,
52-
TaskRequest::CodeRunRequest(Request {
53-
request_id,
54-
content,
55-
widget_name,
56-
}) => run_or_submit_question(request_id, widget_name, content, client).await,
57-
TaskRequest::DbUpdateQuestion(Request {
58-
request_id,
59-
content,
60-
widget_name,
61-
}) => update_status_to_accepted(request_id, widget_name, content, conn).await,
25+
macro_rules! impl_task_request {
26+
($(($var:ident, $f_name: ident)),*) => {
27+
impl TaskRequest {
28+
pub async fn execute(
29+
self,
30+
client: &reqwest::Client,
31+
conn: &DatabaseConnection,
32+
) -> TaskResponse {
33+
match self {
34+
$(
35+
TaskRequest::$var(Request {
36+
content,
37+
widget_name,
38+
request_id,
39+
}) => $f_name(request_id, widget_name, content, client, conn).await,
40+
)*
41+
}
42+
}
6243
}
63-
}
44+
};
6445
}
6546

47+
impl_task_request!(
48+
(QuestionDetail, get_question_details),
49+
(GetAllQuestionsMap, get_all_questions),
50+
(GetAllTopicTags, get_all_topic_tags),
51+
(GetQuestionEditorData, get_editor_data),
52+
(CodeRunRequest, run_or_submit_question),
53+
(DbUpdateQuestion, update_status_to_accepted)
54+
);
55+
6656
#[derive(Debug)]
6757
pub struct Response<T> {
6858
pub(crate) request_id: String,
@@ -81,21 +71,31 @@ pub enum TaskResponse {
8171
Error(Response<String>),
8272
}
8373

84-
impl TaskResponse {
85-
pub fn get_widget_name(&self) -> WidgetName {
86-
match self {
87-
TaskResponse::QuestionDetail(Response { widget_name, .. }) => widget_name,
88-
TaskResponse::GetAllQuestionsMap(Response { widget_name, .. }) => widget_name,
89-
TaskResponse::AllTopicTags(Response { widget_name, .. }) => widget_name,
90-
TaskResponse::Error(Response { widget_name, .. }) => widget_name,
91-
TaskResponse::QuestionEditorData(Response { widget_name, .. }) => widget_name,
92-
TaskResponse::RunResponseData(Response { widget_name, .. }) => widget_name,
93-
TaskResponse::DbUpdateStatus(Response { widget_name, .. }) => widget_name,
74+
macro_rules! impl_task_response {
75+
($($variant:ident),*) => {
76+
impl TaskResponse {
77+
pub fn get_widget_name(&self) -> WidgetName {
78+
match self {
79+
$(
80+
TaskResponse::$variant(Response { widget_name, .. }) => widget_name,
81+
)*
82+
}
83+
.clone()
84+
}
9485
}
95-
.clone()
96-
}
86+
};
9787
}
9888

89+
impl_task_response!(
90+
QuestionDetail,
91+
GetAllQuestionsMap,
92+
AllTopicTags,
93+
QuestionEditorData,
94+
RunResponseData,
95+
DbUpdateStatus,
96+
Error
97+
);
98+
9999
pub type ChannelRequestSender = tokio::sync::mpsc::UnboundedSender<TaskRequest>;
100100
pub type ChannelRequestReceiver = tokio::sync::mpsc::UnboundedReceiver<TaskRequest>;
101101

src/app_ui/components/list.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
use ratatui::widgets::ListState;
2-
use std::rc::Rc;
32

43
#[derive(Debug, Clone)]
54
pub struct StatefulList<T> {
65
pub state: ListState,
7-
pub items: Vec<Rc<T>>,
6+
pub items: Vec<T>,
87
}
98

109
impl<T> Default for StatefulList<T> {
@@ -21,10 +20,10 @@ impl<T> StatefulList<T> {
2120
if self.items.is_empty() {
2221
self.state.select(Some(0))
2322
}
24-
self.items.push(Rc::new(item))
23+
self.items.push(item)
2524
}
2625

27-
pub fn get_selected_item(&self) -> Option<&Rc<T>> {
26+
pub fn get_selected_item(&self) -> Option<&T> {
2827
match self.state.selected() {
2928
Some(i) => Some(&self.items[i]),
3029
None => None,
@@ -38,7 +37,7 @@ impl<T> StatefulList<T> {
3837
}
3938
StatefulList {
4039
state: list_state,
41-
items: items.into_iter().map(|item| Rc::new(item)).collect(),
40+
items,
4241
}
4342
}
4443

src/app_ui/components/popups/selection_list.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ impl Component for SelectionListPopup {
6060
.items
6161
.iter()
6262
.map(|item| {
63-
let line_text = item.as_ref();
63+
let line_text = item;
6464
ListItem::new(Span::styled(line_text, Style::default()))
6565
})
6666
.collect::<Vec<_>>();

src/app_ui/helpers/question.rs

Lines changed: 5 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,9 @@
11
use std::{cell::RefCell, rc::Rc};
22

33
use crate::entities::QuestionModel;
4-
use std::hash::Hash;
5-
6-
#[derive(PartialEq, Eq, Debug, Ord, PartialOrd)]
7-
pub struct QuestionModelContainer {
8-
pub question: RefCell<QuestionModel>,
9-
}
10-
11-
// RefCell keys are mutable and should not be used in types where hashing
12-
// is required. This implementation is valid until question_frontend_id change.
13-
// For more refer https://rust-lang.github.io/rust-clippy/master/index.html#/mutable_key_type
14-
impl Hash for QuestionModelContainer {
15-
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
16-
self.question.borrow().hash(state)
17-
}
18-
}
194

205
pub struct Stats<'a> {
21-
pub qm: &'a Vec<Rc<QuestionModelContainer>>,
6+
pub qm: &'a Vec<Rc<RefCell<QuestionModel>>>,
227
}
238

249
impl<'a> Stats<'a> {
@@ -66,12 +51,8 @@ impl<'a> Stats<'a> {
6651
self.qm
6752
.iter()
6853
.filter(|q| {
69-
if let Some(st) = &q.question.borrow().status {
70-
if let Some(at) = &q.question.borrow().difficulty {
71-
st.as_str() == status && difficulty == at.as_str()
72-
} else {
73-
false
74-
}
54+
if let Some(st) = &q.borrow().status {
55+
st.as_str() == status && difficulty == q.borrow().difficulty.as_str()
7556
} else {
7657
false
7758
}
@@ -83,7 +64,7 @@ impl<'a> Stats<'a> {
8364
self.qm
8465
.iter()
8566
.filter(|q| {
86-
if let Some(st) = &q.question.borrow().status {
67+
if let Some(st) = &q.borrow().status {
8768
st.as_str() == status
8869
} else {
8970
false
@@ -95,13 +76,7 @@ impl<'a> Stats<'a> {
9576
fn get_diff_count(&self, difficulty: &str) -> usize {
9677
self.qm
9778
.iter()
98-
.filter(|q| {
99-
if let Some(diff) = &q.question.borrow().difficulty {
100-
diff.as_str() == difficulty
101-
} else {
102-
false
103-
}
104-
})
79+
.filter(|q| q.borrow().difficulty.as_str() == difficulty)
10580
.count()
10681
}
10782
}

src/app_ui/helpers/tasks.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@ pub async fn get_question_details(
1313
widget_name: WidgetName,
1414
slug: String,
1515
client: &reqwest::Client,
16+
_conn: &DatabaseConnection,
1617
) -> TaskResponse {
17-
match QuestionGQLQuery::new(slug).post(client).await {
18+
match QuestionGQLQuery::new(slug).send(client).await {
1819
Ok(resp) => {
1920
let query_response = resp;
2021
TaskResponse::QuestionDetail(Response {
@@ -36,8 +37,9 @@ pub async fn get_editor_data(
3637
widget_name: WidgetName,
3738
slug: String,
3839
client: &reqwest::Client,
40+
_conn: &DatabaseConnection,
3941
) -> TaskResponse {
40-
match QuestionEditorDataQuery::new(slug).post(client).await {
42+
match QuestionEditorDataQuery::new(slug).send(client).await {
4143
Ok(data) => TaskResponse::QuestionEditorData(Response {
4244
request_id,
4345
content: data.data.question,
@@ -54,6 +56,8 @@ pub async fn get_editor_data(
5456
pub async fn get_all_questions(
5557
request_id: String,
5658
widget_name: WidgetName,
59+
_content: (),
60+
_client: &reqwest::Client,
5761
conn: &DatabaseConnection,
5862
) -> TaskResponse {
5963
match TopicTagEntity::get_all_topic_questions_map(conn).await {
@@ -73,6 +77,8 @@ pub async fn get_all_questions(
7377
pub async fn get_all_topic_tags(
7478
request_id: String,
7579
widget_name: WidgetName,
80+
_content: (),
81+
_client: &reqwest::Client,
7682
conn: &DatabaseConnection,
7783
) -> TaskResponse {
7884
match TopicTagEntity::get_all_topics(conn).await {
@@ -94,6 +100,7 @@ pub async fn run_or_submit_question(
94100
widget_name: WidgetName,
95101
mut run_or_submit_code: graphql::RunOrSubmitCode,
96102
client: &reqwest::Client,
103+
_conn: &DatabaseConnection,
97104
) -> TaskResponse {
98105
if let RunOrSubmitCode::Run(RunCode {
99106
test_cases_stdin,
@@ -102,7 +109,7 @@ pub async fn run_or_submit_question(
102109
}) = &mut run_or_submit_code
103110
{
104111
match graphql::console_panel_config::Query::new(slug.clone())
105-
.post(client)
112+
.send(client)
106113
.await
107114
{
108115
Ok(resp) => {
@@ -136,6 +143,7 @@ pub async fn update_status_to_accepted(
136143
request_id: String,
137144
widget_name: WidgetName,
138145
question: QuestionModel,
146+
_client: &reqwest::Client,
139147
db: &DatabaseConnection,
140148
) -> TaskResponse {
141149
let mut am = question.into_active_model();

src/app_ui/widgets/notification.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
1-
use std::rc::Rc;
1+
use std::{cell::RefCell, rc::Rc};
22

3-
use crate::app_ui::helpers::question::QuestionModelContainer;
43
use crate::{
54
app_ui::components::{
65
help_text::HelpText,
76
popups::{paragraph::ParagraphPopup, selection_list::SelectionListPopup},
87
},
9-
entities::TopicTagModel,
8+
entities::{QuestionModel, TopicTagModel},
109
};
1110

1211
#[derive(Debug, Clone)]
@@ -54,7 +53,7 @@ impl<T> NotifContent<T> {
5453
#[derive(Debug, Clone)]
5554
pub enum Notification {
5655
Questions(NotifContent<Vec<TopicTagModel>>),
57-
Stats(NotifContent<Vec<Rc<QuestionModelContainer>>>),
56+
Stats(NotifContent<Vec<Rc<RefCell<QuestionModel>>>>),
5857
Popup(NotifContent<PopupMessage>),
5958
HelpText(NotifContent<IndexSet<HelpText>>),
6059
Event(NotifContent<KeyEvent>),

0 commit comments

Comments
 (0)