Skip to content

Commit

Permalink
Merge libsoup async implementation (#236)
Browse files Browse the repository at this point in the history
  • Loading branch information
rafaelmardojai committed Feb 23, 2022
2 parents 820e1a1 + 1b9c08d commit a309c32
Show file tree
Hide file tree
Showing 8 changed files with 908 additions and 555 deletions.
55 changes: 53 additions & 2 deletions data/resources/window.ui
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,6 @@
</child>
<child>
<object class="AdwStatusPage" id="error_page">
<property name="title">Could not load the translator service</property>
<property name="vexpand">True</property>
<property name="child">
<object class="GtkBox">
Expand All @@ -102,7 +101,59 @@
</child>
<child>
<object class="GtkButton">
<property name="label" translatable="yes">Open preferences</property>
<property name="label" translatable="yes">Open Preferences</property>
<property name="action-name">app.preferences</property>
<style>
<class name="pill" />
</style>
</object>
</child>
</object>
</property>
</object>
</child>
</object>
</property>
</object>
</property>
</object>
</child>
<child>
<object class="GtkStackPage">
<property name="name">api-key</property>
<property name="child">
<object class="GtkWindowHandle">
<property name="child">
<object class="GtkBox">
<property name="orientation">vertical</property>
<child>
<object class="AdwHeaderBar">
<style>
<class name="flat" />
</style>
</object>
</child>
<child>
<object class="AdwStatusPage" id="key_page">
<property name="icon-name">dialog-password-symbolic</property>
<property name="vexpand">True</property>
<property name="child">
<object class="GtkBox">
<property name="spacing">12</property>
<property name="halign">center</property>
<child>
<object class="GtkButton" id="rmv_key_btn">
<property name="visible">False</property>
<property name="label" translatable="yes">Remove Key and Retry</property>
<style>
<class name="pill" />
<class name="suggested-action" />
</style>
</object>
</child>
<child>
<object class="GtkButton">
<property name="label" translatable="yes">Open Preferences</property>
<property name="action-name">app.preferences</property>
<style>
<class name="pill" />
Expand Down
13 changes: 12 additions & 1 deletion dialect/lang_selector.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
@Gtk.Template(resource_path=f'{RES_PATH}/lang-selector.ui')
class DialectLangSelector(Gtk.Popover):
__gtype_name__ = 'DialectLangSelector'
__gsignals__ = {
'user-selection-changed': (GObject.SIGNAL_RUN_LAST, GObject.TYPE_NONE, ())
}

# Get widgets
search = Gtk.Template.Child()
Expand Down Expand Up @@ -55,6 +58,14 @@ def __init__(self, **kwargs):
self.lang_list.set_model(selection_model)
self.lang_list.set_factory(self.factory)

def get_selected(self):
return self.get_property('selected')

def set_selected(self, lang_code, notify=True):
self.set_property('selected', lang_code)
if notify:
self.emit('user-selection-changed')

def set_languages(self, languages):
# Clear list
self.lang_model.remove_all()
Expand All @@ -80,7 +91,7 @@ def _activated(self, list_view, index):
model = list_view.get_model()
lang = model.get_selected_item()
# Set selected property
self.set_property('selected', lang.code)
self.set_selected(lang.code)

def _closed(self, _popover):
# Reset scroll
Expand Down
1 change: 1 addition & 0 deletions dialect/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ sources = [
'window.py',
'preferences.py',
'lang_selector.py',
'session.py',
'settings.py',
'shortcuts.py',
]
Expand Down
197 changes: 106 additions & 91 deletions dialect/preferences.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@
# Copyright 2020-2021 Rafael Mardojai CM
# SPDX-License-Identifier: GPL-3.0-or-later

import logging
import os
import re
import threading
from gettext import gettext as _

from gi.repository import Adw, Gio, GLib, GObject, Gtk
from gi.repository import Adw, Gio, GLib, GObject, Gtk, Soup

from dialect.define import RES_PATH
from dialect.session import Session
from dialect.settings import Settings
from dialect.translators import TRANSLATORS
from dialect.tts import TTS
Expand Down Expand Up @@ -161,7 +163,7 @@ def _on_settings_changed(self, _settings, key):
if key == 'instance-url' and TRANSLATORS[backend].supported_features['change-instance']:
Settings.get().reset_src_langs()
Settings.get().reset_dest_langs()
self.parent.change_backends(backend)
self.parent.reload_backends()

def _toggle_dark_mode(self, switch, _active):
active = switch.get_active()
Expand Down Expand Up @@ -197,36 +199,85 @@ def _switch_backends(self, row, _value):
backend = self.backend_model[row.get_selected()].name
Settings.get().active_translator = backend
self.__check_instance_or_api_key_support()
self.parent.change_backends(backend)
self.parent.reload_backends()

def _on_backend_loading(self, window, _value):
self.backend.set_sensitive(not window.get_property('backend-loading'))
self.backend_instance_row.set_sensitive(not window.get_property('backend-loading'))
self.api_key_row.set_sensitive(not window.get_property('backend-loading'))

# Show or hide api key entry
if not window.get_property('backend-loading') and window.translator:
if window.translator.supported_features['api-key-supported']:
self.api_key_row.set_visible(True)
self.api_key_label.set_label(Settings.get().api_key or 'None')
else:
self.api_key_row.set_visible(False)

def _on_edit_backend_instance(self, _button):
self.backend_instance_stack.set_visible_child_name('edit')
self.backend_instance.set_text(Settings.get().instance_url)

def _on_save_backend_instance(self, _button):
def on_validation_response(session, result):
valid = False
backend = Settings.get().active_translator
try:
data = Session.get_response(session, result)
valid = TRANSLATORS[backend].validate_instance(data)
except Exception as exc:
logging.error(exc)

if valid:
Settings.get().instance_url = self.new_instance_url
self.backend_instance.get_style_context().remove_class('error')
self.backend_instance_stack.set_visible_child_name('view')
# self.error_popover.popdown()
else:
self.backend_instance.get_style_context().add_class('error')
error_text = _('Not a valid {backend} instance')
error_text = error_text.format(backend=TRANSLATORS[backend].prettyname)
self.error_label.set_label(error_text)
# self.error_popover.popup()
self.api_key_row.set_visible(False)
self.api_key_label.set_label('None')

self.backend.set_sensitive(True)
self.backend_instance_row.set_sensitive(True)
self.api_key_row.set_sensitive(True)
self.backend_instance_save.set_child(self.instance_save_image)
self.backend_instance_label.set_label(Settings.get().instance_url)
self.instance_save_spinner.stop()

old_value = Settings.get().instance_url
new_value = self.backend_instance.get_text()

url = re.compile(r'https?://(www\.)?')
new_value = url.sub('', new_value).strip().strip('/')
self.new_instance_url = url.sub('', new_value).strip().strip('/')

if new_value != old_value:
# Validate
threading.Thread(
target=self.__validate_new_backend_instance,
args=[new_value],
daemon=True
).start()
# Validate
if self.new_instance_url != old_value:
# Progress feedback
self.backend.set_sensitive(False)
self.backend_instance_row.set_sensitive(False)
self.api_key_row.set_sensitive(False)
self.backend_instance_save.set_child(self.instance_save_spinner)
self.instance_save_spinner.start()

backend = Settings.get().active_translator
validation_url = TRANSLATORS[backend].format_instance_url(
self.new_instance_url,
TRANSLATORS[backend].validation_path
)
validation_message = Soup.Message.new('GET', validation_url)

Session.get().send_and_read_async(validation_message, 0, None, on_validation_response)
else:
self.backend_instance_stack.set_visible_child_name('view')

def _on_reset_backend_instance(self, _button):
Settings.get().reset_instance_url()
Settings.get().reset_api_key()
self.backend_instance_label.set_label(Settings.get().instance_url)
self.backend_instance_stack.set_visible_child_name('view')
self.backend_instance.get_style_context().remove_class('error')
Expand All @@ -237,16 +288,52 @@ def _on_edit_api_key(self, _button):
self.api_key.set_text(Settings.get().api_key)

def _on_save_api_key(self, _button):
def on_response(session, result):
valid = False
try:
data = Session.get_response(session, result)
self.parent.translator.get_translation(data)
valid = True
except Exception as exc:
logging.warning(exc)

if valid:
Settings.get().api_key = self.new_api_key
self.api_key.get_style_context().remove_class('error')
self.api_key_stack.set_visible_child_name('view')
else:
self.api_key.get_style_context().add_class('error')
error_text = _('Not a valid {backend} API key')
error_text = error_text.format(backend=TRANSLATORS[backend].prettyname)
self.error_label.set_label(error_text)

self.backend.set_sensitive(True)
self.backend_instance_row.set_sensitive(True)
self.api_key_row.set_sensitive(True)
self.api_key_save.set_child(self.api_key_save_image)
self.api_key_label.set_label(Settings.get().api_key or 'None')
self.instance_save_spinner.stop()

old_value = Settings.get().api_key
new_value = self.api_key.get_text()
self.new_api_key = self.api_key.get_text()

if new_value != old_value:
# Validate
threading.Thread(
target=self.__validate_new_api_key,
args=[new_value],
daemon=True
).start()
if self.new_api_key != old_value:
# Progress feedback
self.backend.set_sensitive(False)
self.backend_instance_row.set_sensitive(False)
self.api_key_row.set_sensitive(False)
self.api_key_save.set_child(self.api_key_save_spinner)
self.api_key_save_spinner.start()

backend = Settings.get().active_translator
validation_url = TRANSLATORS[backend].format_instance_url(
Settings.get().instance_url,
TRANSLATORS[backend].api_test_path
)
(data, headers) = TRANSLATORS[backend].format_api_key_test(self.new_api_key)
message = Session.create_post_message(validation_url, data, headers)

Session.get().send_and_read_async(message, 0, None, on_response)
else:
self.api_key_stack.set_visible_child_name('view')

Expand All @@ -271,78 +358,6 @@ def __check_instance_or_api_key_support(self):
else:
self.api_key_row.set_visible(False)

def __validate_new_backend_instance(self, url):
def spinner_start():
self.backend.set_sensitive(False)
self.backend_instance_row.set_sensitive(False)
self.api_key_row.set_sensitive(False)
self.backend_instance_save.set_child(self.instance_save_spinner)
self.instance_save_spinner.start()

def spinner_end():
self.backend.set_sensitive(True)
self.backend_instance_row.set_sensitive(True)
self.api_key_row.set_sensitive(True)
self.backend_instance_save.set_child(self.instance_save_image)
self.backend_instance_label.set_label(Settings.get().instance_url)
self.instance_save_spinner.stop()

GLib.idle_add(spinner_start)
backend = Settings.get().active_translator
result = TRANSLATORS[backend].validate_instance_url(url)
if result['validation-success']:
Settings.get().instance_url = url
GLib.idle_add(self.backend_instance.get_style_context().remove_class, 'error')
GLib.idle_add(self.backend_instance_stack.set_visible_child_name, 'view')
# GLib.idle_add(self.error_popover.popdown)
if result['api-key-supported']:
Settings.get().reset_api_key()
self.api_key_row.set_visible(True)
self.api_key_label.set_label(Settings.get().api_key or 'None')
else:
self.api_key_row.set_visible(False)
else:
GLib.idle_add(self.backend_instance.get_style_context().add_class, 'error')
error_text = _('Not a valid {backend} instance')
error_text = error_text.format(backend=TRANSLATORS[backend].prettyname)
GLib.idle_add(self.error_label.set_label, error_text)
# GLib.idle_add(self.error_popover.popup)
self.api_key_row.set_visible(False)
self.api_key_label.set_label('None')

GLib.idle_add(spinner_end)

def __validate_new_api_key(self, api_key):
def spinner_start():
self.backend.set_sensitive(False)
self.backend_instance_row.set_sensitive(False)
self.api_key_row.set_sensitive(False)
self.api_key_save.set_child(self.api_key_save_spinner)
self.api_key_save_spinner.start()

def spinner_end():
self.backend.set_sensitive(True)
self.backend_instance_row.set_sensitive(True)
self.api_key_row.set_sensitive(True)
self.api_key_save.set_child(self.api_key_save_image)
self.api_key_label.set_label(Settings.get().api_key or 'None')
self.instance_save_spinner.stop()

GLib.idle_add(spinner_start)
backend = Settings.get().active_translator
result = TRANSLATORS[backend].validate_api_key(api_key, Settings.get().instance_url)
if result:
Settings.get().api_key = api_key
GLib.idle_add(self.api_key.get_style_context().remove_class, 'error')
GLib.idle_add(self.api_key_stack.set_visible_child_name, 'view')
else:
GLib.idle_add(self.api_key.get_style_context().add_class, 'error')
error_text = _('Not a valid {backend} API key')
error_text = error_text.format(backend=TRANSLATORS[backend].prettyname)
GLib.idle_add(self.error_label.set_label, error_text)

GLib.idle_add(spinner_end)


class BackendObject(GObject.Object):
__gtype_name__ = 'BackendObject'
Expand Down
Loading

0 comments on commit a309c32

Please sign in to comment.