Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
146 changes: 141 additions & 5 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
/>

<head>
<!-- change this to your project name -->
<title>Waffle - Template</title>

<!-- config for our rust wasm binary. go to https://trunkrs.dev/assets/#rust for more customization -->
Expand All @@ -26,6 +25,43 @@

<script type="module">
import createWorker from "https://esm.sh/@supabase/supabase-js?worker";
import { createClient } from "https://esm.sh/@supabase/supabase-js";

(async () => {
window.sb = createClient(
"https://qmpdruitzlownnnnjmpk.supabase.co",
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InFtcGRydWl0emxvd25ubm5qbXBrIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NDk2NjA0NTYsImV4cCI6MjA2NTIzNjQ1Nn0.OhD3qN4dq0TMA65qVGvry_QsZEeLKK7RbwYP3QzAvcY"
);

const {
data: { session },
} = await window.sb.auth.getSession();

if (session) {
let retries = 50;
while (!window.supabase?.worker && retries-- > 0) {
await new Promise((r) => setTimeout(r, 100));
}

if (window.supabase?.worker) {
console.log("[Main] Session detected, syncing to worker...");

window.supabase.worker.postMessage({
id: `session_sync`,
action: "setSession",
payload: {
access_token: session.access_token,
refresh_token: session.refresh_token,
},
});
} else {
console.log("[Main] Worker not found.");
}
}
else {
console.log("[Main] No session found — user is logged out.");
}
})();

