mirror of
https://github.com/johrpan/musicus.git
synced 2025-10-26 19:57:25 +01:00
Add registration dialog
This commit is contained in:
parent
c9d9c1bc24
commit
1f90f6108e
9 changed files with 530 additions and 22 deletions
|
|
@ -15,6 +15,7 @@
|
||||||
<file preprocess="xml-stripblanks">ui/preferences.ui</file>
|
<file preprocess="xml-stripblanks">ui/preferences.ui</file>
|
||||||
<file preprocess="xml-stripblanks">ui/recording_editor.ui</file>
|
<file preprocess="xml-stripblanks">ui/recording_editor.ui</file>
|
||||||
<file preprocess="xml-stripblanks">ui/recording_screen.ui</file>
|
<file preprocess="xml-stripblanks">ui/recording_screen.ui</file>
|
||||||
|
<file preprocess="xml-stripblanks">ui/register_dialog.ui</file>
|
||||||
<file preprocess="xml-stripblanks">ui/selector.ui</file>
|
<file preprocess="xml-stripblanks">ui/selector.ui</file>
|
||||||
<file preprocess="xml-stripblanks">ui/server_dialog.ui</file>
|
<file preprocess="xml-stripblanks">ui/server_dialog.ui</file>
|
||||||
<file preprocess="xml-stripblanks">ui/source_selector.ui</file>
|
<file preprocess="xml-stripblanks">ui/source_selector.ui</file>
|
||||||
|
|
|
||||||
|
|
@ -47,38 +47,84 @@
|
||||||
<property name="margin-end">12</property>
|
<property name="margin-end">12</property>
|
||||||
<property name="margin-top">18</property>
|
<property name="margin-top">18</property>
|
||||||
<property name="margin-bottom">12</property>
|
<property name="margin-bottom">12</property>
|
||||||
<property name="maximum-size">500</property>
|
<property name="maximum-size">800</property>
|
||||||
<property name="tightening-threshold">300</property>
|
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkFrame">
|
<object class="GtkBox">
|
||||||
<property name="valign">start</property>
|
<property name="orientation">vertical</property>
|
||||||
|
<property name="spacing">12</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkListBox">
|
<object class="GtkLabel">
|
||||||
<property name="selection-mode">none</property>
|
<property name="halign">start</property>
|
||||||
|
<property name="label" translatable="yes">Login to existing account</property>
|
||||||
|
<attributes>
|
||||||
|
<attribute name="weight" value="bold"/>
|
||||||
|
</attributes>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkFrame">
|
||||||
|
<property name="valign">start</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="AdwActionRow">
|
<object class="GtkListBox">
|
||||||
<property name="activatable">True</property>
|
<property name="selection-mode">none</property>
|
||||||
<property name="title" translatable="yes">Username</property>
|
|
||||||
<property name="activatable-widget">username_entry</property>
|
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkEntry" id="username_entry">
|
<object class="AdwActionRow">
|
||||||
<property name="valign">center</property>
|
<property name="activatable">True</property>
|
||||||
<property name="hexpand">True</property>
|
<property name="title" translatable="yes">Username</property>
|
||||||
|
<property name="activatable-widget">username_entry</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkEntry" id="username_entry">
|
||||||
|
<property name="valign">center</property>
|
||||||
|
<property name="hexpand">True</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="AdwActionRow">
|
||||||
|
<property name="activatable">True</property>
|
||||||
|
<property name="title" translatable="yes">Password</property>
|
||||||
|
<property name="activatable-widget">password_entry</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkEntry" id="password_entry">
|
||||||
|
<property name="valign">center</property>
|
||||||
|
<property name="hexpand">True</property>
|
||||||
|
<property name="visibility">False</property>
|
||||||
|
<property name="input-purpose">password</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel">
|
||||||
|
<property name="halign">start</property>
|
||||||
|
<property name="label" translatable="yes">Create a new account</property>
|
||||||
|
<attributes>
|
||||||
|
<attribute name="weight" value="bold"/>
|
||||||
|
</attributes>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkFrame">
|
||||||
|
<property name="valign">start</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="AdwActionRow">
|
<object class="GtkListBox">
|
||||||
<property name="activatable">True</property>
|
<property name="selection-mode">none</property>
|
||||||
<property name="title" translatable="yes">Password</property>
|
|
||||||
<property name="activatable-widget">password_entry</property>
|
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkEntry" id="password_entry">
|
<object class="AdwActionRow">
|
||||||
<property name="valign">center</property>
|
<property name="activatable">True</property>
|
||||||
<property name="hexpand">True</property>
|
<property name="title" translatable="yes">Register a new account</property>
|
||||||
<property name="visibility">False</property>
|
<property name="activatable-widget">register_button</property>
|
||||||
<property name="input-purpose">password</property>
|
<child>
|
||||||
|
<object class="GtkButton" id="register_button">
|
||||||
|
<property name="label" translatable="yes">Start</property>
|
||||||
|
<property name="valign">center</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
</object>
|
</object>
|
||||||
|
|
|
||||||
233
res/ui/register_dialog.ui
Normal file
233
res/ui/register_dialog.ui
Normal file
|
|
@ -0,0 +1,233 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<interface>
|
||||||
|
<requires lib="gtk" version="4.0"/>
|
||||||
|
<requires lib="libadwaita" version="1.0"/>
|
||||||
|
<object class="GtkStack" id="widget">
|
||||||
|
<property name="transition-type">crossfade</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkStackPage">
|
||||||
|
<property name="name">loading</property>
|
||||||
|
<property name="child">
|
||||||
|
<object class="GtkBox">
|
||||||
|
<property name="orientation">vertical</property>
|
||||||
|
<child>
|
||||||
|
<object class="AdwHeaderBar">
|
||||||
|
<property name="show-start-title-buttons">false</property>
|
||||||
|
<property name="show-end-title-buttons">false</property>
|
||||||
|
<property name="title-widget">
|
||||||
|
<object class="GtkLabel">
|
||||||
|
<property name="label" translatable="yes">Register</property>
|
||||||
|
<style>
|
||||||
|
<class name="title"/>
|
||||||
|
</style>
|
||||||
|
</object>
|
||||||
|
</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkSpinner">
|
||||||
|
<property name="spinning">true</property>
|
||||||
|
<property name="hexpand">true</property>
|
||||||
|
<property name="vexpand">true</property>
|
||||||
|
<property name="halign">center</property>
|
||||||
|
<property name="valign">center</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkStackPage">
|
||||||
|
<property name="name">content</property>
|
||||||
|
<property name="child">
|
||||||
|
<object class="GtkBox">
|
||||||
|
<property name="orientation">vertical</property>
|
||||||
|
<child>
|
||||||
|
<object class="AdwHeaderBar">
|
||||||
|
<property name="show-start-title-buttons">false</property>
|
||||||
|
<property name="show-end-title-buttons">false</property>
|
||||||
|
<property name="title-widget">
|
||||||
|
<object class="GtkLabel">
|
||||||
|
</object>
|
||||||
|
</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkButton" id="cancel_button">
|
||||||
|
<property name="icon-name">go-previous-symbolic</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child type="end">
|
||||||
|
<object class="GtkButton" id="register_button">
|
||||||
|
<property name="label" translatable="yes">Create account</property>
|
||||||
|
<style>
|
||||||
|
<class name="suggested-action"/>
|
||||||
|
</style>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkInfoBar" id="info_bar">
|
||||||
|
<property name="revealed">False</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkScrolledWindow">
|
||||||
|
<property name="vexpand">true</property>
|
||||||
|
<child>
|
||||||
|
<object class="AdwClamp">
|
||||||
|
<property name="margin-start">12</property>
|
||||||
|
<property name="margin-end">12</property>
|
||||||
|
<property name="margin-top">18</property>
|
||||||
|
<property name="margin-bottom">12</property>
|
||||||
|
<property name="maximum-size">800</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkBox">
|
||||||
|
<property name="orientation">vertical</property>
|
||||||
|
<property name="spacing">12</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel">
|
||||||
|
<property name="halign">start</property>
|
||||||
|
<property name="label" translatable="yes">Personal data</property>
|
||||||
|
<attributes>
|
||||||
|
<attribute name="weight" value="bold"/>
|
||||||
|
</attributes>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkFrame">
|
||||||
|
<property name="valign">start</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkListBox">
|
||||||
|
<property name="selection-mode">none</property>
|
||||||
|
<child>
|
||||||
|
<object class="AdwActionRow">
|
||||||
|
<property name="activatable">True</property>
|
||||||
|
<property name="title" translatable="yes">Username</property>
|
||||||
|
<property name="activatable-widget">username_entry</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkEntry" id="username_entry">
|
||||||
|
<property name="valign">center</property>
|
||||||
|
<property name="hexpand">True</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="AdwActionRow">
|
||||||
|
<property name="activatable">True</property>
|
||||||
|
<property name="title" translatable="yes">E-mail (optional)</property>
|
||||||
|
<property name="activatable-widget">email_entry</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkEntry" id="email_entry">
|
||||||
|
<property name="valign">center</property>
|
||||||
|
<property name="hexpand">True</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel">
|
||||||
|
<property name="halign">start</property>
|
||||||
|
<property name="label" translatable="yes">Password</property>
|
||||||
|
<attributes>
|
||||||
|
<attribute name="weight" value="bold"/>
|
||||||
|
</attributes>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkFrame">
|
||||||
|
<property name="valign">start</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkListBox">
|
||||||
|
<property name="selection-mode">none</property>
|
||||||
|
<child>
|
||||||
|
<object class="AdwActionRow">
|
||||||
|
<property name="activatable">True</property>
|
||||||
|
<property name="title" translatable="yes">Password</property>
|
||||||
|
<property name="activatable-widget">password_entry</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkEntry" id="password_entry">
|
||||||
|
<property name="valign">center</property>
|
||||||
|
<property name="hexpand">True</property>
|
||||||
|
<property name="visibility">False</property>
|
||||||
|
<property name="input-purpose">password</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="AdwActionRow">
|
||||||
|
<property name="activatable">True</property>
|
||||||
|
<property name="title" translatable="yes">Repeat password</property>
|
||||||
|
<property name="activatable-widget">repeat_password_entry</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkEntry" id="repeat_password_entry">
|
||||||
|
<property name="valign">center</property>
|
||||||
|
<property name="hexpand">True</property>
|
||||||
|
<property name="visibility">False</property>
|
||||||
|
<property name="input-purpose">password</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel">
|
||||||
|
<property name="halign">start</property>
|
||||||
|
<property name="label" translatable="yes">Captcha</property>
|
||||||
|
<attributes>
|
||||||
|
<attribute name="weight" value="bold"/>
|
||||||
|
</attributes>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkFrame">
|
||||||
|
<property name="valign">start</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkListBox">
|
||||||
|
<property name="selection-mode">none</property>
|
||||||
|
<child>
|
||||||
|
<object class="AdwActionRow" id="captcha_row">
|
||||||
|
<property name="title-lines">0</property>
|
||||||
|
<property name="subtitle" translatable="yes">Feel free to look for the answer online!</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="AdwActionRow">
|
||||||
|
<property name="activatable">True</property>
|
||||||
|
<property name="title" translatable="yes">Your answer</property>
|
||||||
|
<property name="activatable-widget">captcha_entry</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkEntry" id="captcha_entry">
|
||||||
|
<property name="valign">center</property>
|
||||||
|
<property name="hexpand">True</property>
|
||||||
|
<property name="visibility">False</property>
|
||||||
|
<property name="activates-default">True</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</interface>
|
||||||
|
|
@ -22,6 +22,9 @@ pub use persons::*;
|
||||||
pub mod recordings;
|
pub mod recordings;
|
||||||
pub use recordings::*;
|
pub use recordings::*;
|
||||||
|
|
||||||
|
pub mod register;
|
||||||
|
pub use register::*;
|
||||||
|
|
||||||
pub mod works;
|
pub mod works;
|
||||||
pub use works::*;
|
pub use works::*;
|
||||||
|
|
||||||
|
|
|
||||||
49
src/backend/client/register.rs
Normal file
49
src/backend/client/register.rs
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
use super::Backend;
|
||||||
|
use anyhow::{anyhow, Result};
|
||||||
|
use isahc::http::StatusCode;
|
||||||
|
use isahc::prelude::*;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
/// Response body data for captcha requests.
|
||||||
|
#[derive(Clone, Debug, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct Captcha {
|
||||||
|
pub id: String,
|
||||||
|
pub question: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Request body data for user registration.
|
||||||
|
#[derive(Serialize, Debug, Clone)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct UserRegistration {
|
||||||
|
pub username: String,
|
||||||
|
pub password: String,
|
||||||
|
pub email: Option<String>,
|
||||||
|
pub captcha_id: String,
|
||||||
|
pub answer: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Backend {
|
||||||
|
/// Request a new captcha for registration.
|
||||||
|
pub async fn get_captcha(&self) -> Result<Captcha> {
|
||||||
|
let body = self.get("captcha").await?;
|
||||||
|
let captcha = serde_json::from_str(&body)?;
|
||||||
|
Ok(captcha)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Register a new user and return whether the process suceeded. This will
|
||||||
|
/// not store the new login credentials.
|
||||||
|
pub async fn register(&self, data: UserRegistration) -> Result<bool> {
|
||||||
|
let server_url = self.get_server_url().ok_or(anyhow!("No server URL set!"))?;
|
||||||
|
|
||||||
|
let mut response = Request::post(format!("{}/users", server_url))
|
||||||
|
.timeout(Duration::from_secs(10))
|
||||||
|
.header("Content-Type", "application/json")
|
||||||
|
.body(serde_json::to_string(&data)?)?
|
||||||
|
.send_async()
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(response.status() == StatusCode::OK)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
use super::RegisterDialog;
|
||||||
use crate::backend::{Backend, LoginData};
|
use crate::backend::{Backend, LoginData};
|
||||||
use crate::widgets::{Navigator, NavigatorScreen};
|
use crate::widgets::{Navigator, NavigatorScreen};
|
||||||
use glib::clone;
|
use glib::clone;
|
||||||
|
|
@ -29,6 +30,7 @@ impl LoginDialog {
|
||||||
get_widget!(builder, gtk::Button, login_button);
|
get_widget!(builder, gtk::Button, login_button);
|
||||||
get_widget!(builder, gtk::Entry, username_entry);
|
get_widget!(builder, gtk::Entry, username_entry);
|
||||||
get_widget!(builder, gtk::Entry, password_entry);
|
get_widget!(builder, gtk::Entry, password_entry);
|
||||||
|
get_widget!(builder, gtk::Button, register_button);
|
||||||
|
|
||||||
let this = Rc::new(Self {
|
let this = Rc::new(Self {
|
||||||
backend,
|
backend,
|
||||||
|
|
@ -77,6 +79,26 @@ impl LoginDialog {
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
register_button.connect_clicked(clone!(@strong this => move |_| {
|
||||||
|
let navigator = this.navigator.borrow().clone();
|
||||||
|
if let Some(navigator) = navigator {
|
||||||
|
let dialog = RegisterDialog::new(this.backend.clone());
|
||||||
|
|
||||||
|
dialog.set_selected_cb(clone!(@strong this => move |data| {
|
||||||
|
if let Some(cb) = &*this.selected_cb.borrow() {
|
||||||
|
cb(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
let navigator = this.navigator.borrow().clone();
|
||||||
|
if let Some(navigator) = navigator {
|
||||||
|
navigator.pop();
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
navigator.push(dialog);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
this
|
this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,5 +7,8 @@ pub use login_dialog::*;
|
||||||
pub mod preferences;
|
pub mod preferences;
|
||||||
pub use preferences::*;
|
pub use preferences::*;
|
||||||
|
|
||||||
|
pub mod register;
|
||||||
|
pub use register::*;
|
||||||
|
|
||||||
pub mod server_dialog;
|
pub mod server_dialog;
|
||||||
pub use server_dialog::*;
|
pub use server_dialog::*;
|
||||||
|
|
|
||||||
149
src/dialogs/register.rs
Normal file
149
src/dialogs/register.rs
Normal file
|
|
@ -0,0 +1,149 @@
|
||||||
|
use crate::backend::{Backend, LoginData, UserRegistration};
|
||||||
|
use crate::widgets::{Navigator, NavigatorScreen};
|
||||||
|
use glib::clone;
|
||||||
|
use gtk::prelude::*;
|
||||||
|
use gtk_macros::get_widget;
|
||||||
|
use libadwaita::prelude::*;
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
/// A dialog for creating a new user account.
|
||||||
|
pub struct RegisterDialog {
|
||||||
|
backend: Rc<Backend>,
|
||||||
|
widget: gtk::Stack,
|
||||||
|
username_entry: gtk::Entry,
|
||||||
|
email_entry: gtk::Entry,
|
||||||
|
password_entry: gtk::Entry,
|
||||||
|
repeat_password_entry: gtk::Entry,
|
||||||
|
captcha_row: libadwaita::ActionRow,
|
||||||
|
captcha_entry: gtk::Entry,
|
||||||
|
captcha_id: RefCell<Option<String>>,
|
||||||
|
selected_cb: RefCell<Option<Box<dyn Fn(LoginData)>>>,
|
||||||
|
navigator: RefCell<Option<Rc<Navigator>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RegisterDialog {
|
||||||
|
/// Create a new register dialog.
|
||||||
|
pub fn new(backend: Rc<Backend>) -> Rc<Self> {
|
||||||
|
// Create UI
|
||||||
|
let builder = gtk::Builder::from_resource("/de/johrpan/musicus/ui/register_dialog.ui");
|
||||||
|
|
||||||
|
get_widget!(builder, gtk::Stack, widget);
|
||||||
|
get_widget!(builder, gtk::Button, cancel_button);
|
||||||
|
get_widget!(builder, gtk::Button, register_button);
|
||||||
|
get_widget!(builder, gtk::Entry, username_entry);
|
||||||
|
get_widget!(builder, gtk::Entry, email_entry);
|
||||||
|
get_widget!(builder, gtk::Entry, password_entry);
|
||||||
|
get_widget!(builder, gtk::Entry, repeat_password_entry);
|
||||||
|
get_widget!(builder, libadwaita::ActionRow, captcha_row);
|
||||||
|
get_widget!(builder, gtk::Entry, captcha_entry);
|
||||||
|
|
||||||
|
let this = Rc::new(Self {
|
||||||
|
backend,
|
||||||
|
widget,
|
||||||
|
username_entry,
|
||||||
|
email_entry,
|
||||||
|
password_entry,
|
||||||
|
repeat_password_entry,
|
||||||
|
captcha_row,
|
||||||
|
captcha_entry,
|
||||||
|
captcha_id: RefCell::new(None),
|
||||||
|
selected_cb: RefCell::new(None),
|
||||||
|
navigator: RefCell::new(None),
|
||||||
|
});
|
||||||
|
|
||||||
|
// Connect signals and callbacks
|
||||||
|
|
||||||
|
cancel_button.connect_clicked(clone!(@strong this => move |_| {
|
||||||
|
let navigator = this.navigator.borrow().clone();
|
||||||
|
if let Some(navigator) = navigator {
|
||||||
|
navigator.pop();
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
register_button.connect_clicked(clone!(@strong this => move |_| {
|
||||||
|
let password = this.password_entry.get_text().unwrap().to_string();
|
||||||
|
let repeat = this.repeat_password_entry.get_text().unwrap().to_string();
|
||||||
|
|
||||||
|
if (password != repeat) {
|
||||||
|
// TODO: Show error and validate other input.
|
||||||
|
} else {
|
||||||
|
this.widget.set_visible_child_name("loading");
|
||||||
|
|
||||||
|
let context = glib::MainContext::default();
|
||||||
|
let clone = this.clone();
|
||||||
|
context.spawn_local(async move {
|
||||||
|
let username = clone.username_entry.get_text().unwrap().to_string();
|
||||||
|
let email = clone.email_entry.get_text().unwrap().to_string();
|
||||||
|
let captcha_id = clone.captcha_id.borrow().clone().unwrap();
|
||||||
|
let answer = clone.captcha_entry.get_text().unwrap().to_string();
|
||||||
|
|
||||||
|
let email = if email.len() == 0 {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(email)
|
||||||
|
};
|
||||||
|
|
||||||
|
let registration = UserRegistration {
|
||||||
|
username: username.clone(),
|
||||||
|
password: password.clone(),
|
||||||
|
email,
|
||||||
|
captcha_id,
|
||||||
|
answer,
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: Handle errors.
|
||||||
|
if clone.backend.register(registration).await.unwrap() {
|
||||||
|
if let Some(cb) = &*clone.selected_cb.borrow() {
|
||||||
|
let data = LoginData {
|
||||||
|
username,
|
||||||
|
password,
|
||||||
|
};
|
||||||
|
|
||||||
|
cb(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
let navigator = clone.navigator.borrow().clone();
|
||||||
|
if let Some(navigator) = navigator {
|
||||||
|
navigator.pop();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
clone.widget.set_visible_child_name("content");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Initialize
|
||||||
|
|
||||||
|
let context = glib::MainContext::default();
|
||||||
|
let clone = this.clone();
|
||||||
|
context.spawn_local(async move {
|
||||||
|
let captcha = clone.backend.get_captcha().await.unwrap();
|
||||||
|
clone.captcha_row.set_title(Some(&captcha.question));
|
||||||
|
clone.captcha_id.replace(Some(captcha.id));
|
||||||
|
clone.widget.set_visible_child_name("content");
|
||||||
|
});
|
||||||
|
|
||||||
|
this
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The closure to call when the login succeded.
|
||||||
|
pub fn set_selected_cb<F: Fn(LoginData) + 'static>(&self, cb: F) {
|
||||||
|
self.selected_cb.replace(Some(Box::new(cb)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NavigatorScreen for RegisterDialog {
|
||||||
|
fn attach_navigator(&self, navigator: Rc<Navigator>) {
|
||||||
|
self.navigator.replace(Some(navigator));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_widget(&self) -> gtk::Widget {
|
||||||
|
self.widget.clone().upcast()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn detach_navigator(&self) {
|
||||||
|
self.navigator.replace(None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -39,6 +39,7 @@ sources = files(
|
||||||
'backend/client/mod.rs',
|
'backend/client/mod.rs',
|
||||||
'backend/client/persons.rs',
|
'backend/client/persons.rs',
|
||||||
'backend/client/recordings.rs',
|
'backend/client/recordings.rs',
|
||||||
|
'backend/client/register.rs',
|
||||||
'backend/client/works.rs',
|
'backend/client/works.rs',
|
||||||
'backend/library.rs',
|
'backend/library.rs',
|
||||||
'backend/mod.rs',
|
'backend/mod.rs',
|
||||||
|
|
@ -56,6 +57,7 @@ sources = files(
|
||||||
'dialogs/login_dialog.rs',
|
'dialogs/login_dialog.rs',
|
||||||
'dialogs/mod.rs',
|
'dialogs/mod.rs',
|
||||||
'dialogs/preferences.rs',
|
'dialogs/preferences.rs',
|
||||||
|
'dialogs/register.rs',
|
||||||
'dialogs/server_dialog.rs',
|
'dialogs/server_dialog.rs',
|
||||||
'editors/ensemble.rs',
|
'editors/ensemble.rs',
|
||||||
'editors/instrument.rs',
|
'editors/instrument.rs',
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue