mirror of
https://github.com/YGGverse/Yoda.git
synced 2025-01-28 12:04:13 +00:00
begin identity dialog implementation
This commit is contained in:
parent
12b4d441ca
commit
14c31734fd
@ -1,5 +1,6 @@
|
||||
mod action;
|
||||
mod database;
|
||||
mod identity;
|
||||
mod page;
|
||||
mod widget;
|
||||
|
||||
@ -15,7 +16,7 @@ use crate::Profile;
|
||||
use adw::TabView;
|
||||
use gtk::{
|
||||
glib::{uuid_string_random, GString},
|
||||
prelude::EditableExt,
|
||||
prelude::{Cast, EditableExt},
|
||||
};
|
||||
use sqlite::Transaction;
|
||||
use std::rc::Rc;
|
||||
@ -49,7 +50,7 @@ impl Item {
|
||||
|
||||
let page = Rc::new(Page::new(
|
||||
id.clone(),
|
||||
profile,
|
||||
profile.clone(),
|
||||
(actions.0, actions.1, action.clone()),
|
||||
));
|
||||
|
||||
@ -76,10 +77,24 @@ impl Item {
|
||||
}
|
||||
}
|
||||
|
||||
action.auth().connect_activate(|request| {
|
||||
// @TODO
|
||||
// Show identity selection for item
|
||||
action.ident().connect_activate({
|
||||
let page = page.clone();
|
||||
let parent = tab_view.clone().upcast::<gtk::Widget>();
|
||||
move || {
|
||||
// Request should match valid URI for all drivers supported
|
||||
if let Some(uri) = page.navigation().request().uri() {
|
||||
// Rout by scheme
|
||||
if uri.scheme().to_lowercase() == "gemini" {
|
||||
return identity::new_gemini(profile.clone(), uri).present(Some(&parent));
|
||||
}
|
||||
}
|
||||
// Show dialog with unsupported request message
|
||||
identity::new_unsupported().present(Some(&parent));
|
||||
}
|
||||
});
|
||||
|
||||
// Load new request for item
|
||||
action.load().connect_activate({
|
||||
let page = page.clone();
|
||||
move |request, is_history| {
|
||||
|
@ -1,14 +1,14 @@
|
||||
mod auth;
|
||||
mod ident;
|
||||
mod load;
|
||||
|
||||
use auth::Auth;
|
||||
use ident::Ident;
|
||||
use load::Load;
|
||||
|
||||
use std::rc::Rc;
|
||||
|
||||
/// [SimpleActionGroup](https://docs.gtk.org/gio/class.SimpleActionGroup.html) wrapper for `Browser` actions
|
||||
pub struct Action {
|
||||
auth: Rc<Auth>,
|
||||
ident: Rc<Ident>,
|
||||
load: Rc<Load>,
|
||||
}
|
||||
|
||||
@ -18,16 +18,16 @@ impl Action {
|
||||
/// Create new `Self`
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
auth: Rc::new(Auth::new()),
|
||||
ident: Rc::new(Ident::new()),
|
||||
load: Rc::new(Load::new()),
|
||||
}
|
||||
}
|
||||
|
||||
// Getters
|
||||
|
||||
/// Get reference to `Auth` action
|
||||
pub fn auth(&self) -> &Rc<Auth> {
|
||||
&self.auth
|
||||
/// Get reference to `Ident` action
|
||||
pub fn ident(&self) -> &Rc<Ident> {
|
||||
&self.ident
|
||||
}
|
||||
|
||||
/// Get reference to `Load` action
|
||||
|
@ -1,43 +0,0 @@
|
||||
use gtk::{
|
||||
gio::SimpleAction,
|
||||
glib::uuid_string_random,
|
||||
prelude::{ActionExt, StaticVariantType, ToVariant},
|
||||
};
|
||||
|
||||
/// [SimpleAction](https://docs.gtk.org/gio/class.SimpleAction.html) wrapper for `Load` action of `Item` group
|
||||
pub struct Auth {
|
||||
gobject: SimpleAction,
|
||||
}
|
||||
|
||||
impl Auth {
|
||||
// Constructors
|
||||
|
||||
/// Create new `Self`
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
gobject: SimpleAction::new(&uuid_string_random(), Some(&String::static_variant_type())),
|
||||
}
|
||||
}
|
||||
|
||||
// Actions
|
||||
|
||||
/// Emit [activate](https://docs.gtk.org/gio/signal.SimpleAction.activate.html) signal
|
||||
/// with formatted for this action [Variant](https://docs.gtk.org/glib/struct.Variant.html) value
|
||||
pub fn activate(&self, request: &str) {
|
||||
self.gobject.activate(Some(&request.to_variant()));
|
||||
}
|
||||
|
||||
// Events
|
||||
|
||||
/// Define callback function for
|
||||
/// [SimpleAction::activate](https://docs.gtk.org/gio/signal.SimpleAction.activate.html) signal
|
||||
pub fn connect_activate(&self, callback: impl Fn(String) + 'static) {
|
||||
self.gobject.connect_activate(move |_, this| {
|
||||
callback(
|
||||
this.expect("Expected variant value")
|
||||
.get::<String>()
|
||||
.expect("Parameter type does not match `String` type"),
|
||||
)
|
||||
});
|
||||
}
|
||||
}
|
33
src/app/browser/window/tab/item/action/ident.rs
Normal file
33
src/app/browser/window/tab/item/action/ident.rs
Normal file
@ -0,0 +1,33 @@
|
||||
use gtk::{gio::SimpleAction, glib::uuid_string_random, prelude::ActionExt};
|
||||
|
||||
/// [SimpleAction](https://docs.gtk.org/gio/class.SimpleAction.html) wrapper for `Ident` action of `Item` group
|
||||
pub struct Ident {
|
||||
gobject: SimpleAction,
|
||||
}
|
||||
|
||||
impl Ident {
|
||||
// Constructors
|
||||
|
||||
/// Create new `Self`
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
gobject: SimpleAction::new(&uuid_string_random(), None),
|
||||
}
|
||||
}
|
||||
|
||||
// Actions
|
||||
|
||||
/// Emit [activate](https://docs.gtk.org/gio/signal.SimpleAction.activate.html) signal
|
||||
/// with formatted for this action [Variant](https://docs.gtk.org/glib/struct.Variant.html) value
|
||||
pub fn activate(&self) {
|
||||
self.gobject.activate(None);
|
||||
}
|
||||
|
||||
// Events
|
||||
|
||||
/// Define callback function for
|
||||
/// [SimpleAction::activate](https://docs.gtk.org/gio/signal.SimpleAction.activate.html) signal
|
||||
pub fn connect_activate(&self, callback: impl Fn() + 'static) {
|
||||
self.gobject.connect_activate(move |_, _| callback());
|
||||
}
|
||||
}
|
19
src/app/browser/window/tab/item/identity.rs
Normal file
19
src/app/browser/window/tab/item/identity.rs
Normal file
@ -0,0 +1,19 @@
|
||||
mod gemini;
|
||||
mod unsupported;
|
||||
|
||||
use gemini::Gemini;
|
||||
use unsupported::Unsupported;
|
||||
|
||||
use crate::profile::Profile;
|
||||
use gtk::glib::Uri;
|
||||
use std::rc::Rc;
|
||||
|
||||
/// Create new identity widget for Gemini protocol match given URI
|
||||
pub fn new_gemini(profile: Rc<Profile>, auth_uri: Uri) -> Gemini {
|
||||
Gemini::new(profile, auth_uri)
|
||||
}
|
||||
|
||||
/// Create new identity widget for unknown request
|
||||
pub fn new_unsupported() -> Unsupported {
|
||||
Unsupported::new()
|
||||
}
|
45
src/app/browser/window/tab/item/identity/gemini.rs
Normal file
45
src/app/browser/window/tab/item/identity/gemini.rs
Normal file
@ -0,0 +1,45 @@
|
||||
mod widget;
|
||||
use widget::Widget;
|
||||
|
||||
use crate::profile::Profile;
|
||||
use gtk::{glib::Uri, prelude::IsA};
|
||||
use std::rc::Rc;
|
||||
|
||||
pub struct Gemini {
|
||||
profile: Rc<Profile>,
|
||||
widget: Rc<Widget>,
|
||||
}
|
||||
|
||||
impl Gemini {
|
||||
// Construct
|
||||
|
||||
/// Create new `Self` for given Profile
|
||||
pub fn new(profile: Rc<Profile>, auth_uri: Uri) -> Self {
|
||||
let widget = Rc::new(Widget::new());
|
||||
|
||||
// Init events
|
||||
widget.connect_response({
|
||||
let profile = profile.clone();
|
||||
move |value| {
|
||||
match value {
|
||||
Some(id) => {
|
||||
// Activate selected identity ID
|
||||
}
|
||||
None => {
|
||||
// Create and select new identity
|
||||
}
|
||||
} // @TODO handle result
|
||||
}
|
||||
});
|
||||
|
||||
// Return activated `Self`
|
||||
Self { profile, widget }
|
||||
}
|
||||
|
||||
// Actions
|
||||
|
||||
/// Show dialog for parent [Widget](https://docs.gtk.org/gtk4/class.Widget.html)
|
||||
pub fn present(&self, parent: Option<&impl IsA<gtk::Widget>>) {
|
||||
self.widget.present(parent);
|
||||
}
|
||||
}
|
86
src/app/browser/window/tab/item/identity/gemini/widget.rs
Normal file
86
src/app/browser/window/tab/item/identity/gemini/widget.rs
Normal file
@ -0,0 +1,86 @@
|
||||
mod form;
|
||||
|
||||
use form::Form;
|
||||
|
||||
use adw::{
|
||||
prelude::{AdwDialogExt, AlertDialogExt, AlertDialogExtManual},
|
||||
AlertDialog, ResponseAppearance,
|
||||
};
|
||||
use gtk::prelude::IsA;
|
||||
|
||||
// Defaults
|
||||
const HEADING: &str = "Ident";
|
||||
const BODY: &str = "Select identity certificate";
|
||||
|
||||
// Response variants
|
||||
const RESPONSE_APPLY: (&str, &str) = ("apply", "Apply");
|
||||
const RESPONSE_CANCEL: (&str, &str) = ("cancel", "Cancel");
|
||||
// const RESPONSE_MANAGE: (&str, &str) = ("manage", "Manage");
|
||||
|
||||
// List options
|
||||
const OPTION_CREATE: (Option<i64>, &str) = (None, "Create new..");
|
||||
|
||||
// Select options
|
||||
|
||||
pub struct Widget {
|
||||
gobject: AlertDialog,
|
||||
}
|
||||
|
||||
impl Widget {
|
||||
// Constructors
|
||||
|
||||
/// Create new `Self`
|
||||
pub fn new() -> Self {
|
||||
// Collect identity certificates
|
||||
let mut options: Vec<(Option<i64>, String, bool)> = Vec::new();
|
||||
options.push((OPTION_CREATE.0, OPTION_CREATE.1.to_owned(), false));
|
||||
|
||||
// Init child container
|
||||
let form = Form::new(options);
|
||||
|
||||
// Init main `GObject`
|
||||
let gobject = AlertDialog::builder()
|
||||
.heading(HEADING)
|
||||
.body(BODY)
|
||||
.close_response(RESPONSE_CANCEL.0)
|
||||
.default_response(RESPONSE_APPLY.0)
|
||||
.extra_child(form.gobject())
|
||||
.build();
|
||||
|
||||
// Set response variants
|
||||
gobject.add_responses(&[
|
||||
RESPONSE_CANCEL,
|
||||
// RESPONSE_MANAGE,
|
||||
RESPONSE_APPLY,
|
||||
]);
|
||||
|
||||
// Deactivate not implemented feature @TODO
|
||||
// gobject.set_response_enabled(RESPONSE_MANAGE.0, false);
|
||||
|
||||
// Decorate default response preset
|
||||
gobject.set_response_appearance(RESPONSE_APPLY.0, ResponseAppearance::Suggested);
|
||||
gobject.set_response_appearance(RESPONSE_CANCEL.0, ResponseAppearance::Destructive);
|
||||
|
||||
// Return new activated `Self`
|
||||
Self { gobject }
|
||||
}
|
||||
|
||||
// Actions
|
||||
|
||||
/// Wrapper for default [response](https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/signal.AlertDialog.response.html) signal
|
||||
/// * return `profile_identity_gemini_id` or new record request on `None`
|
||||
pub fn connect_response(&self, callback: impl Fn(Option<i64>) + 'static) {
|
||||
self.gobject.connect_response(None, move |_, response| {
|
||||
if response == RESPONSE_APPLY.0 {
|
||||
callback(None)
|
||||
} else {
|
||||
callback(None)
|
||||
} // @TODO
|
||||
});
|
||||
}
|
||||
|
||||
/// Show dialog with new preset
|
||||
pub fn present(&self, parent: Option<&impl IsA<gtk::Widget>>) {
|
||||
self.gobject.present(parent)
|
||||
}
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
mod list;
|
||||
mod name;
|
||||
|
||||
use list::List;
|
||||
use name::Name;
|
||||
|
||||
use gtk::{
|
||||
prelude::{BoxExt, WidgetExt},
|
||||
Box, Orientation,
|
||||
};
|
||||
|
||||
pub struct Form {
|
||||
gobject: Box,
|
||||
}
|
||||
|
||||
impl Form {
|
||||
// Constructors
|
||||
|
||||
/// Create new `Self`
|
||||
pub fn new(list_options: Vec<(Option<i64>, String, bool)>) -> Self {
|
||||
// Init components
|
||||
let list = List::new(&list_options);
|
||||
let name = Name::new();
|
||||
|
||||
// Init main container
|
||||
let gobject = Box::builder().orientation(Orientation::Vertical).build();
|
||||
|
||||
gobject.append(list.gobject());
|
||||
gobject.append(name.gobject());
|
||||
|
||||
// Init events
|
||||
list.gobject().connect_selected_notify(move |this| {
|
||||
// Get selection ID from vector @TODO use GObject storage instead
|
||||
// https://gtk-rs.org/gtk4-rs/stable/latest/book/list_widgets.html
|
||||
match list_options.get(this.selected() as usize) {
|
||||
// Hide name entry on existing identity selected
|
||||
Some((id, _, _)) => name.gobject().set_visible(id.is_none()),
|
||||
None => todo!(),
|
||||
}
|
||||
});
|
||||
|
||||
// Return activated `Self`
|
||||
Self { gobject }
|
||||
}
|
||||
|
||||
// Getters
|
||||
|
||||
pub fn gobject(&self) -> &Box {
|
||||
&self.gobject
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
use gtk::{DropDown, StringList};
|
||||
|
||||
pub struct List {
|
||||
gobject: DropDown,
|
||||
}
|
||||
|
||||
impl List {
|
||||
// Constructors
|
||||
|
||||
/// Create new `Self`
|
||||
pub fn new(list_options: &Vec<(Option<i64>, String, bool)>) -> Self {
|
||||
// Init empty list model
|
||||
let model = StringList::new(&[]);
|
||||
|
||||
// Init `GObject`
|
||||
let gobject = DropDown::builder().model(&model).build();
|
||||
|
||||
// Build selection list
|
||||
let mut index = 0;
|
||||
|
||||
for (_key, value, is_selected) in list_options {
|
||||
model.append(&value);
|
||||
|
||||
if *is_selected {
|
||||
gobject.set_selected(index);
|
||||
}
|
||||
|
||||
index += 1;
|
||||
}
|
||||
|
||||
// Done
|
||||
Self { gobject }
|
||||
}
|
||||
|
||||
// Getters
|
||||
|
||||
pub fn gobject(&self) -> &DropDown {
|
||||
&self.gobject
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
use gtk::Entry;
|
||||
|
||||
const PLACEHOLDER_TEXT: &str = "Identity name (optional)";
|
||||
const MARGIN: i32 = 8;
|
||||
|
||||
pub struct Name {
|
||||
gobject: Entry,
|
||||
}
|
||||
|
||||
impl Name {
|
||||
// Constructors
|
||||
|
||||
/// Create new `Self`
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
gobject: Entry::builder()
|
||||
.max_length(36) // @TODO use profile const
|
||||
.placeholder_text(PLACEHOLDER_TEXT)
|
||||
.margin_top(MARGIN)
|
||||
.build(),
|
||||
}
|
||||
}
|
||||
|
||||
// Getters
|
||||
|
||||
pub fn gobject(&self) -> &Entry {
|
||||
&self.gobject
|
||||
}
|
||||
}
|
27
src/app/browser/window/tab/item/identity/unsupported.rs
Normal file
27
src/app/browser/window/tab/item/identity/unsupported.rs
Normal file
@ -0,0 +1,27 @@
|
||||
mod widget;
|
||||
use widget::Widget;
|
||||
|
||||
use gtk::prelude::IsA;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub struct Unsupported {
|
||||
widget: Rc<Widget>,
|
||||
}
|
||||
|
||||
impl Unsupported {
|
||||
// Construct
|
||||
|
||||
/// Create new `Self`
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
widget: Rc::new(Widget::new()),
|
||||
}
|
||||
}
|
||||
|
||||
// Actions
|
||||
|
||||
/// Show dialog for given parent
|
||||
pub fn present(&self, parent: Option<&impl IsA<gtk::Widget>>) {
|
||||
self.widget.present(parent)
|
||||
}
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
use adw::{
|
||||
prelude::{AdwDialogExt, AlertDialogExt, AlertDialogExtManual},
|
||||
AlertDialog, ResponseAppearance,
|
||||
};
|
||||
use gtk::prelude::IsA;
|
||||
|
||||
const HEADING: &str = "Oops";
|
||||
const BODY: &str = "Identity not supported for this request";
|
||||
const RESPONSE_QUIT: (&str, &str) = ("close", "Close");
|
||||
|
||||
pub struct Widget {
|
||||
gobject: AlertDialog,
|
||||
}
|
||||
|
||||
impl Widget {
|
||||
// Constructors
|
||||
|
||||
/// Create new `Self`
|
||||
pub fn new() -> Self {
|
||||
// Init gobject
|
||||
let gobject = AlertDialog::builder()
|
||||
.heading(HEADING)
|
||||
.body(BODY)
|
||||
.close_response(RESPONSE_QUIT.0)
|
||||
.default_response(RESPONSE_QUIT.0)
|
||||
.build();
|
||||
|
||||
// Set response variants
|
||||
gobject.add_responses(&[RESPONSE_QUIT]);
|
||||
|
||||
// Decorate default response preset
|
||||
gobject.set_response_appearance(RESPONSE_QUIT.0, ResponseAppearance::Destructive);
|
||||
|
||||
// Init events
|
||||
gobject.connect_response(None, move |dialog, response| {
|
||||
if response == RESPONSE_QUIT.0 {
|
||||
dialog.close();
|
||||
}
|
||||
});
|
||||
|
||||
// Return new activated `Self`
|
||||
Self { gobject }
|
||||
}
|
||||
|
||||
// Actions
|
||||
|
||||
/// Show dialog for given parent
|
||||
pub fn present(&self, parent: Option<&impl IsA<gtk::Widget>>) {
|
||||
self.gobject.present(parent)
|
||||
}
|
||||
}
|
@ -60,7 +60,7 @@ impl Content {
|
||||
/// * action removes previous children component from `Self`
|
||||
pub fn to_status_identity(&self) -> Status {
|
||||
self.clean();
|
||||
let status = Status::new_identity();
|
||||
let status = Status::new_identity(self.tab_action.clone());
|
||||
self.gobject.append(status.gobject());
|
||||
status
|
||||
}
|
||||
|
@ -2,8 +2,9 @@ mod failure;
|
||||
mod identity;
|
||||
mod loading;
|
||||
|
||||
use crate::app::browser::window::tab::item::Action;
|
||||
use adw::StatusPage;
|
||||
use std::time::Duration;
|
||||
use std::{rc::Rc, time::Duration};
|
||||
|
||||
pub struct Status {
|
||||
gobject: StatusPage,
|
||||
@ -25,9 +26,9 @@ impl Status {
|
||||
///
|
||||
/// Useful as placeholder for 60 status code
|
||||
/// https://geminiprotocol.net/docs/protocol-specification.gmi#status-60
|
||||
pub fn new_identity() -> Self {
|
||||
pub fn new_identity(action: Rc<Action>) -> Self {
|
||||
Self {
|
||||
gobject: identity::new_gobject(),
|
||||
gobject: identity::new_gobject(action),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,6 @@
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::app::browser::window::tab::item::Action;
|
||||
use adw::StatusPage;
|
||||
use gtk::{prelude::ButtonExt, Align, Button};
|
||||
|
||||
@ -11,7 +14,7 @@ const DEFAULT_BUTTON_CLASS: &str = "suggested-action";
|
||||
|
||||
/// Create new default preset for `Identity`
|
||||
/// [StatusPage](https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/class.StatusPage.html)
|
||||
pub fn new_gobject() -> StatusPage {
|
||||
pub fn new_gobject(action: Rc<Action>) -> StatusPage {
|
||||
// Init certificate selection
|
||||
let button = &Button::builder()
|
||||
.css_classes([DEFAULT_BUTTON_CLASS])
|
||||
@ -21,7 +24,7 @@ pub fn new_gobject() -> StatusPage {
|
||||
.build();
|
||||
|
||||
// Init events
|
||||
button.connect_activate(|_| {}); // @TODO
|
||||
button.connect_clicked(move |_| action.ident().activate());
|
||||
|
||||
// Init status page
|
||||
StatusPage::builder()
|
||||
|
@ -16,11 +16,11 @@ impl Widget {
|
||||
let gobject = Button::builder()
|
||||
.icon_name("avatar-default-symbolic")
|
||||
.tooltip_text("Identity")
|
||||
.sensitive(false)
|
||||
//.sensitive(false)
|
||||
.build();
|
||||
|
||||
// Init events @TODO dialog window required
|
||||
// gobject.connect_clicked(move |_| action.auth().activate());
|
||||
gobject.connect_clicked(move |_| action.ident().activate());
|
||||
|
||||
// Return activated `Self`
|
||||
Self { gobject }
|
||||
@ -28,7 +28,7 @@ impl Widget {
|
||||
|
||||
// Actions
|
||||
pub fn update(&self, is_sensitive: bool) {
|
||||
self.gobject.set_sensitive(is_sensitive);
|
||||
//self.gobject.set_sensitive(is_sensitive);
|
||||
}
|
||||
|
||||
// Getters
|
||||
|
@ -13,7 +13,7 @@ use std::{rc::Rc, sync::RwLock};
|
||||
/// Authorization wrapper for different protocols
|
||||
pub struct Identity {
|
||||
// database: Rc<Database>,
|
||||
gemini: Rc<Gemini>,
|
||||
pub gemini: Rc<Gemini>,
|
||||
}
|
||||
|
||||
impl Identity {
|
||||
|
@ -1,10 +1,13 @@
|
||||
use sqlite::{Connection, Error, Transaction};
|
||||
use std::{rc::Rc, sync::RwLock};
|
||||
|
||||
pub const NAME_MAX_LEN: i32 = 36;
|
||||
|
||||
pub struct Table {
|
||||
pub id: i64,
|
||||
//pub profile_identity_id: i64,
|
||||
pub pem: String,
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
/// Storage for Gemini auth certificates
|
||||
@ -36,14 +39,19 @@ impl Database {
|
||||
|
||||
pub fn init(tx: &Transaction) -> Result<usize, Error> {
|
||||
tx.execute(
|
||||
"CREATE TABLE IF NOT EXISTS `profile_identity_gemini`
|
||||
(
|
||||
`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
`profile_identity_id` INTEGER NOT NULL,
|
||||
`pem` TEXT NOT NULL,
|
||||
format!(
|
||||
"CREATE TABLE IF NOT EXISTS `profile_identity_gemini`
|
||||
(
|
||||
`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
`profile_identity_id` INTEGER NOT NULL,
|
||||
`pem` TEXT NOT NULL,
|
||||
`name` VARCHAR({}),
|
||||
|
||||
FOREIGN KEY (`profile_identity_id`) REFERENCES `profile_identity`(`id`)
|
||||
)",
|
||||
FOREIGN KEY (`profile_identity_id`) REFERENCES `profile_identity`(`id`)
|
||||
)",
|
||||
NAME_MAX_LEN
|
||||
)
|
||||
.as_str(),
|
||||
[],
|
||||
)
|
||||
}
|
||||
@ -52,7 +60,8 @@ pub fn select(tx: &Transaction, profile_id: i64) -> Result<Vec<Table>, Error> {
|
||||
let mut stmt = tx.prepare(
|
||||
"SELECT `id`,
|
||||
`profile_identity_id`,
|
||||
`pem`
|
||||
`pem`,
|
||||
`name`
|
||||
|
||||
FROM `profile_identity_gemini` WHERE `profile_identity_id` = ?",
|
||||
)?;
|
||||
@ -62,6 +71,7 @@ pub fn select(tx: &Transaction, profile_id: i64) -> Result<Vec<Table>, Error> {
|
||||
id: row.get(0)?,
|
||||
//profile_identity_id: row.get(1)?,
|
||||
pem: row.get(2)?,
|
||||
name: row.get(3)?,
|
||||
})
|
||||
})?;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user