// Create the worker
(async () => {
Expand All @@ -34,7 +70,13 @@
inject: `
const supabase = $module.createClient(
"https://qmpdruitzlownnnnjmpk.supabase.co",
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InFtcGRydWl0emxvd25ubm5qbXBrIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NDk2NjA0NTYsImV4cCI6MjA2NTIzNjQ1Nn0.OhD3qN4dq0TMA65qVGvry_QsZEeLKK7RbwYP3QzAvcY"
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InFtcGRydWl0emxvd25ubm5qbXBrIiwicm9zZSI6ImFub24iLCJpYXQiOjE3NDk2NjA0NTYsImV4cCI6MjA2NTIzNjQ1Nn0.OhD3qN4dq0TMA65qVGvry_QsZEeLKK7RbwYP3QzAvcY",
{
auth: {
detectSessionInUrl: false,
persistSession: false,
}
}
);

self.onmessage = async (e) => {
Expand All @@ -59,18 +101,23 @@
password: payload.password,
options: { captchaToken: payload.captchaToken }
});
console.log("[Worker] Login result:", result);

break;

case "logout":
result = await supabase.auth.signOut();
console.log("[Worker] Logout result:", result);
break;

case "session":
result = await supabase.auth.getSession();
console.log("[Worker] Session:", result);
break;

case "getUser":
result = await supabase.auth.getUser();
console.log("[Worker] User:", result);
break;

case "getProfile":
Expand All @@ -81,7 +128,13 @@
.single();
result = { data, error };
break;

case "setSession":
result = await supabase.auth.setSession({
access_token: payload.access_token,
refresh_token: payload.refresh_token
});
console.log("[Worker] Session set via setSession:", result);
break;
default:
throw new Error(\`Unknown action: \${action}\`);
}
Expand Down Expand Up @@ -133,6 +186,8 @@
session: () => sendToWorker("session", {}),
getUser: () => sendToWorker("getUser", {}),
getProfile: (user_id) => sendToWorker("getProfile", { user_id }),
setSession: () => sendToWorker("setSession", {session}),
worker: supabaseWorker,
};

console.log("[JS]: Supabase worker initialized and ready.");
Expand Down Expand Up @@ -324,11 +379,18 @@
></div>
<button
onclick="closeCaptcha()"
style="margin-top: 16px"
style="margin-top: 16px; margin-right: 8px;"
class="px-4 py-2 bg-red-600 hover:bg-red-700 text-white rounded shadow transition-colors duration-150"
>
Cancel
</button>
<button
onclick="resetCaptcha()"
style="margin-top: 16px;"
class="px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded shadow transition-colors duration-150"
>
Reset Captcha
</button>
</div>
</div>
<script>
Expand All @@ -355,6 +417,7 @@
break;
case "register":
console.log("[DEBUG]: Called Registered Here");
resetCaptcha();
if (
message &&
message.email &&
Expand Down Expand Up @@ -399,18 +462,77 @@
}
break;
case "login":
console.log("[DEBUG]: Called Login Here");
resetCaptcha();
if (
message &&
message.email &&
message.password &&
message.captcha_token
) {
window.sb.auth
.signInWithPassword({
email: message.email,
password: message.password,
options: {
captchaToken: message.captcha_token,
},
})
.then((resp) => {
const session = resp.data?.session;
console.log("[DEBUG]: LOGIN -> THEN PLACEHOLDER");

// Forward session to the worker if login was successful
if (
session &&
session.access_token &&
session.refresh_token
) {
window.supabase.worker.postMessage({
id: `sync_session_${Date.now()}`,
action: "setSession",
payload: {
access_token: session.access_token,
refresh_token: session.refresh_token,
},
});
}

if (window.JSRustResponseHandler) {
window.JSRustResponseHandler(resp);
}
})
.catch((err) => {
console.error("[ERROR]: Login failed:", err);

if (window.JSRustResponseHandler) {
window.JSRustResponseHandler({
success: false,
error: err.message || "Unexpected login error",
});
}
});
} else {
console.warn("[WARN]: Incomplete login message:", message);
if (window.JSRustResponseHandler) {
window.JSRustResponseHandler({
success: false,
error: "Missing email, password, or captcha_token",
});
}
}
break;
case "logout":
if (window.supabase && window.supabase.logout) {
window.supabase
.login(message.email, message.password, message.captcha_token)
.logout()
.then((resp) => {
if (window.JSRustResponseHandler) {
window.JSRustResponseHandler(resp);
}
})
.catch((err) => {
console.error("[ERROR]: logout call failed", err);
});
}
break;
Expand All @@ -419,6 +541,9 @@
console.log("[JSRust]", message);
}
break;
case "resetCaptcha":
resetCaptcha();
break;
// Add more actions as needed
default:
console.warn("[JSRust] Unknown action:", action, message);
Expand Down Expand Up @@ -452,6 +577,17 @@
);
}
};

function resetCaptcha() {
if (window.hcaptcha) {
window.hcaptcha.reset();
} else {
const widget = document.querySelector(".h-captcha");
if (widget && widget.reset) {
widget.reset();
}
}
}
</script>
<!-- End hCaptcha integration -->
</body>
Expand Down
62 changes: 52 additions & 10 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::db::idb::LANGUAGES;
use crate::erust::uiux::search::SearchWidget;
use crate::erust::state::{AppState, WaffleState};
use crate::erust::uiux::auth::AuthWidget;
use crate::erust::uiux::user::User;

#[derive(serde::Deserialize, serde::Serialize, Debug, Clone, PartialEq, Eq)]
pub enum LoadingState {
Expand Down Expand Up @@ -63,6 +64,12 @@ pub struct TemplateApp {
search_widget: Option<SearchWidget>,
#[serde(skip)]
auth_widget: AuthWidget,
#[serde(skip)]
user: User,
#[serde(skip)]
show_auth_window: bool, // Track if auth window should be shown
#[serde(skip)]
show_welcome: bool, // Track if welcome window should be shown
}

impl Default for TemplateApp {
Expand All @@ -84,6 +91,9 @@ impl Default for TemplateApp {
filter_loading: false,
search_widget: Some(SearchWidget::new()),
auth_widget: AuthWidget::new(false),
user: User::default(),
show_auth_window: false,
show_welcome: true, // Show welcome window by default
}
}
}
Expand Down Expand Up @@ -306,6 +316,17 @@ impl TemplateApp {
ui.label("App Log:");
ui.label(&self.waffle_state.log);
}
// Add Login/Register buttons if not authenticated
if !self.user.is_logged_in() {
if ui.button("Login").clicked() {
self.auth_widget.view = crate::erust::uiux::auth::AuthView::Login;
self.show_auth_window = true;
}
if ui.button("Register").clicked() {
self.auth_widget.view = crate::erust::uiux::auth::AuthView::Register;
self.show_auth_window = true;
}
}
});
egui::CentralPanel::default().show(ctx, |ui| {
// --- Logo image loading and display using egui_extras loader system ---
Expand Down Expand Up @@ -343,15 +364,6 @@ 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(widget) = &mut self.search_widget {
widget.update_results_from_ctx(ctx);
Expand All @@ -366,16 +378,46 @@ impl TemplateApp {
}

// Show welcome dialog if DB is empty
if self.app_state == AppState::Empty {
if self.app_state == AppState::Empty && self.show_welcome {
egui::Window::new("Welcome to the Waffle!")
.collapsible(false)
.resizable(false)
.anchor(egui::Align2::CENTER_CENTER, egui::Vec2::ZERO)
.open(&mut self.show_welcome)
.show(ctx, |ui| {
ui.heading("Welcome to the Waffle!");
ui.label("Please sync the languages you would like to see.");
});
}

// --- Always-visible bottom panel with Logout button ---
egui::TopBottomPanel::bottom("bottom_panel").show(ctx, |ui| {
ui.horizontal(|ui| {
if ui.button("Logout").clicked() {
crate::erust::uiux::javascript_interop::send_action_message(
"logout",
"",
"",
"",
);
self.toast_message = Some("Sent logout request to JS".to_string());
}
ui.label("Waffle v0.1.0");
});
});

// --- Authentication Widget (Login/Register) ---
// Only show the authentication window if user is not logged in and show_auth_window is true
if !self.user.is_logged_in() && self.show_auth_window {
egui::Window::new("Authentication")
.collapsible(false)
.resizable(false)
.anchor(egui::Align2::CENTER_TOP, egui::Vec2::new(0.0, 40.0))
.open(&mut self.show_auth_window) // Adds the X close button
.show(ctx, |ui| {
self.auth_widget.show(ctx, ui);
});
}
}
}

Expand Down
Empty file removed src/core/mod.rs
Empty file.
Empty file removed src/core/uiux/mod.rs
Empty file.
Empty file removed src/core/uiux/search.rs
Empty file.
Loading
Loading