Initial port to templates
This commit is contained in:
parent
34dd188a98
commit
6da52ba6de
|
@ -0,0 +1,44 @@
|
||||||
|
using Gtk 4.0;
|
||||||
|
using Adw 1;
|
||||||
|
|
||||||
|
Adw.Window window {
|
||||||
|
default-width: 500;
|
||||||
|
default-height: 500;
|
||||||
|
|
||||||
|
Adw.ToolbarView view {
|
||||||
|
content: Box{
|
||||||
|
orientation: vertical;
|
||||||
|
ScrolledWindow {
|
||||||
|
vexpand: true;
|
||||||
|
hexpand: true;
|
||||||
|
child: Box content {
|
||||||
|
orientation: vertical;
|
||||||
|
Adw.PreferencesPage preferences_page {
|
||||||
|
title: "General";
|
||||||
|
|
||||||
|
Adw.PreferencesGroup register_browser_biometrics_group {
|
||||||
|
title: "Register Browser Biometrics";
|
||||||
|
description: "Run the following command in your terminal to set up the browser biometrics integration";
|
||||||
|
|
||||||
|
Adw.ActionRow setup_command_row {
|
||||||
|
subtitle: "flatpak run --filesystem=home --command=goldwarden com.quexten.Goldwarden setup browserbiometrics";
|
||||||
|
subtitle-selectable: true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
[top]
|
||||||
|
Adw.HeaderBar {
|
||||||
|
halign: baseline;
|
||||||
|
|
||||||
|
title-widget: Adw.WindowTitle {
|
||||||
|
title: 'Goldwarden Browser Biometrics Setup';
|
||||||
|
};
|
||||||
|
|
||||||
|
valign: start;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,53 +1,32 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
import sys
|
||||||
import gi
|
import gi
|
||||||
|
|
||||||
gi.require_version('Gtk', '4.0')
|
gi.require_version('Gtk', '4.0')
|
||||||
gi.require_version('Adw', '1')
|
gi.require_version('Adw', '1')
|
||||||
import gc
|
|
||||||
import time
|
|
||||||
from gi.repository import Gtk, Adw, GLib, Notify, Gdk
|
|
||||||
from threading import Thread
|
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
from . import components
|
|
||||||
|
|
||||||
class MyApp(Adw.Application):
|
from gi.repository import Gtk, Adw, GLib, Gdk, Gio
|
||||||
|
from ..services import goldwarden
|
||||||
|
from threading import Thread
|
||||||
|
from .template_loader import load_template
|
||||||
|
import subprocess
|
||||||
|
from . import components
|
||||||
|
import os
|
||||||
|
|
||||||
|
class GoldwardenBrowserBiometricsSetupGuideApp(Adw.Application):
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
super().__init__(**kwargs)
|
super().__init__(**kwargs)
|
||||||
self.connect('activate', self.on_activate)
|
self.connect('activate', self.on_activate)
|
||||||
|
|
||||||
def on_activate(self, app):
|
def on_activate(self, app):
|
||||||
self.pinentry_window = MainWindow(application=app)
|
self.load()
|
||||||
self.pinentry_window.present()
|
self.window.present()
|
||||||
self.app = app
|
|
||||||
|
|
||||||
class MainWindow(Gtk.ApplicationWindow):
|
def load(self):
|
||||||
def __init__(self, *args, **kwargs):
|
builder = load_template("browserbiometrics.ui")
|
||||||
super().__init__(*args, **kwargs)
|
self.window = builder.get_object("window")
|
||||||
|
self.window.set_application(self)
|
||||||
|
|
||||||
# vertical box
|
if __name__ == "__main__":
|
||||||
self.box = Gtk.Box()
|
app = GoldwardenBrowserBiometricsSetupGuideApp(application_id="com.quexten.Goldwarden.browserbiometrics")
|
||||||
self.box.set_orientation(Gtk.Orientation.VERTICAL)
|
app.run(sys.argv)
|
||||||
self.set_child(self.box)
|
|
||||||
|
|
||||||
self.stack = Gtk.Stack()
|
|
||||||
self.stack.set_transition_type(Gtk.StackTransitionType.SLIDE_LEFT_RIGHT)
|
|
||||||
self.box.append(self.stack)
|
|
||||||
|
|
||||||
self.preferences_page = Adw.PreferencesPage()
|
|
||||||
self.preferences_page.set_title("General")
|
|
||||||
self.stack.add_named(self.preferences_page, "preferences_page")
|
|
||||||
|
|
||||||
self.register_browser_biometrics_group = Adw.PreferencesGroup()
|
|
||||||
self.register_browser_biometrics_group.set_title("Register Browser Biometrics")
|
|
||||||
self.register_browser_biometrics_group.set_description("Run the following command in your terminal to set up the browser biometrics integration")
|
|
||||||
self.preferences_page.add(self.register_browser_biometrics_group)
|
|
||||||
|
|
||||||
self.setup_command_row = Adw.ActionRow()
|
|
||||||
self.setup_command_row.set_subtitle("flatpak run --filesystem=home --command=goldwarden com.quexten.Goldwarden setup browserbiometrics")
|
|
||||||
self.setup_command_row.set_subtitle_selectable(True)
|
|
||||||
self.register_browser_biometrics_group.add(self.setup_command_row)
|
|
||||||
|
|
||||||
self.set_default_size(700, 400)
|
|
||||||
self.set_title("Goldwarden Browser Biometrics Setup")
|
|
||||||
|
|
||||||
app = MyApp(application_id="com.quexten.Goldwarden.browserbiometrics")
|
|
||||||
app.run(sys.argv)
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
using Gtk 4.0;
|
||||||
|
using Adw 1;
|
||||||
|
|
||||||
|
Adw.Window window {
|
||||||
|
default-width: 400;
|
||||||
|
default-height: 550;
|
||||||
|
|
||||||
|
Adw.ToolbarView view {
|
||||||
|
content: Box {
|
||||||
|
orientation: vertical;
|
||||||
|
spacing: 6;
|
||||||
|
|
||||||
|
Adw.PreferencesPage preferences_page {
|
||||||
|
Adw.PreferencesGroup {
|
||||||
|
title: "Authentication";
|
||||||
|
margin-start: 12;
|
||||||
|
margin-end: 12;
|
||||||
|
margin-bottom: 12;
|
||||||
|
Adw.EntryRow email_row {
|
||||||
|
title: "Email";
|
||||||
|
text: "";
|
||||||
|
}
|
||||||
|
Adw.EntryRow client_id_row {
|
||||||
|
title: "Client ID (optional)";
|
||||||
|
text: "";
|
||||||
|
}
|
||||||
|
Adw.EntryRow client_secret_row {
|
||||||
|
title: "Client Secret (optional)";
|
||||||
|
text: "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Adw.PreferencesGroup {
|
||||||
|
title: "Server";
|
||||||
|
margin-start: 12;
|
||||||
|
margin-end: 12;
|
||||||
|
margin-top: 12;
|
||||||
|
margin-bottom: 12;
|
||||||
|
Adw.EntryRow server_row {
|
||||||
|
title: "Server URL";
|
||||||
|
text: "https://vault.bitwarden.com";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Adw.PreferencesGroup {
|
||||||
|
margin-start: 12;
|
||||||
|
margin-end: 12;
|
||||||
|
margin-top: 12;
|
||||||
|
margin-bottom: 12;
|
||||||
|
Button login_button {
|
||||||
|
label: "Login";
|
||||||
|
styles [
|
||||||
|
"suggested-action"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
[top]
|
||||||
|
Adw.HeaderBar {
|
||||||
|
halign: baseline;
|
||||||
|
|
||||||
|
title-widget: Adw.WindowTitle {
|
||||||
|
title: 'Goldwarden Login';
|
||||||
|
};
|
||||||
|
|
||||||
|
valign: start;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
import gi
|
||||||
|
gi.require_version('Gtk', '4.0')
|
||||||
|
gi.require_version('Adw', '1')
|
||||||
|
import gc
|
||||||
|
import time
|
||||||
|
from gi.repository import Gtk, Adw, GLib, Notify, Gdk
|
||||||
|
from threading import Thread
|
||||||
|
from .template_loader import load_template
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
from ..services import goldwarden
|
||||||
|
|
||||||
|
goldwarden.create_authenticated_connection(None)
|
||||||
|
|
||||||
|
class GoldwardenLoginApp(Adw.Application):
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
super().__init__(**kwargs)
|
||||||
|
self.connect('activate', self.on_activate)
|
||||||
|
|
||||||
|
def on_activate(self, app):
|
||||||
|
self.load()
|
||||||
|
self.window.present()
|
||||||
|
|
||||||
|
def load(self):
|
||||||
|
builder = load_template("login.ui")
|
||||||
|
self.window = builder.get_object("window")
|
||||||
|
self.window.set_application(self)
|
||||||
|
self.email_row = builder.get_object("email_row")
|
||||||
|
self.client_id_row = builder.get_object("client_id_row")
|
||||||
|
self.client_secret_row = builder.get_object("client_secret_row")
|
||||||
|
self.server_row = builder.get_object("server_row")
|
||||||
|
self.login_button = builder.get_object("login_button")
|
||||||
|
self.login_button.connect("clicked", lambda x: self.on_login())
|
||||||
|
|
||||||
|
def on_login(self):
|
||||||
|
email = self.email_row.get_text()
|
||||||
|
client_id = self.client_id_row.get_text()
|
||||||
|
client_secret = self.client_secret_row.get_text()
|
||||||
|
server = self.server_row.get_text()
|
||||||
|
goldwarden.set_url(server)
|
||||||
|
if client_id != "":
|
||||||
|
goldwarden.set_client_id(client_id)
|
||||||
|
if client_secret != "":
|
||||||
|
goldwarden.set_client_secret(client_secret)
|
||||||
|
goldwarden.login_with_password(email, "")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
app = GoldwardenLoginApp(application_id="com.quexten.Goldwarden.login")
|
||||||
|
app.run(sys.argv)
|
|
@ -0,0 +1,48 @@
|
||||||
|
using Gtk 4.0;
|
||||||
|
using Adw 1;
|
||||||
|
|
||||||
|
Adw.Window window {
|
||||||
|
default-width: 400;
|
||||||
|
default-height: 700;
|
||||||
|
|
||||||
|
Adw.ToolbarView view {
|
||||||
|
content: Box {
|
||||||
|
orientation: vertical;
|
||||||
|
spacing: 6;
|
||||||
|
|
||||||
|
Label message {
|
||||||
|
label: 'Placeholder label';
|
||||||
|
}
|
||||||
|
|
||||||
|
Entry password_entry {
|
||||||
|
placeholder-text: "Enter your password";
|
||||||
|
visibility: false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Box button_box {
|
||||||
|
spacing: 6;
|
||||||
|
|
||||||
|
Button cancel_button {
|
||||||
|
label: "Cancel";
|
||||||
|
hexpand: true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Button approve_button {
|
||||||
|
label: "Approve";
|
||||||
|
hexpand: true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
[top]
|
||||||
|
Adw.HeaderBar {
|
||||||
|
halign: baseline;
|
||||||
|
|
||||||
|
title-widget: Adw.WindowTitle {
|
||||||
|
title: 'Goldwarden Pinentry';
|
||||||
|
};
|
||||||
|
|
||||||
|
valign: start;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,65 +5,45 @@ import gc
|
||||||
import time
|
import time
|
||||||
from gi.repository import Gtk, Adw, GLib, Notify, Gdk
|
from gi.repository import Gtk, Adw, GLib, Notify, Gdk
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
|
from .template_loader import load_template
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
|
|
||||||
message = sys.stdin.readline()
|
class GoldwardenPinentryApp(Adw.Application):
|
||||||
|
|
||||||
class MyApp(Adw.Application):
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
super().__init__(**kwargs)
|
super().__init__(**kwargs)
|
||||||
self.connect('activate', self.on_activate)
|
self.connect('activate', self.on_activate)
|
||||||
|
|
||||||
def on_activate(self, app):
|
def on_activate(self, app):
|
||||||
self.pinentry_window = MainWindow(application=app)
|
self.load()
|
||||||
self.pinentry_window.present()
|
self.window.present()
|
||||||
self.app = app
|
|
||||||
|
|
||||||
class MainWindow(Gtk.ApplicationWindow):
|
def load(self):
|
||||||
def __init__(self, *args, **kwargs):
|
builder = load_template("pinentry.ui")
|
||||||
super().__init__(*args, **kwargs)
|
self.window = builder.get_object("window")
|
||||||
|
self.message_label = builder.get_object("message")
|
||||||
|
self.message_label.set_label(self.message)
|
||||||
|
|
||||||
|
self.cancel_button = builder.get_object("cancel_button")
|
||||||
|
self.cancel_button.connect("clicked", self.on_cancel_button_clicked)
|
||||||
|
self.approve_button = builder.get_object("approve_button")
|
||||||
|
self.approve_button.connect("clicked", self.on_approve_button_clicked)
|
||||||
|
|
||||||
self.stack = Gtk.Stack()
|
self.password_entry = builder.get_object("password_entry")
|
||||||
self.stack.set_transition_type(Gtk.StackTransitionType.SLIDE_LEFT_RIGHT)
|
|
||||||
self.set_child(self.stack)
|
|
||||||
|
|
||||||
box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)
|
|
||||||
self.stack.add_child(box)
|
|
||||||
|
|
||||||
label = Gtk.Label(label=message)
|
|
||||||
box.append(label)
|
|
||||||
|
|
||||||
# Create the password entry
|
|
||||||
self.password_entry = Gtk.Entry()
|
|
||||||
self.password_entry.set_placeholder_text("Enter your password")
|
self.password_entry.set_placeholder_text("Enter your password")
|
||||||
self.password_entry.set_visibility(False) # Hide the password
|
|
||||||
box.append(self.password_entry)
|
|
||||||
|
|
||||||
# Create a button box for cancel and approve buttons
|
self.window.set_application(self)
|
||||||
button_box = Gtk.Box(spacing=6)
|
|
||||||
box.append(button_box)
|
|
||||||
|
|
||||||
# Cancel button
|
def on_approve_button_clicked(self, button):
|
||||||
cancel_button = Gtk.Button(label="Cancel")
|
print(self.password_entry.get_text(), flush=True)
|
||||||
cancel_button.set_hexpand(True) # Make the button expand horizontally
|
os._exit(0)
|
||||||
def on_cancel_button_clicked(button):
|
|
||||||
print("", flush=True)
|
|
||||||
os._exit(0)
|
|
||||||
cancel_button.connect("clicked", on_cancel_button_clicked)
|
|
||||||
button_box.append(cancel_button)
|
|
||||||
|
|
||||||
# Approve button
|
def on_cancel_button_clicked(self, button):
|
||||||
approve_button = Gtk.Button(label="Approve")
|
print("", flush=True)
|
||||||
approve_button.set_hexpand(True) # Make the button expand horizontally
|
os._exit(0)
|
||||||
def on_approve_button_clicked(button):
|
|
||||||
print(self.password_entry.get_text(), flush=True)
|
|
||||||
os._exit(0)
|
|
||||||
approve_button.connect("clicked", on_approve_button_clicked)
|
|
||||||
button_box.append(approve_button)
|
|
||||||
|
|
||||||
self.set_default_size(700, 200)
|
if __name__ == "__main__":
|
||||||
self.set_title("Goldwarden Pinentry")
|
app = GoldwardenPinentryApp(application_id="com.quexten.Goldwarden.pinentry")
|
||||||
|
message = sys.stdin.readline()
|
||||||
app = MyApp(application_id="com.quexten.Goldwarden.pinentry")
|
app.message = message
|
||||||
app.run(sys.argv)
|
app.run(sys.argv)
|
|
@ -0,0 +1,43 @@
|
||||||
|
using Gtk 4.0;
|
||||||
|
using Adw 1;
|
||||||
|
|
||||||
|
Adw.Window window {
|
||||||
|
default-width: 400;
|
||||||
|
default-height: 200;
|
||||||
|
|
||||||
|
Adw.ToolbarView view {
|
||||||
|
content: Box {
|
||||||
|
orientation: vertical;
|
||||||
|
spacing: 6;
|
||||||
|
|
||||||
|
Label message {
|
||||||
|
label: 'Dynamic Message';
|
||||||
|
}
|
||||||
|
|
||||||
|
Box button_box {
|
||||||
|
spacing: 6;
|
||||||
|
|
||||||
|
Button cancel_button {
|
||||||
|
label: "Cancel";
|
||||||
|
hexpand: true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Button approve_button {
|
||||||
|
label: "Approve";
|
||||||
|
hexpand: true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
[top]
|
||||||
|
Adw.HeaderBar {
|
||||||
|
halign: baseline;
|
||||||
|
|
||||||
|
title-widget: Adw.WindowTitle {
|
||||||
|
title: 'Goldwarden Approval';
|
||||||
|
};
|
||||||
|
|
||||||
|
valign: start;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,59 +5,42 @@ import gc
|
||||||
import time
|
import time
|
||||||
from gi.repository import Gtk, Adw, GLib, Notify, Gdk
|
from gi.repository import Gtk, Adw, GLib, Notify, Gdk
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
|
from .template_loader import load_template
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
|
|
||||||
message = sys.stdin.readline()
|
class GoldwardenPinentryApprovalApp(Adw.Application):
|
||||||
|
|
||||||
class MyApp(Adw.Application):
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
super().__init__(**kwargs)
|
super().__init__(**kwargs)
|
||||||
self.connect('activate', self.on_activate)
|
self.connect('activate', self.on_activate)
|
||||||
|
|
||||||
def on_activate(self, app):
|
def on_activate(self, app):
|
||||||
self.pinentry_window = MainWindow(application=app)
|
self.load()
|
||||||
self.pinentry_window.present()
|
self.window.present()
|
||||||
self.app = app
|
|
||||||
|
|
||||||
class MainWindow(Gtk.ApplicationWindow):
|
def load(self):
|
||||||
def __init__(self, *args, **kwargs):
|
builder = load_template("pinentry_approval.ui")
|
||||||
super().__init__(*args, **kwargs)
|
self.window = builder.get_object("window")
|
||||||
|
self.message_label = builder.get_object("message")
|
||||||
|
self.message_label.set_label(self.message)
|
||||||
|
|
||||||
|
self.cancel_button = builder.get_object("cancel_button")
|
||||||
|
self.cancel_button.connect("clicked", self.on_cancel_button_clicked)
|
||||||
|
self.approve_button = builder.get_object("approve_button")
|
||||||
|
self.approve_button.connect("clicked", self.on_approve_button_clicked)
|
||||||
|
|
||||||
self.stack = Gtk.Stack()
|
self.window.set_application(self)
|
||||||
self.stack.set_transition_type(Gtk.StackTransitionType.SLIDE_LEFT_RIGHT)
|
|
||||||
self.set_child(self.stack)
|
|
||||||
|
|
||||||
box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)
|
def on_approve_button_clicked(self, button):
|
||||||
self.stack.add_child(box)
|
print("true", flush=True)
|
||||||
|
os._exit(0)
|
||||||
|
|
||||||
label = Gtk.Label(label=message)
|
def on_cancel_button_clicked(self, button):
|
||||||
box.append(label)
|
print("false", flush=True)
|
||||||
|
os._exit(0)
|
||||||
|
|
||||||
# Create a button box for cancel and approve buttons
|
if __name__ == "__main__":
|
||||||
button_box = Gtk.Box(spacing=6)
|
app = GoldwardenPinentryApprovalApp(application_id="com.quexten.Goldwarden.pinentry")
|
||||||
box.append(button_box)
|
message = sys.stdin.readline()
|
||||||
|
app.message = message
|
||||||
# Cancel button
|
app.run(sys.argv)
|
||||||
cancel_button = Gtk.Button(label="Cancel")
|
|
||||||
cancel_button.set_hexpand(True) # Make the button expand horizontally
|
|
||||||
def on_cancel_button_clicked(button):
|
|
||||||
print("false", flush=True)
|
|
||||||
os._exit(0)
|
|
||||||
cancel_button.connect("clicked", on_cancel_button_clicked)
|
|
||||||
button_box.append(cancel_button)
|
|
||||||
|
|
||||||
# Approve button
|
|
||||||
approve_button = Gtk.Button(label="Approve")
|
|
||||||
approve_button.set_hexpand(True) # Make the button expand horizontally
|
|
||||||
def on_approve_button_clicked(button):
|
|
||||||
print("true", flush=True)
|
|
||||||
os._exit(0)
|
|
||||||
approve_button.connect("clicked", on_approve_button_clicked)
|
|
||||||
button_box.append(approve_button)
|
|
||||||
|
|
||||||
self.set_default_size(700, 200)
|
|
||||||
self.set_title("Goldwarden Approval")
|
|
||||||
|
|
||||||
app = MyApp(application_id="com.quexten.Goldwarden.pinentry")
|
|
||||||
app.run(sys.argv)
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
using Gtk 4.0;
|
||||||
|
using Adw 1;
|
||||||
|
|
||||||
|
|
||||||
|
Adw.Window window {
|
||||||
|
default-width: 400;
|
||||||
|
default-height: 700;
|
||||||
|
|
||||||
|
Adw.ToolbarView view {
|
||||||
|
content: Box{
|
||||||
|
orientation: vertical;
|
||||||
|
Box {
|
||||||
|
orientation: vertical;
|
||||||
|
|
||||||
|
Adw.PreferencesPage preferences_page {
|
||||||
|
Adw.PreferencesGroup {
|
||||||
|
Adw.EntryRow search_row {
|
||||||
|
title: "Search";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Adw.StatusPage status_page {
|
||||||
|
visible: true;
|
||||||
|
margin-top: 100;
|
||||||
|
title: "Type to search";
|
||||||
|
icon-name: "system-search-symbolic";
|
||||||
|
}
|
||||||
|
|
||||||
|
ListBox results_list {
|
||||||
|
margin-start: 10;
|
||||||
|
margin-end: 10;
|
||||||
|
margin-top: 10;
|
||||||
|
margin-bottom: 10;
|
||||||
|
visible: false;
|
||||||
|
styles [
|
||||||
|
"boxed-list"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
[top]
|
||||||
|
Adw.HeaderBar {
|
||||||
|
halign: baseline;
|
||||||
|
|
||||||
|
title-widget: Adw.WindowTitle {
|
||||||
|
title: 'QuickAccess';
|
||||||
|
};
|
||||||
|
|
||||||
|
valign: start;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,172 +7,111 @@ import time
|
||||||
from gi.repository import Gtk, Adw, GLib, Notify, Gdk
|
from gi.repository import Gtk, Adw, GLib, Notify, Gdk
|
||||||
from ..services import goldwarden
|
from ..services import goldwarden
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
|
from .template_loader import load_template
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
from ..services import totp
|
from ..services import totp
|
||||||
Notify.init("Goldwarden")
|
Notify.init("Goldwarden")
|
||||||
|
|
||||||
# read line from stdin
|
class GoldwardenQuickAccessApp(Adw.Application):
|
||||||
token = sys.stdin.readline()
|
|
||||||
goldwarden.create_authenticated_connection(token)
|
|
||||||
|
|
||||||
def autotype(text):
|
|
||||||
goldwarden.autotype(text)
|
|
||||||
time.sleep(0.1)
|
|
||||||
os._exit(0)
|
|
||||||
|
|
||||||
def set_clipboard(text):
|
|
||||||
Gdk.Display.get_clipboard(Gdk.Display.get_default()).set_content(
|
|
||||||
Gdk.ContentProvider.new_for_value(text)
|
|
||||||
)
|
|
||||||
|
|
||||||
def kill():
|
|
||||||
time.sleep(0.5)
|
|
||||||
os._exit(0)
|
|
||||||
thread = Thread(target=kill)
|
|
||||||
thread.start()
|
|
||||||
|
|
||||||
class MyApp(Adw.Application):
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
super().__init__(**kwargs)
|
super().__init__(**kwargs)
|
||||||
|
self.logins = []
|
||||||
|
self.filtered_logins = []
|
||||||
|
self.query = ""
|
||||||
self.connect('activate', self.on_activate)
|
self.connect('activate', self.on_activate)
|
||||||
|
|
||||||
def update_logins(self):
|
|
||||||
logins = goldwarden.get_vault_logins()
|
|
||||||
if logins == None:
|
|
||||||
os._exit(0)
|
|
||||||
return
|
|
||||||
self.app.autofill_window.logins = logins
|
|
||||||
|
|
||||||
def on_activate(self, app):
|
def on_activate(self, app):
|
||||||
self.autofill_window = MainWindow(application=app)
|
self.load()
|
||||||
self.autofill_window.logins = []
|
self.window.present()
|
||||||
self.autofill_window.present()
|
|
||||||
self.app = app
|
|
||||||
thread = Thread(target=self.update_logins)
|
thread = Thread(target=self.update_logins)
|
||||||
thread.start()
|
thread.start()
|
||||||
|
|
||||||
class MainWindow(Gtk.ApplicationWindow):
|
def load(self):
|
||||||
def __init__(self, *args, **kwargs):
|
builder = load_template("quickaccess.ui")
|
||||||
super().__init__(*args, **kwargs)
|
self.window = builder.get_object("window")
|
||||||
|
self.results_list = builder.get_object("results_list")
|
||||||
|
self.status_page = builder.get_object("status_page")
|
||||||
|
self.text_view = builder.get_object("search_row")
|
||||||
|
self.text_view.connect("changed", self.on_type)
|
||||||
|
self.window.set_application(self)
|
||||||
|
|
||||||
self.stack = Gtk.Stack()
|
def update(self):
|
||||||
self.stack.set_transition_type(Gtk.StackTransitionType.SLIDE_LEFT_RIGHT)
|
self.update_list()
|
||||||
self.set_child(self.stack)
|
self.render_list()
|
||||||
|
|
||||||
self.box = Gtk.Box()
|
def autotype(self, text):
|
||||||
self.box.set_orientation(Gtk.Orientation.VERTICAL)
|
goldwarden.autotype(text)
|
||||||
self.stack.add_named(self.box, "box")
|
time.sleep(0.1)
|
||||||
|
os._exit(0)
|
||||||
|
|
||||||
self.text_view = Adw.EntryRow()
|
def set_clipboard(self, text):
|
||||||
self.text_view.set_title("Search")
|
Gdk.Display.get_clipboard(Gdk.Display.get_default()).set_content(
|
||||||
|
Gdk.ContentProvider.new_for_value(text)
|
||||||
def on_type(entry):
|
)
|
||||||
if len(entry.get_text()) > 1:
|
|
||||||
self.results_list.show()
|
|
||||||
else:
|
|
||||||
self.results_list.hide()
|
|
||||||
|
|
||||||
|
def kill():
|
||||||
|
time.sleep(0.5)
|
||||||
|
os._exit(0)
|
||||||
|
thread = Thread(target=kill)
|
||||||
|
thread.start()
|
||||||
|
|
||||||
|
def update_list(self):
|
||||||
|
if self.query == "":
|
||||||
|
self.filtered_logins = []
|
||||||
|
return
|
||||||
|
|
||||||
|
self.filtered_logins = list(filter(lambda i: self.query.lower() in i["name"].lower(), self.logins))
|
||||||
|
|
||||||
|
self.starts_with_logins = list(filter(lambda i: i["name"].lower().startswith(self.query.lower()), self.filtered_logins))
|
||||||
|
self.other_logins = list(filter(lambda i: i not in self.starts_with_logins, self.filtered_logins))
|
||||||
|
self.filtered_logins = self.starts_with_logins + self.other_logins
|
||||||
|
if len(self.filtered_logins) > 7:
|
||||||
|
self.filtered_logins = self.filtered_logins[0:7]
|
||||||
|
|
||||||
|
def render_list(self):
|
||||||
|
if len(self.filtered_logins) > 1:
|
||||||
|
self.results_list.set_visible(True)
|
||||||
while self.results_list.get_first_child() != None:
|
while self.results_list.get_first_child() != None:
|
||||||
self.results_list.remove(self.results_list.get_first_child())
|
self.results_list.remove(self.results_list.get_first_child())
|
||||||
|
self.status_page.set_visible(False)
|
||||||
|
else:
|
||||||
|
self.results_list.set_visible(False)
|
||||||
|
self.status_page.set_visible(True)
|
||||||
|
|
||||||
self.filtered_logins = list(filter(lambda i: entry.get_text().lower() in i["name"].lower(), self.logins))
|
for i in self.filtered_logins:
|
||||||
if len( self.filtered_logins) > 10:
|
action_row = Adw.ActionRow()
|
||||||
self.filtered_logins = self.filtered_logins[0:10]
|
action_row.set_title(i["name"])
|
||||||
self.starts_with_logins = list(filter(lambda i: i["name"].lower().startswith(entry.get_text().lower()), self.logins))
|
action_row.set_subtitle(i["username"])
|
||||||
self.other_logins = list(filter(lambda i: i not in self.starts_with_logins , self.filtered_logins))
|
action_row.set_icon_name("dialog-password")
|
||||||
self.filtered_logins = None
|
action_row.set_activatable(True)
|
||||||
|
action_row.password = i["password"]
|
||||||
|
action_row.username = i["username"]
|
||||||
|
action_row.uuid = i["uuid"]
|
||||||
|
action_row.uri = i["uri"]
|
||||||
|
action_row.totp = i["totp"]
|
||||||
|
self.results_list.append(action_row)
|
||||||
|
self.starts_with_logins = None
|
||||||
|
self.other_logins = None
|
||||||
|
|
||||||
for i in self.starts_with_logins + self.other_logins :
|
def on_type(self, entry):
|
||||||
action_row = Adw.ActionRow()
|
search_query = entry.get_text()
|
||||||
action_row.set_title(i["name"])
|
self.query = search_query
|
||||||
action_row.set_subtitle(i["username"])
|
self.update()
|
||||||
action_row.set_icon_name("dialog-password")
|
|
||||||
action_row.set_activatable(True)
|
|
||||||
action_row.password = i["password"]
|
|
||||||
action_row.username = i["username"]
|
|
||||||
action_row.uuid = i["uuid"]
|
|
||||||
action_row.uri = i["uri"]
|
|
||||||
action_row.totp = i["totp"]
|
|
||||||
self.results_list.append(action_row)
|
|
||||||
self.starts_with_logins = None
|
|
||||||
self.other_logins = None
|
|
||||||
self.text_view.connect("changed", lambda entry: on_type(entry))
|
|
||||||
self.box.append(self.text_view)
|
|
||||||
|
|
||||||
self.results_list = Gtk.ListBox()
|
def update_logins(self):
|
||||||
# margin'
|
logins = goldwarden.get_vault_logins()
|
||||||
self.results_list.set_margin_start(10)
|
print(logins)
|
||||||
self.results_list.set_margin_end(10)
|
if logins == None:
|
||||||
self.results_list.set_margin_top(10)
|
os._exit(0)
|
||||||
self.results_list.set_margin_bottom(10)
|
return
|
||||||
self.results_list.hide()
|
self.logins = logins
|
||||||
|
self.update()
|
||||||
keycont = Gtk.EventControllerKey()
|
|
||||||
def handle_keypress(controller, keyval, keycode, state, user_data):
|
if __name__ == "__main__":
|
||||||
ctrl_pressed = state & Gdk.ModifierType.CONTROL_MASK > 0
|
# todo add proper method to debug this
|
||||||
alt_pressed = state & Gdk.ModifierType.ALT_MASK > 0
|
# token = sys.stdin.readline()
|
||||||
|
token = "Test"
|
||||||
if keycode == 9:
|
goldwarden.create_authenticated_connection(token)
|
||||||
os._exit(0)
|
app = GoldwardenQuickAccessApp(application_id="com.quexten.Goldwarden.quickaccess")
|
||||||
|
app.run(sys.argv)
|
||||||
if keyval == 65364:
|
|
||||||
# focus results
|
|
||||||
if self.results_list.get_first_child() != None:
|
|
||||||
self.results_list.get_first_child().grab_focus()
|
|
||||||
self.results_list.select_row(self.results_list.get_first_child())
|
|
||||||
|
|
||||||
if keyval == 113:
|
|
||||||
return False
|
|
||||||
|
|
||||||
if keycode == 36:
|
|
||||||
self.hide()
|
|
||||||
autotypeThread = Thread(target=autotype, args=(f"{self.results_list.get_selected_row().username}\t{self.results_list.get_selected_row().password}",))
|
|
||||||
autotypeThread.start()
|
|
||||||
if keyval == 112:
|
|
||||||
print("pass", ctrl_pressed, alt_pressed)
|
|
||||||
if ctrl_pressed and not alt_pressed:
|
|
||||||
set_clipboard(self.results_list.get_selected_row().password)
|
|
||||||
if ctrl_pressed and alt_pressed:
|
|
||||||
self.hide()
|
|
||||||
autotypeThread = Thread(target=autotype, args=(self.results_list.get_selected_row().password,))
|
|
||||||
autotypeThread.start()
|
|
||||||
elif keyval == 117:
|
|
||||||
if ctrl_pressed and not alt_pressed:
|
|
||||||
set_clipboard(self.results_list.get_selected_row().username)
|
|
||||||
if ctrl_pressed and alt_pressed:
|
|
||||||
self.hide()
|
|
||||||
autotypeThread = Thread(target=autotype, args=(self.results_list.get_selected_row().username,))
|
|
||||||
autotypeThread.start()
|
|
||||||
elif keyval == 118:
|
|
||||||
if ctrl_pressed and alt_pressed:
|
|
||||||
environment = goldwarden.get_environment()
|
|
||||||
if environment == None:
|
|
||||||
return
|
|
||||||
item_uri = environment["vault"] + "#/vault?itemId=" + self.results_list.get_selected_row().uuid
|
|
||||||
Gtk.show_uri(None, item_uri, Gdk.CURRENT_TIME)
|
|
||||||
elif keyval == 108:
|
|
||||||
if ctrl_pressed and alt_pressed:
|
|
||||||
Gtk.show_uri(None, self.results_list.get_selected_row().uri, Gdk.CURRENT_TIME)
|
|
||||||
elif keyval == 116:
|
|
||||||
totp_code = totp.totp(self.results_list.get_selected_row().totp)
|
|
||||||
if ctrl_pressed and not alt_pressed:
|
|
||||||
set_clipboard(totp_code)
|
|
||||||
if ctrl_pressed and alt_pressed:
|
|
||||||
self.hide()
|
|
||||||
autotypeThread = Thread(target=autotype, args=(totp_code,))
|
|
||||||
autotypeThread.start()
|
|
||||||
elif keyval == 102:
|
|
||||||
# focus search
|
|
||||||
self.text_view.grab_focus()
|
|
||||||
|
|
||||||
keycont.connect('key-pressed', handle_keypress, self)
|
|
||||||
self.add_controller(keycont)
|
|
||||||
|
|
||||||
self.results_list.get_style_context().add_class("boxed-list")
|
|
||||||
self.box.append(self.results_list)
|
|
||||||
self.set_default_size(700, 700)
|
|
||||||
self.set_title("Goldwarden Quick Access")
|
|
||||||
|
|
||||||
app = MyApp(application_id="com.quexten.Goldwarden.autofill-menu")
|
|
||||||
app.run(sys.argv)
|
|
|
@ -1,84 +1,145 @@
|
||||||
using Gtk 4.0;
|
using Gtk 4.0;
|
||||||
using Adw 1;
|
using Adw 1;
|
||||||
|
|
||||||
Box content {
|
|
||||||
orientation: vertical;
|
|
||||||
Adw.Banner paused_banner {
|
|
||||||
title: 'No pin set, please set it now';
|
|
||||||
button-label: 'Set Pin';
|
|
||||||
revealed: false;
|
|
||||||
}
|
|
||||||
Adw.PreferencesPage preferences_page {
|
|
||||||
title: "General";
|
|
||||||
Adw.PreferencesGroup {
|
|
||||||
title: "Actions";
|
|
||||||
Button quick_access_button {
|
|
||||||
label: "Quick Access";
|
|
||||||
margin-top: 20;
|
|
||||||
styles [
|
|
||||||
"suggested-action"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
Button login_button {
|
|
||||||
label: "Login";
|
|
||||||
margin-top: 20;
|
|
||||||
styles [
|
|
||||||
"suggested-action"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
Button pin_button {
|
|
||||||
label: "Set pin";
|
|
||||||
margin-top: 20;
|
|
||||||
styles [
|
|
||||||
"suggested-action"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
Button unlock_button {
|
|
||||||
label: "Unlock";
|
|
||||||
sensitive: false;
|
|
||||||
margin-top: 20;
|
|
||||||
styles [
|
|
||||||
"suggested-action"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
Button logout_button {
|
|
||||||
label: "Logout";
|
|
||||||
margin-top: 20;
|
|
||||||
styles [
|
|
||||||
"destructive-action"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
LinkButton {
|
|
||||||
uri: "https://github.com/quexten/goldwarden/wiki/Flatpak-Configuration";
|
|
||||||
label: "Help & Wiki";
|
|
||||||
|
|
||||||
|
Adw.Window window {
|
||||||
|
default-width: 400;
|
||||||
|
default-height: 700;
|
||||||
|
|
||||||
|
Adw.ToolbarView view {
|
||||||
|
content: Box{
|
||||||
|
orientation: vertical;
|
||||||
|
|
||||||
|
Stack stack {
|
||||||
|
Box set_pin_status {
|
||||||
|
orientation: vertical;
|
||||||
|
visible: false;
|
||||||
|
Adw.StatusPage {
|
||||||
|
margin-top: 100;
|
||||||
|
title: "Pin required";
|
||||||
|
icon-name: "dialog-password-symbolic";
|
||||||
|
}
|
||||||
|
Button set_pin_button {
|
||||||
|
label: "Set pin";
|
||||||
|
margin-start: 20;
|
||||||
|
margin-end: 20;
|
||||||
|
styles [
|
||||||
|
"suggested-action",
|
||||||
|
"pill"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Box unlock_status {
|
||||||
|
orientation: vertical;
|
||||||
|
Adw.StatusPage {
|
||||||
|
margin-top: 100;
|
||||||
|
title: "Vault locked";
|
||||||
|
icon-name: "security-high-symbolic";
|
||||||
|
}
|
||||||
|
Button unlock_button {
|
||||||
|
label: "Unlock";
|
||||||
|
margin-start: 20;
|
||||||
|
margin-end: 20;
|
||||||
|
styles [
|
||||||
|
"suggested-action",
|
||||||
|
"pill"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Box login_status {
|
||||||
|
orientation: vertical;
|
||||||
|
Adw.StatusPage {
|
||||||
|
margin-top: 100;
|
||||||
|
title: "Logged out";
|
||||||
|
icon-name: "system-users-symbolic";
|
||||||
|
}
|
||||||
|
Button {
|
||||||
|
label: "Log in";
|
||||||
|
margin-start: 20;
|
||||||
|
margin-end: 20;
|
||||||
|
styles [
|
||||||
|
"suggested-action",
|
||||||
|
"pill"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ScrolledWindow settings_view {
|
||||||
|
vexpand: true;
|
||||||
|
hexpand: true;
|
||||||
|
child: Box content {
|
||||||
|
orientation: vertical;
|
||||||
|
Adw.PreferencesPage preferences_page {
|
||||||
|
title: "General";
|
||||||
|
Adw.PreferencesGroup {
|
||||||
|
title: "Actions";
|
||||||
|
Button quickaccess_button {
|
||||||
|
label: "Quick Access";
|
||||||
|
styles [
|
||||||
|
"suggested-action"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
Button update_pin_button {
|
||||||
|
label: "Update pin";
|
||||||
|
margin-top: 20;
|
||||||
|
styles [
|
||||||
|
"suggested-action"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
Button lock_button {
|
||||||
|
label: "Lock";
|
||||||
|
margin-top: 20;
|
||||||
|
styles [
|
||||||
|
"suggested-action"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
Button logout_button {
|
||||||
|
label: "Logout";
|
||||||
|
margin-top: 20;
|
||||||
|
styles [
|
||||||
|
"destructive-action"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Adw.PreferencesGroup {
|
||||||
|
title: "Vault Status";
|
||||||
|
Adw.ActionRow last_sync_row {
|
||||||
|
title: "Last Sync";
|
||||||
|
subtitle: "Never";
|
||||||
|
icon-name: "emblem-synchronizing-symbolic";
|
||||||
|
}
|
||||||
|
Adw.ActionRow websocket_connected_row {
|
||||||
|
title: "Websocked Connected";
|
||||||
|
subtitle: "False";
|
||||||
|
}
|
||||||
|
Adw.ActionRow logins_row {
|
||||||
|
title: "Vault Login Entries";
|
||||||
|
subtitle: "0";
|
||||||
|
icon-name: "dialog-password-symbolic";
|
||||||
|
}
|
||||||
|
Adw.ActionRow notes_row {
|
||||||
|
title: "Vault Notes";
|
||||||
|
subtitle: "0";
|
||||||
|
icon-name: "emblem-documents-symbolic";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
Adw.PreferencesGroup {
|
|
||||||
title: "Vault Status";
|
[top]
|
||||||
Adw.ActionRow {
|
Adw.HeaderBar {
|
||||||
title: "Vault Status";
|
halign: baseline;
|
||||||
subtitle: "Locked";
|
|
||||||
}
|
title-widget: Adw.WindowTitle {
|
||||||
Adw.ActionRow {
|
title: 'Goldwarden';
|
||||||
title: "Last Sync";
|
};
|
||||||
subtitle: "Never";
|
|
||||||
icon-name: "emblem-synchronizing-symbolic";
|
valign: start;
|
||||||
}
|
|
||||||
Adw.ActionRow {
|
|
||||||
title: "Websocked Connected";
|
|
||||||
subtitle: "False";
|
|
||||||
}
|
|
||||||
Adw.ActionRow {
|
|
||||||
title: "Vault Login Entries";
|
|
||||||
subtitle: "0";
|
|
||||||
icon-name: "dialog-password-symbolic";
|
|
||||||
}
|
|
||||||
Adw.ActionRow {
|
|
||||||
title: "Vault Notes";
|
|
||||||
subtitle: "0";
|
|
||||||
icon-name: "emblem-documents-symbolic";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,249 +13,13 @@ import subprocess
|
||||||
from . import components
|
from . import components
|
||||||
import os
|
import os
|
||||||
|
|
||||||
root_path = os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)), os.pardir, os.pardir))
|
def run_window(name, token):
|
||||||
# token = sys.stdin.readline()
|
gui_path = os.path.dirname(os.path.realpath(__file__))
|
||||||
# goldwarden.create_authenticated_connection(None)
|
cwd = os.path.abspath(os.path.join(gui_path, os.pardir, os.pardir))
|
||||||
#
|
print(f"Running window {name} with path {cwd}")
|
||||||
# def quickaccess_button_clicked():
|
p = subprocess.Popen(["python3", "-m", "src.gui." + name], stdin=subprocess.PIPE, stdout=subprocess.PIPE, cwd=cwd, start_new_session=True)
|
||||||
# p = subprocess.Popen(["python3", "-m", "src.gui.quickaccess"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, cwd=root_path, start_new_session=True)
|
p.stdin.write(f"{token}\n".encode())
|
||||||
# if p.stdin != None:
|
p.stdin.flush()
|
||||||
# p.stdin.write(f"{token}\n".encode())
|
|
||||||
# p.stdin.flush()
|
|
||||||
#
|
|
||||||
# def shortcuts_button_clicked():
|
|
||||||
# p = subprocess.Popen(["python3", "-m", "src.gui.shortcuts"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, cwd=root_path, start_new_session=True)
|
|
||||||
# p.stdin.write(f"{token}\n".encode())
|
|
||||||
# p.stdin.flush()
|
|
||||||
#
|
|
||||||
# def ssh_button_clicked():
|
|
||||||
# p = subprocess.Popen(["python3", "-m", "src.gui.ssh"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, cwd=root_path, start_new_session=True)
|
|
||||||
# p.stdin.write(f"{token}\n".encode())
|
|
||||||
# p.stdin.flush()
|
|
||||||
#
|
|
||||||
# def browserbiometrics_button_clicked():
|
|
||||||
# p = subprocess.Popen(["python3", "-m", "src.gui.browserbiometrics"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, cwd=root_path, start_new_session=True)
|
|
||||||
# p.stdin.write(f"{token}\n".encode())
|
|
||||||
# p.stdin.flush()
|
|
||||||
#
|
|
||||||
# def add_action_row(parent, title, subtitle, icon=None):
|
|
||||||
# row = Adw.ActionRow()
|
|
||||||
# row.set_title(title)
|
|
||||||
# row.set_subtitle(subtitle)
|
|
||||||
# if icon != None:
|
|
||||||
# row.set_icon_name(icon)
|
|
||||||
# parent.add(row)
|
|
||||||
# return row
|
|
||||||
#
|
|
||||||
|
|
||||||
class SettingsWindow(Gtk.ApplicationWindow):
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
super().__init__(*args, **kwargs)
|
|
||||||
# # vertical box
|
|
||||||
self.box = Gtk.Box()
|
|
||||||
self.box.set_orientation(Gtk.Orientation.VERTICAL)
|
|
||||||
self.set_child(self.box)
|
|
||||||
#
|
|
||||||
# def set_pin():
|
|
||||||
# set_pin_thread = Thread(target=goldwarden.enable_pin)
|
|
||||||
# set_pin_thread.start()
|
|
||||||
#
|
|
||||||
# self.banner = Adw.Banner()
|
|
||||||
# self.banner.set_title("No pin set, please set it now")
|
|
||||||
# self.banner.set_button_label("Set Pin")
|
|
||||||
# self.banner.connect("button-clicked", lambda banner: set_pin())
|
|
||||||
# self.box.append(self.banner)
|
|
||||||
#
|
|
||||||
# self.stack = Gtk.Stack()
|
|
||||||
# self.stack.set_transition_type(Gtk.StackTransitionType.SLIDE_LEFT_RIGHT)
|
|
||||||
# self.box.append(self.stack)
|
|
||||||
#
|
|
||||||
# self.preferences_page = Adw.PreferencesPage()
|
|
||||||
# self.preferences_page.set_title("General")
|
|
||||||
# self.stack.add_named(self.preferences_page, "preferences_page")
|
|
||||||
#
|
|
||||||
# self.action_preferences_group = Adw.PreferencesGroup()
|
|
||||||
# self.action_preferences_group.set_title("Actions")
|
|
||||||
# self.preferences_page.add(self.action_preferences_group)
|
|
||||||
#
|
|
||||||
# self.autotype_button = Gtk.Button()
|
|
||||||
# self.autotype_button.set_label("Quick Access")
|
|
||||||
# self.autotype_button.set_margin_top(10)
|
|
||||||
#
|
|
||||||
# self.autotype_button.connect("clicked", lambda button: quickaccess_button_clicked())
|
|
||||||
# self.autotype_button.get_style_context().add_class("suggested-action")
|
|
||||||
# self.action_preferences_group.add(self.autotype_button)
|
|
||||||
#
|
|
||||||
# self.login_button = Gtk.Button()
|
|
||||||
# self.login_button.set_label("Login")
|
|
||||||
# self.login_button.connect("clicked", lambda button: show_login())
|
|
||||||
# self.login_button.set_sensitive(False)
|
|
||||||
# self.login_button.set_margin_top(10)
|
|
||||||
# self.login_button.get_style_context().add_class("suggested-action")
|
|
||||||
# self.action_preferences_group.add(self.login_button)
|
|
||||||
#
|
|
||||||
# self.set_pin_button = Gtk.Button()
|
|
||||||
# self.set_pin_button.set_label("Set Pin")
|
|
||||||
# self.set_pin_button.connect("clicked", lambda button: set_pin())
|
|
||||||
# self.set_pin_button.set_margin_top(10)
|
|
||||||
# self.set_pin_button.set_sensitive(False)
|
|
||||||
# self.set_pin_button.get_style_context().add_class("suggested-action")
|
|
||||||
# self.action_preferences_group.add(self.set_pin_button)
|
|
||||||
#
|
|
||||||
# self.unlock_button = Gtk.Button()
|
|
||||||
# self.unlock_button.set_label("Unlock")
|
|
||||||
# self.unlock_button.set_margin_top(10)
|
|
||||||
# def unlock_button_clicked():
|
|
||||||
# action = goldwarden.unlock if self.unlock_button.get_label() == "Unlock" else goldwarden.lock
|
|
||||||
# unlock_thread = Thread(target=action)
|
|
||||||
# unlock_thread.start()
|
|
||||||
# self.unlock_button.connect("clicked", lambda button: unlock_button_clicked())
|
|
||||||
# # set disabled
|
|
||||||
# self.unlock_button.set_sensitive(False)
|
|
||||||
# self.action_preferences_group.add(self.unlock_button)
|
|
||||||
#
|
|
||||||
# self.logout_button = Gtk.Button()
|
|
||||||
# self.logout_button.set_label("Logout")
|
|
||||||
# self.logout_button.set_margin_top(10)
|
|
||||||
# self.logout_button.connect("clicked", lambda button: goldwarden.purge())
|
|
||||||
# self.logout_button.get_style_context().add_class("destructive-action")
|
|
||||||
# self.action_preferences_group.add(self.logout_button)
|
|
||||||
#
|
|
||||||
# self.wiki_button = Gtk.LinkButton(uri="https://github.com/quexten/goldwarden/wiki/Flatpak-Configuration")
|
|
||||||
# self.wiki_button.set_label("Help & Wiki")
|
|
||||||
# self.wiki_button.set_margin_top(10)
|
|
||||||
# self.action_preferences_group.add(self.wiki_button)
|
|
||||||
#
|
|
||||||
# self.vault_status_preferences_group = Adw.PreferencesGroup()
|
|
||||||
# self.vault_status_preferences_group.set_title("Vault Status")
|
|
||||||
# self.preferences_page.add(self.vault_status_preferences_group)
|
|
||||||
#
|
|
||||||
# self.status_row = add_action_row(self.vault_status_preferences_group, "Vault Status", "Locked")
|
|
||||||
#
|
|
||||||
# self.vault_status_icon = components.StatusIcon()
|
|
||||||
# self.vault_status_icon.set_icon("dialog-error", "error")
|
|
||||||
# self.status_row.add_prefix(self.vault_status_icon)
|
|
||||||
#
|
|
||||||
# self.last_sync_row = add_action_row(self.vault_status_preferences_group, "Last Sync", "Never", "emblem-synchronizing-symbolic")
|
|
||||||
# self.websocket_connected_row = add_action_row(self.vault_status_preferences_group, "Websocket Connected", "False")
|
|
||||||
#
|
|
||||||
# self.websocket_connected_status_icon = components.StatusIcon()
|
|
||||||
# self.websocket_connected_status_icon.set_icon("dialog-error", "error")
|
|
||||||
# self.websocket_connected_row.add_prefix(self.websocket_connected_status_icon)
|
|
||||||
#
|
|
||||||
# self.login_row = add_action_row(self.vault_status_preferences_group, "Vault Login Entries", "0", "dialog-password-symbolic")
|
|
||||||
# self.notes_row = add_action_row(self.vault_status_preferences_group, "Vault Notes", "0", "emblem-documents-symbolic")
|
|
||||||
#
|
|
||||||
# self.header = Gtk.HeaderBar()
|
|
||||||
# self.set_titlebar(self.header)
|
|
||||||
#
|
|
||||||
# action = Gio.SimpleAction.new("shortcuts", None)
|
|
||||||
# action.connect("activate", lambda action, parameter: shortcuts_button_clicked())
|
|
||||||
# self.add_action(action)
|
|
||||||
# menu = Gio.Menu.new()
|
|
||||||
# menu.append("Keyboard Shortcuts", "win.shortcuts")
|
|
||||||
# self.popover = Gtk.PopoverMenu()
|
|
||||||
# self.popover.set_menu_model(menu)
|
|
||||||
#
|
|
||||||
# action = Gio.SimpleAction.new("ssh", None)
|
|
||||||
# action.connect("activate", lambda action, parameter: ssh_button_clicked())
|
|
||||||
# self.add_action(action)
|
|
||||||
# menu.append("SSH Agent", "win.ssh")
|
|
||||||
#
|
|
||||||
# action = Gio.SimpleAction.new("browserbiometrics", None)
|
|
||||||
# action.connect("activate", lambda action, parameter: browserbiometrics_button_clicked())
|
|
||||||
# self.add_action(action)
|
|
||||||
# menu.append("Browser Biometrics", "win.browserbiometrics")
|
|
||||||
#
|
|
||||||
# self.hamburger = Gtk.MenuButton()
|
|
||||||
# self.hamburger.set_popover(self.popover)
|
|
||||||
# self.hamburger.set_icon_name("open-menu-symbolic")
|
|
||||||
# self.header.pack_start(self.hamburger)
|
|
||||||
#
|
|
||||||
#
|
|
||||||
# def update_labels():
|
|
||||||
# pin_set = goldwarden.is_pin_enabled()
|
|
||||||
# status = goldwarden.get_vault_status()
|
|
||||||
# print("status", status)
|
|
||||||
# runtimeCfg = goldwarden.get_runtime_config()
|
|
||||||
#
|
|
||||||
# if status != None:
|
|
||||||
# if pin_set:
|
|
||||||
# self.unlock_button.set_sensitive(True)
|
|
||||||
# self.banner.set_revealed(False)
|
|
||||||
# else:
|
|
||||||
# self.unlock_button.set_sensitive(False)
|
|
||||||
# self.banner.set_revealed(True)
|
|
||||||
# logged_in = status["loggedIn"]
|
|
||||||
# if logged_in and not status["locked"]:
|
|
||||||
# self.autotype_button.set_visible(True)
|
|
||||||
# self.login_row.set_sensitive(True)
|
|
||||||
# self.notes_row.set_sensitive(True)
|
|
||||||
# self.websocket_connected_row.set_sensitive(True)
|
|
||||||
# else:
|
|
||||||
# self.autotype_button.set_visible(False)
|
|
||||||
# self.websocket_connected_row.set_sensitive(False)
|
|
||||||
# self.login_row.set_sensitive(False)
|
|
||||||
# self.notes_row.set_sensitive(False)
|
|
||||||
#
|
|
||||||
# locked = status["locked"]
|
|
||||||
# self.login_button.set_sensitive(pin_set and not locked)
|
|
||||||
# self.set_pin_button.set_sensitive(not pin_set or not locked)
|
|
||||||
# self.autotype_button.set_sensitive(not locked)
|
|
||||||
# self.status_row.set_subtitle(str("Logged in" if (logged_in and not locked) else "Logged out") if not locked else "Locked")
|
|
||||||
# if locked or not logged_in:
|
|
||||||
# self.vault_status_icon.set_icon("dialog-warning", "warning")
|
|
||||||
# else:
|
|
||||||
# self.vault_status_icon.set_icon("emblem-default", "ok")
|
|
||||||
# if not logged_in:
|
|
||||||
# self.logout_button.set_sensitive(False)
|
|
||||||
# else:
|
|
||||||
# self.logout_button.set_sensitive(True)
|
|
||||||
# self.login_row.set_subtitle(str(status["loginEntries"]))
|
|
||||||
# self.notes_row.set_subtitle(str(status["noteEntries"]))
|
|
||||||
# self.websocket_connected_row.set_subtitle("Connected" if status["websocketConnected"] else "Disconnected")
|
|
||||||
# if status["websocketConnected"]:
|
|
||||||
# self.websocket_connected_status_icon.set_icon("emblem-default", "ok")
|
|
||||||
# else:
|
|
||||||
# self.websocket_connected_status_icon.set_icon("dialog-error", "error")
|
|
||||||
# self.last_sync_row.set_subtitle(str(status["lastSynced"]))
|
|
||||||
# if status["lastSynced"].startswith("1970") or status["lastSynced"].startswith("1969"):
|
|
||||||
# self.last_sync_row.set_subtitle("Never")
|
|
||||||
# self.unlock_button.set_label("Unlock" if locked else "Lock")
|
|
||||||
# else:
|
|
||||||
# is_daemon_running = goldwarden.is_daemon_running()
|
|
||||||
# if not is_daemon_running:
|
|
||||||
# self.status_row.set_subtitle("Daemon not running")
|
|
||||||
# self.vault_status_icon.set_icon("dialog-error", "error")
|
|
||||||
#
|
|
||||||
# GLib.timeout_add(5000, update_labels)
|
|
||||||
#
|
|
||||||
# GLib.timeout_add(1000, update_labels)
|
|
||||||
self.set_default_size(400, 700)
|
|
||||||
self.set_title("Goldwarden")
|
|
||||||
|
|
||||||
def load(self):
|
|
||||||
builder = load_template("settings.ui")
|
|
||||||
self.edit_view = builder.get_object("window")
|
|
||||||
self.content = builder.get_object("content")
|
|
||||||
print(self.content)
|
|
||||||
# self.back_button = builder.get_object("back_button")
|
|
||||||
# self.back_button.connect("clicked", lambda _: self.navigate_callback("main", None))
|
|
||||||
# self.id_row = builder.get_object("id_row")
|
|
||||||
# self.name_row = builder.get_object("name_row")
|
|
||||||
# self.rclone_path_row = builder.get_object("rclone_path_row")
|
|
||||||
# self.password_row = builder.get_object("password_row")
|
|
||||||
# self.rclone_button = builder.get_object("rclone_row")
|
|
||||||
# self.rclone_button.connect("activated", lambda _: self.edit_rclone())
|
|
||||||
# self.save_button = builder.get_object("save_button")
|
|
||||||
# self.save_button.connect("clicked", lambda _: self.save())
|
|
||||||
# self.remove_button = builder.get_object("remove_button")
|
|
||||||
# self.remove_button.connect("clicked", lambda _: self.remove())
|
|
||||||
print(self.box)
|
|
||||||
print(self.content)
|
|
||||||
self.box.append(self.content)
|
|
||||||
return self.edit_view
|
|
||||||
|
|
||||||
|
|
||||||
class GoldwardenSettingsApp(Adw.Application):
|
class GoldwardenSettingsApp(Adw.Application):
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
|
@ -263,87 +27,73 @@ class GoldwardenSettingsApp(Adw.Application):
|
||||||
self.connect('activate', self.on_activate)
|
self.connect('activate', self.on_activate)
|
||||||
|
|
||||||
def on_activate(self, app):
|
def on_activate(self, app):
|
||||||
print("on activate")
|
self.load()
|
||||||
self.settings_win = SettingsWindow(application=app)
|
self.window.present()
|
||||||
self.settings_win.present()
|
GLib.timeout_add(100, self.update)
|
||||||
self.settings_win.load()
|
|
||||||
|
|
||||||
# def show_login():
|
def load(self):
|
||||||
# dialog = Gtk.Dialog(title="Goldwarden")
|
builder = load_template("settings.ui")
|
||||||
#
|
self.window = builder.get_object("window")
|
||||||
# auth_preference_group = Adw.PreferencesGroup()
|
self.window.set_application(self)
|
||||||
# auth_preference_group.set_title("Authentication")
|
self.stack = builder.get_object("stack")
|
||||||
# auth_preference_group.set_margin_top(10)
|
|
||||||
# auth_preference_group.set_margin_bottom(10)
|
|
||||||
# auth_preference_group.set_margin_start(10)
|
|
||||||
# auth_preference_group.set_margin_end(10)
|
|
||||||
# dialog.get_content_area().append(auth_preference_group)
|
|
||||||
#
|
|
||||||
# email_entry = Adw.EntryRow()
|
|
||||||
# email_entry.set_title("Email")
|
|
||||||
# email_entry.set_text("")
|
|
||||||
# auth_preference_group.add(email_entry)
|
|
||||||
#
|
|
||||||
# client_id_entry = Adw.EntryRow()
|
|
||||||
# client_id_entry.set_title("Client ID (optional)")
|
|
||||||
# client_id_entry.set_text("")
|
|
||||||
# auth_preference_group.add(client_id_entry)
|
|
||||||
#
|
|
||||||
# client_secret_entry = Adw.EntryRow()
|
|
||||||
# client_secret_entry.set_title("Client Secret (optional)")
|
|
||||||
# client_secret_entry.set_text("")
|
|
||||||
# auth_preference_group.add(client_secret_entry)
|
|
||||||
#
|
|
||||||
# dialog.add_button("Login", Gtk.ResponseType.OK)
|
|
||||||
# def on_save(res):
|
|
||||||
# if res != Gtk.ResponseType.OK:
|
|
||||||
# return
|
|
||||||
# goldwarden.set_url(url_entry.get_text())
|
|
||||||
# goldwarden.set_client_id(client_id_entry.get_text())
|
|
||||||
# goldwarden.set_client_secret(client_secret_entry.get_text())
|
|
||||||
# def login():
|
|
||||||
# res = goldwarden.login_with_password(email_entry.get_text(), "password")
|
|
||||||
# def handle_res():
|
|
||||||
# if res == "ok":
|
|
||||||
# dialog.close()
|
|
||||||
# # elif res == "badpass":
|
|
||||||
# # bad_pass_diag = Gtk.MessageDialog(transient_for=dialog, modal=True, message_type=Gtk.MessageType.ERROR, buttons=Gtk.ButtonsType.OK, text="Bad password")
|
|
||||||
# # bad_pass_diag.connect("response", lambda dialog, response: bad_pass_diag.close())
|
|
||||||
# # bad_pass_diag.present()
|
|
||||||
# GLib.idle_add(handle_res)
|
|
||||||
#
|
|
||||||
# login_thread = Thread(target=login)
|
|
||||||
# login_thread.start()
|
|
||||||
#
|
|
||||||
# preference_group = Adw.PreferencesGroup()
|
|
||||||
# preference_group.set_title("Config")
|
|
||||||
# preference_group.set_margin_top(10)
|
|
||||||
# preference_group.set_margin_bottom(10)
|
|
||||||
# preference_group.set_margin_start(10)
|
|
||||||
# preference_group.set_margin_end(10)
|
|
||||||
#
|
|
||||||
# dialog.get_content_area().append(preference_group)
|
|
||||||
#
|
|
||||||
# url_entry = Adw.EntryRow()
|
|
||||||
# url_entry.set_title("Base Url")
|
|
||||||
# url_entry.set_text("https://vault.bitwarden.com/")
|
|
||||||
# preference_group.add(url_entry)
|
|
||||||
#
|
|
||||||
# #ok response
|
|
||||||
# dialog.connect("response", lambda dialog, response: on_save(response))
|
|
||||||
# dialog.set_default_size(400, 200)
|
|
||||||
# dialog.set_modal(True)
|
|
||||||
# dialog.present()
|
|
||||||
|
|
||||||
isflatpak = os.path.exists("/.flatpak-info")
|
self.set_pin_status_box = builder.get_object("set_pin_status")
|
||||||
pathprefix = "/app/bin/" if isflatpak else "./"
|
self.set_pin_button = builder.get_object("set_pin_button")
|
||||||
css_provider = Gtk.CssProvider()
|
self.set_pin_button.connect("clicked", lambda x: goldwarden.enable_pin())
|
||||||
css_provider.load_from_path(pathprefix+"style.css")
|
|
||||||
Gtk.StyleContext.add_provider_for_display(
|
|
||||||
Gdk.Display.get_default(),
|
|
||||||
css_provider,
|
|
||||||
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
|
|
||||||
)
|
|
||||||
|
|
||||||
app = GoldwardenSettingsApp(application_id="com.quexten.Goldwarden.settings")
|
self.unlock_status_box = builder.get_object("unlock_status")
|
||||||
app.run(sys.argv)
|
self.unlock_button = builder.get_object("unlock_button")
|
||||||
|
self.unlock_button.connect("clicked", lambda x: goldwarden.unlock())
|
||||||
|
self.login_status_box = builder.get_object("login_status")
|
||||||
|
|
||||||
|
self.settings_view = builder.get_object("settings_view")
|
||||||
|
self.lock_button = builder.get_object("lock_button")
|
||||||
|
self.lock_button.connect("clicked", lambda x: goldwarden.lock())
|
||||||
|
self.logout_button = builder.get_object("logout_button")
|
||||||
|
self.logout_button.connect("clicked", lambda x: goldwarden.purge())
|
||||||
|
self.update_pin_button = builder.get_object("update_pin_button")
|
||||||
|
self.update_pin_button.connect("clicked", lambda x: goldwarden.enable_pin())
|
||||||
|
self.quickaccess_button = builder.get_object("quickaccess_button")
|
||||||
|
self.quickaccess_button.connect("clicked", lambda x: run_window("quickaccess", "Test"))
|
||||||
|
self.last_sync_row = builder.get_object("last_sync_row")
|
||||||
|
self.websocket_connected_row = builder.get_object("websocket_connected_row")
|
||||||
|
self.logins_row = builder.get_object("logins_row")
|
||||||
|
self.notes_row = builder.get_object("notes_row")
|
||||||
|
|
||||||
|
def update(self):
|
||||||
|
self.render()
|
||||||
|
return True
|
||||||
|
|
||||||
|
def render(self):
|
||||||
|
pin_set = goldwarden.is_pin_enabled()
|
||||||
|
status = goldwarden.get_vault_status()
|
||||||
|
runtimeCfg = goldwarden.get_runtime_config()
|
||||||
|
if status == None:
|
||||||
|
is_daemon_running = goldwarden.is_daemon_running()
|
||||||
|
if not is_daemon_running:
|
||||||
|
self.status_row.set_subtitle("Daemon not running")
|
||||||
|
self.vault_status_icon.set_icon("dialog-error", "error")
|
||||||
|
return
|
||||||
|
|
||||||
|
logged_in = status["loggedIn"]
|
||||||
|
unlocked = not status["locked"]
|
||||||
|
if not pin_set:
|
||||||
|
self.stack.set_visible_child(self.set_pin_status_box)
|
||||||
|
return
|
||||||
|
if not unlocked:
|
||||||
|
self.stack.set_visible_child(self.unlock_status_box)
|
||||||
|
return
|
||||||
|
if not logged_in:
|
||||||
|
self.stack.set_visible_child(self.login_status_box)
|
||||||
|
return
|
||||||
|
self.stack.set_visible_child(self.settings_view)
|
||||||
|
|
||||||
|
self.last_sync_row.set_subtitle(status["lastSynced"])
|
||||||
|
self.websocket_connected_row.set_subtitle("Yes" if status["websocketConnected"] else "No")
|
||||||
|
self.logins_row.set_subtitle(str(status["loginEntries"]))
|
||||||
|
self.notes_row.set_subtitle(str(status["noteEntries"]))
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
goldwarden.create_authenticated_connection(None)
|
||||||
|
app = GoldwardenSettingsApp(application_id="com.quexten.Goldwarden.settings")
|
||||||
|
app.run(sys.argv)
|
||||||
|
|
|
@ -0,0 +1,95 @@
|
||||||
|
using Gtk 4.0;
|
||||||
|
using Adw 1;
|
||||||
|
|
||||||
|
Adw.Window window {
|
||||||
|
default-width: 400;
|
||||||
|
default-height: 700;
|
||||||
|
|
||||||
|
Adw.ToolbarView view {
|
||||||
|
content: Box{
|
||||||
|
orientation: vertical;
|
||||||
|
Adw.Banner pin_banner {
|
||||||
|
title: 'No pin set, please set it now';
|
||||||
|
button-label: 'Set Pin';
|
||||||
|
revealed: false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScrolledWindow {
|
||||||
|
vexpand: true;
|
||||||
|
hexpand: true;
|
||||||
|
child: Box content {
|
||||||
|
orientation: vertical;
|
||||||
|
Adw.PreferencesPage preferences_page {
|
||||||
|
title: "General";
|
||||||
|
|
||||||
|
Adw.PreferencesGroup global_preferences_group {
|
||||||
|
title: "Global Shortcuts";
|
||||||
|
|
||||||
|
Adw.ActionRow autofill_row {
|
||||||
|
title: "Autofill Shortcut";
|
||||||
|
subtitle: "Not implemented - check the wiki for manual setup";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Adw.PreferencesGroup quick_access_preferences_group {
|
||||||
|
title: "Quick Access Shortcuts";
|
||||||
|
Adw.ActionRow {
|
||||||
|
title: "Copy Username Shortcut";
|
||||||
|
subtitle: "CTRL + U";
|
||||||
|
}
|
||||||
|
Adw.ActionRow {
|
||||||
|
title: "Autotype Username Shortcut";
|
||||||
|
subtitle: "CTRL + ALT + U";
|
||||||
|
}
|
||||||
|
Adw.ActionRow {
|
||||||
|
title: "Copy Password Shortcut";
|
||||||
|
subtitle: "CTRL + P";
|
||||||
|
}
|
||||||
|
Adw.ActionRow {
|
||||||
|
title: "Autotype Password Shortcut";
|
||||||
|
subtitle: "CTRL + ALT + P";
|
||||||
|
}
|
||||||
|
Adw.ActionRow {
|
||||||
|
title: "Copy TOTP Shortcut";
|
||||||
|
subtitle: "CTRL + T";
|
||||||
|
}
|
||||||
|
Adw.ActionRow {
|
||||||
|
title: "Autotype TOTP Shortcut";
|
||||||
|
subtitle: "CTRL + ALT + T";
|
||||||
|
}
|
||||||
|
Adw.ActionRow {
|
||||||
|
title: "Launch URI Shortcut";
|
||||||
|
subtitle: "CTRL + L";
|
||||||
|
}
|
||||||
|
Adw.ActionRow {
|
||||||
|
title: "Launch Web Vault Shortcut";
|
||||||
|
subtitle: "CTRL + V";
|
||||||
|
}
|
||||||
|
Adw.ActionRow {
|
||||||
|
title: "Focus Search Shortcut";
|
||||||
|
subtitle: "F";
|
||||||
|
}
|
||||||
|
Adw.ActionRow {
|
||||||
|
title: "Quit Shortcut";
|
||||||
|
subtitle: "Esc";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
[top]
|
||||||
|
Adw.HeaderBar {
|
||||||
|
halign: baseline;
|
||||||
|
|
||||||
|
title-widget: Adw.WindowTitle {
|
||||||
|
title: 'Settings';
|
||||||
|
};
|
||||||
|
|
||||||
|
valign: start;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,80 +1,32 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
import sys
|
||||||
import gi
|
import gi
|
||||||
|
|
||||||
gi.require_version('Gtk', '4.0')
|
gi.require_version('Gtk', '4.0')
|
||||||
gi.require_version('Adw', '1')
|
gi.require_version('Adw', '1')
|
||||||
import gc
|
|
||||||
import time
|
from gi.repository import Gtk, Adw, GLib, Gdk, Gio
|
||||||
from gi.repository import Gtk, Adw, GLib, Notify, Gdk
|
from ..services import goldwarden
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
import sys
|
from .template_loader import load_template
|
||||||
import os
|
import subprocess
|
||||||
from . import components
|
from . import components
|
||||||
|
import os
|
||||||
|
|
||||||
def add_action_row(parent, title, subtitle, icon=None):
|
class GoldwardenShortcutsSetupGuideApp(Adw.Application):
|
||||||
row = Adw.ActionRow()
|
|
||||||
row.set_title(title)
|
|
||||||
row.set_subtitle(subtitle)
|
|
||||||
if icon != None:
|
|
||||||
row.set_icon_name(icon)
|
|
||||||
parent.add(row)
|
|
||||||
return row
|
|
||||||
|
|
||||||
class MyApp(Adw.Application):
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
super().__init__(**kwargs)
|
super().__init__(**kwargs)
|
||||||
self.connect('activate', self.on_activate)
|
self.connect('activate', self.on_activate)
|
||||||
|
|
||||||
def on_activate(self, app):
|
def on_activate(self, app):
|
||||||
self.pinentry_window = MainWindow(application=app)
|
self.load()
|
||||||
self.pinentry_window.present()
|
self.window.present()
|
||||||
self.app = app
|
|
||||||
|
|
||||||
class MainWindow(Gtk.ApplicationWindow):
|
def load(self):
|
||||||
def __init__(self, *args, **kwargs):
|
builder = load_template("shortcuts.ui")
|
||||||
super().__init__(*args, **kwargs)
|
self.window = builder.get_object("window")
|
||||||
|
self.window.set_application(self)
|
||||||
|
|
||||||
# vertical box
|
if __name__ == "__main__":
|
||||||
self.box = Gtk.Box()
|
app = GoldwardenShortcutsSetupGuideApp(application_id="com.quexten.Goldwarden.shortcuts")
|
||||||
self.box.set_orientation(Gtk.Orientation.VERTICAL)
|
app.run(sys.argv)
|
||||||
self.set_child(self.box)
|
|
||||||
|
|
||||||
self.stack = Gtk.Stack()
|
|
||||||
self.stack.set_transition_type(Gtk.StackTransitionType.SLIDE_LEFT_RIGHT)
|
|
||||||
self.box.append(self.stack)
|
|
||||||
|
|
||||||
self.preferences_page = Adw.PreferencesPage()
|
|
||||||
self.preferences_page.set_title("General")
|
|
||||||
self.stack.add_named(self.preferences_page, "preferences_page")
|
|
||||||
|
|
||||||
self.global_preferences_group = Adw.PreferencesGroup()
|
|
||||||
self.global_preferences_group.set_title("Global Shortcuts")
|
|
||||||
self.preferences_page.add(self.global_preferences_group)
|
|
||||||
|
|
||||||
self.autofill_row = Adw.ActionRow()
|
|
||||||
self.autofill_row.set_title("Autofill Shortcut")
|
|
||||||
self.autofill_row.set_subtitle("Not implemented - check the wiki for manual setup")
|
|
||||||
self.global_preferences_group.add(self.autofill_row)
|
|
||||||
|
|
||||||
self.autofill_icon = components.StatusIcon()
|
|
||||||
self.autofill_icon.set_icon("dialog-warning", "warning")
|
|
||||||
self.autofill_row.add_prefix(self.autofill_icon)
|
|
||||||
|
|
||||||
self.quickaccess_preferences_group = Adw.PreferencesGroup()
|
|
||||||
self.quickaccess_preferences_group.set_title("Quick Access Shortcuts")
|
|
||||||
self.preferences_page.add(self.quickaccess_preferences_group)
|
|
||||||
|
|
||||||
add_action_row(self.quickaccess_preferences_group, "Copy Username Shortcut", "CTRL + U")
|
|
||||||
add_action_row(self.quickaccess_preferences_group, "Autotype Username Shortcut", "CTRL + ALT + U")
|
|
||||||
add_action_row(self.quickaccess_preferences_group, "Copy Password Shortcut", "CTRL + P")
|
|
||||||
add_action_row(self.quickaccess_preferences_group, "Autotype Password Shortcut", "CTRL + ALT + P")
|
|
||||||
add_action_row(self.quickaccess_preferences_group, "Copy TOTP Shortcut", "CTRL + T")
|
|
||||||
add_action_row(self.quickaccess_preferences_group, "Autotype TOTP Shortcut", "CTRL + ALT + T")
|
|
||||||
add_action_row(self.quickaccess_preferences_group, "Launch URI Shortcut", "CTRL+L")
|
|
||||||
add_action_row(self.quickaccess_preferences_group, "Launch Web Vault Shortcut", "CTRL+V")
|
|
||||||
add_action_row(self.quickaccess_preferences_group, "Focus Search Shortcut", "F")
|
|
||||||
add_action_row(self.quickaccess_preferences_group, "Quit Shortcut", "Esc")
|
|
||||||
|
|
||||||
self.set_default_size(700, 700)
|
|
||||||
self.set_title("Goldwarden Shortcuts")
|
|
||||||
|
|
||||||
app = MyApp(application_id="com.quexten.Goldwarden.shortcuts")
|
|
||||||
app.run(sys.argv)
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
using Gtk 4.0;
|
||||||
|
using Adw 1;
|
||||||
|
|
||||||
|
|
||||||
|
Adw.Window window {
|
||||||
|
default-width: 400;
|
||||||
|
default-height: 700;
|
||||||
|
|
||||||
|
Adw.ToolbarView view {
|
||||||
|
content: Box{
|
||||||
|
orientation: vertical;
|
||||||
|
ScrolledWindow {
|
||||||
|
vexpand: true;
|
||||||
|
hexpand: true;
|
||||||
|
child: Box content {
|
||||||
|
orientation: vertical;
|
||||||
|
Adw.PreferencesPage {
|
||||||
|
title: "General";
|
||||||
|
|
||||||
|
Adw.PreferencesGroup add_ssh_key_group {
|
||||||
|
title: "Add an SSH Key";
|
||||||
|
Adw.ActionRow add_ssh_key_row {
|
||||||
|
subtitle: "flatpak run --command=goldwarden com.quexten.Goldwarden ssh add --name MY_KEY_NAME";
|
||||||
|
subtitle-selectable: true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Adw.PreferencesGroup ssh_socket_path_group {
|
||||||
|
title: "SSH Socket Path";
|
||||||
|
description: "Add this to your environment variables";
|
||||||
|
Adw.ActionRow ssh_socket_path_row {
|
||||||
|
subtitle: "export SSH_AUTH_SOCK=/home/$USER/.var/app/com.quexten.Goldwarden/data/ssh-auth-sock";
|
||||||
|
subtitle-selectable: true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Adw.PreferencesGroup git_signing_group {
|
||||||
|
title: "Git Signing";
|
||||||
|
description: "Check the wiki for more information";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
[top]
|
||||||
|
Adw.HeaderBar {
|
||||||
|
halign: baseline;
|
||||||
|
|
||||||
|
title-widget: Adw.WindowTitle {
|
||||||
|
title: 'SSH Configuration';
|
||||||
|
};
|
||||||
|
|
||||||
|
valign: start;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,67 +1,32 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
import sys
|
||||||
import gi
|
import gi
|
||||||
|
|
||||||
gi.require_version('Gtk', '4.0')
|
gi.require_version('Gtk', '4.0')
|
||||||
gi.require_version('Adw', '1')
|
gi.require_version('Adw', '1')
|
||||||
import gc
|
|
||||||
import time
|
|
||||||
from gi.repository import Gtk, Adw, GLib, Notify, Gdk
|
|
||||||
from threading import Thread
|
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
from . import components
|
|
||||||
|
|
||||||
class MyApp(Adw.Application):
|
from gi.repository import Gtk, Adw, GLib, Gdk, Gio
|
||||||
|
from ..services import goldwarden
|
||||||
|
from threading import Thread
|
||||||
|
from .template_loader import load_template
|
||||||
|
import subprocess
|
||||||
|
from . import components
|
||||||
|
import os
|
||||||
|
|
||||||
|
class GoldwardenSSHSetupGuideApp(Adw.Application):
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
super().__init__(**kwargs)
|
super().__init__(**kwargs)
|
||||||
self.connect('activate', self.on_activate)
|
self.connect('activate', self.on_activate)
|
||||||
|
|
||||||
def on_activate(self, app):
|
def on_activate(self, app):
|
||||||
self.pinentry_window = MainWindow(application=app)
|
self.load()
|
||||||
self.pinentry_window.present()
|
self.window.present()
|
||||||
self.app = app
|
|
||||||
|
|
||||||
class MainWindow(Gtk.ApplicationWindow):
|
def load(self):
|
||||||
def __init__(self, *args, **kwargs):
|
builder = load_template("ssh.ui")
|
||||||
super().__init__(*args, **kwargs)
|
self.window = builder.get_object("window")
|
||||||
|
self.window.set_application(self)
|
||||||
|
|
||||||
# vertical box
|
if __name__ == "__main__":
|
||||||
self.box = Gtk.Box()
|
app = GoldwardenSSHSetupGuideApp(application_id="com.quexten.Goldwarden.sshsetup")
|
||||||
self.box.set_orientation(Gtk.Orientation.VERTICAL)
|
app.run(sys.argv)
|
||||||
self.set_child(self.box)
|
|
||||||
|
|
||||||
self.stack = Gtk.Stack()
|
|
||||||
self.stack.set_transition_type(Gtk.StackTransitionType.SLIDE_LEFT_RIGHT)
|
|
||||||
self.box.append(self.stack)
|
|
||||||
|
|
||||||
self.preferences_page = Adw.PreferencesPage()
|
|
||||||
self.preferences_page.set_title("General")
|
|
||||||
self.stack.add_named(self.preferences_page, "preferences_page")
|
|
||||||
|
|
||||||
self.add_ssh_key_group = Adw.PreferencesGroup()
|
|
||||||
self.add_ssh_key_group.set_title("Add an SSH Key")
|
|
||||||
self.preferences_page.add(self.add_ssh_key_group)
|
|
||||||
|
|
||||||
self.add_ssh_key_row = Adw.ActionRow()
|
|
||||||
self.add_ssh_key_row.set_subtitle("flatpak run --command=goldwarden com.quexten.Goldwarden ssh add --name MY_KEY_NAME")
|
|
||||||
self.add_ssh_key_row.set_subtitle_selectable(True)
|
|
||||||
self.add_ssh_key_group.add(self.add_ssh_key_row)
|
|
||||||
|
|
||||||
self.ssh_socket_path_group = Adw.PreferencesGroup()
|
|
||||||
self.ssh_socket_path_group.set_title("SSH Socket Path")
|
|
||||||
self.ssh_socket_path_group.set_description("Add this to your environment variables")
|
|
||||||
self.preferences_page.add(self.ssh_socket_path_group)
|
|
||||||
|
|
||||||
self.ssh_socket_path_row = Adw.ActionRow()
|
|
||||||
self.ssh_socket_path_row.set_subtitle("export SSH_AUTH_SOCK=/home/$USER/.var/app/com.quexten.Goldwarden/data/ssh-auth-sock")
|
|
||||||
self.ssh_socket_path_row.set_subtitle_selectable(True)
|
|
||||||
self.ssh_socket_path_group.add(self.ssh_socket_path_row)
|
|
||||||
|
|
||||||
self.git_signing_group = Adw.PreferencesGroup()
|
|
||||||
self.git_signing_group.set_title("Git Signing")
|
|
||||||
self.git_signing_group.set_description("Check the wiki for more information")
|
|
||||||
self.preferences_page.add(self.git_signing_group)
|
|
||||||
|
|
||||||
self.set_default_size(400, 700)
|
|
||||||
self.set_title("Goldwarden SSH Setup")
|
|
||||||
|
|
||||||
app = MyApp(application_id="com.quexten.Goldwarden.sshsetup")
|
|
||||||
app.run(sys.argv)
|
|
Loading…
Reference in New Issue