Skip to content
Merged
431 changes: 331 additions & 100 deletions index.html

Large diffs are not rendered by default.

66 changes: 41 additions & 25 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,11 @@ use crate::utility::show_loading_spinner_custom;
use egui::Id;
use crate::db::github::{GithubDb, Repository};
use crate::db::idb::LANGUAGES;
use crate::erust::uiux::search::SearchWidget;
use crate::erust::state::{AppState, WaffleState};
use crate::erust::uiux::auth::AuthWidget;

#[derive(serde::Deserialize, serde::Serialize, Debug, Clone, PartialEq, Eq)]
pub enum AppState {
Init,
Normal,
Empty,
}

#[derive(serde::Deserialize, serde::Serialize, Debug, Clone)]
pub enum LoadingState {
Idle,
Loading {
Expand Down Expand Up @@ -58,9 +54,15 @@ pub struct TemplateApp {
#[serde(skip)]
pending_app_state: Option<AppState>,
#[serde(skip)]
waffle_state: WaffleState,
#[serde(skip)]
filtered_repos: Option<Vec<Repository>>,
#[serde(skip)]
filter_loading: bool,
#[serde(skip)]
search_widget: Option<SearchWidget>,
#[serde(skip)]
auth_widget: AuthWidget,
}

impl Default for TemplateApp {
Expand All @@ -77,8 +79,11 @@ impl Default for TemplateApp {
toast_timer: 0.0,
app_state: AppState::Init,
pending_app_state: None,
waffle_state: WaffleState::new(),
filtered_repos: None,
filter_loading: false,
search_widget: Some(SearchWidget::new()),
auth_widget: AuthWidget::new(false),
}
}
}
Expand Down Expand Up @@ -141,17 +146,10 @@ impl TemplateApp {
pub fn filter_repos_async(&mut self, query: &str, ctx: &egui::Context) {
self.filter_loading = true;
self.filtered_repos = None;
let query = query.to_string();
let language = self.db.get_language();
let ctx = ctx.clone(); // keep this, as it is used in the async block
wasm_bindgen_futures::spawn_local(async move {
let result = match crate::db::idb::open_waffle_db().await {
Ok(db_conn) => crate::db::idb::filter_repos_in_idb::<Repository>(&db_conn, &language, &query).await.unwrap_or_default(),
Err(_) => vec![],
};
ctx.data_mut(|d| d.insert_temp(Id::new("waffle_filtered_repos"), result));
ctx.request_repaint();
});
if let Some(widget) = &mut self.search_widget {
widget.query = query.to_string();
widget.search(&self.db.get_language(), ctx);
}
}

pub fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
Expand Down Expand Up @@ -300,6 +298,14 @@ impl TemplateApp {
let filtered = self.filtered_repos.as_ref().cloned().unwrap_or_default();
ui.separator();
ui.label(format!("Results: {}", filtered.len()));
// --- Show app state at the bottom ---
ui.separator();
ui.label(format!("App State: {:?}", self.waffle_state.app_state));
if !self.waffle_state.log.is_empty() {
ui.separator();
ui.label("App Log:");
ui.label(&self.waffle_state.log);
}
});
egui::CentralPanel::default().show(ctx, |ui| {
// --- Logo image loading and display using egui_extras loader system ---
Expand Down Expand Up @@ -337,16 +343,26 @@ impl TemplateApp {
}
});

// --- Authentication Widget (Login/Register) ---
egui::Window::new("Authentication")
.collapsible(false)
.resizable(false)
.anchor(egui::Align2::CENTER_TOP, egui::Vec2::new(0.0, 40.0))
.show(ctx, |ui| {
self.auth_widget.show(ctx, ui);
});

// Update filtered_repos from egui context temp data if available
if let Some(repos) = ctx.data(|d| d.get_temp::<Vec<Repository>>(Id::new("waffle_filtered_repos"))) {
let is_empty = repos.is_empty();
self.filtered_repos = Some(repos.clone());
// Set app_state based on whether there is data
if is_empty {
self.app_state = AppState::Empty;
if let Some(widget) = &mut self.search_widget {
widget.update_results_from_ctx(ctx);
// Use WaffleState to manage app state
if !widget.results.is_empty() {
self.waffle_state.set_ready(widget.results.clone());
} else {
self.app_state = AppState::Normal;
self.waffle_state.set_empty();
}
self.filtered_repos = Some(self.waffle_state.filtered_repos.clone());
self.app_state = self.waffle_state.app_state.clone();
}

// Show welcome dialog if DB is empty
Expand Down
1 change: 0 additions & 1 deletion src/core/mod.rs
Original file line number Diff line number Diff line change
@@ -1 +0,0 @@
pub mod uiux;
1 change: 0 additions & 1 deletion src/core/uiux/mod.rs
Original file line number Diff line number Diff line change
@@ -1 +0,0 @@
pub mod search;
41 changes: 0 additions & 41 deletions src/core/uiux/search.rs
Original file line number Diff line number Diff line change
@@ -1,41 +0,0 @@
use crate::db::github::Repository;
use crate::db::idb;
use egui::{Context, Id};

pub struct SearchWidget {
pub query: String,
pub results: Vec<Repository>,
pub loading: bool,
}

impl SearchWidget {
pub fn new() -> Self {
Self {
query: String::new(),
results: Vec::new(),
loading: false,
}
}

pub fn search(&mut self, language: &str, ctx: &Context) {
let query = self.query.clone();
let language = language.to_string();
let ctx = ctx.clone();
self.loading = true;
wasm_bindgen_futures::spawn_local(async move {
let result = match idb::open_waffle_db().await {
Ok(db_conn) => idb::filter_repos_in_idb::<Repository>(&db_conn, &language, &query).await.unwrap_or_default(),
Err(_) => vec![],
};
ctx.data_mut(|d| d.insert_temp(Id::new("waffle_search_results"), result));
ctx.request_repaint();
});
}

pub fn update_results_from_ctx(&mut self, ctx: &Context) {
if let Some(results) = ctx.data(|d| d.get_temp::<Vec<Repository>>(Id::new("waffle_search_results"))) {
self.results = results.clone();
self.loading = false;
}
}
}
2 changes: 2 additions & 0 deletions src/erust/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod uiux;
pub mod state;
24 changes: 19 additions & 5 deletions src/state.rs → src/erust/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,26 @@ use crate::db::github::Repository;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum AppState {
Init,
Normal,
Empty,
Syncing,
Normal,
Ready,
Error(String),
}

#[derive(Debug, Clone)]
pub struct WaffleState {
pub app_state: AppState,
pub filtered_repos: Vec<Repository>,
pub log: String,
}

impl WaffleState {
pub fn new() -> Self {
Self {
app_state: AppState::Init,
filtered_repos: Vec::new(),
log: String::new(),
}
}

Expand All @@ -27,21 +31,31 @@ impl WaffleState {
self.filtered_repos.clear();
}

pub fn set_normal(&mut self, repos: Vec<Repository>) {
pub fn set_syncing(&mut self) {
self.app_state = AppState::Syncing;
}

pub fn set_ready(&mut self, repos: Vec<Repository>) {
if repos.is_empty() {
self.set_empty();
} else {
self.app_state = AppState::Normal;
self.app_state = AppState::Ready;
self.filtered_repos = repos;
}
}

pub fn set_error(&mut self, msg: String) {
self.app_state = AppState::Error(msg);
self.app_state = AppState::Error(msg.clone());
self.log.push_str(&format!("Error: {}\n", msg));
self.filtered_repos.clear();
}

pub fn log(&mut self, msg: &str) {
self.log.push_str(msg);
self.log.push('\n');
}

pub fn is_ready(&self) -> bool {
matches!(self.app_state, AppState::Normal)
matches!(self.app_state, AppState::Ready)
}
}
Loading
Loading