From dd0ab21a0cf906c33abde91f6a229952c164ca4a Mon Sep 17 00:00:00 2001 From: Cassidy James Blaede Date: Fri, 5 Jan 2024 16:22:21 -0700 Subject: [PATCH 1/8] MainWindow: Build about window from metainfo --- build-aux/meson/post_install.py | 25 --------------- data/gresource.xml | 3 +- data/metainfo.xml | 5 +++ meson.build | 7 ++--- src/App.vala | 10 ++---- src/MainWindow.vala | 56 +++++++++++++++------------------ 6 files changed, 37 insertions(+), 69 deletions(-) delete mode 100644 build-aux/meson/post_install.py diff --git a/build-aux/meson/post_install.py b/build-aux/meson/post_install.py deleted file mode 100644 index 6291b88..0000000 --- a/build-aux/meson/post_install.py +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env python3 - -import os -import subprocess - -prefix = os.environ.get('MESON_INSTALL_PREFIX', '/usr/local') -datadir = os.path.join(prefix, 'share') -schemadir = os.path.join(os.environ['MESON_INSTALL_PREFIX'], 'share', 'glib-2.0', 'schemas') - -# Packaging tools define DESTDIR and this isn't needed for them -if 'DESTDIR' not in os.environ: - print('Updating icon cache...') - icon_cache_dir = os.path.join(datadir, 'icons', 'hicolor') - if not os.path.exists(icon_cache_dir): - os.makedirs(icon_cache_dir) - subprocess.call(['gtk-update-icon-cache', '-qtf', icon_cache_dir]) - - print('Updating desktop database...') - desktop_database_dir = os.path.join(datadir, 'applications') - if not os.path.exists(desktop_database_dir): - os.makedirs(desktop_database_dir) - subprocess.call(['update-desktop-database', '-q', desktop_database_dir]) - - print('Compiling gsettings schemas...') - subprocess.call(['glib-compile-schemas', schemadir]) diff --git a/data/gresource.xml b/data/gresource.xml index dcb0d81..f54825f 100644 --- a/data/gresource.xml +++ b/data/gresource.xml @@ -1,6 +1,7 @@ - + + metainfo.xml style.css diff --git a/data/metainfo.xml b/data/metainfo.xml index 63b5818..498604a 100644 --- a/data/metainfo.xml +++ b/data/metainfo.xml @@ -55,6 +55,11 @@ + + +

Improved About window

+
+

Improved accessibility and fullscreen experience

diff --git a/meson.build b/meson.build index 5c64d71..98163cb 100644 --- a/meson.build +++ b/meson.build @@ -1,7 +1,8 @@ project( 'com.cassidyjames.butler', 'vala', 'c', - version: '1.0.1' + version: '1.0.2', + meson_version: '>=0.58', ) gnome = import('gnome') @@ -35,7 +36,7 @@ executable( dependencies: [ dependency('glib-2.0'), dependency('gtk4'), - dependency('libadwaita-1'), + dependency('libadwaita-1', version: '>=1.4.2'), dependency('webkitgtk-6.0'), meson.get_compiler('vala').find_library('posix'), ], @@ -43,5 +44,3 @@ executable( ) subdir('data') - -meson.add_install_script('build-aux' / 'meson'/ 'post_install.py') \ No newline at end of file diff --git a/src/App.vala b/src/App.vala index 38050a0..c2b4c40 100644 --- a/src/App.vala +++ b/src/App.vala @@ -4,17 +4,10 @@ */ public class Butler.App : Adw.Application { - public const string NAME = "Butler"; - public const string DEVELOPER = "Cassidy James Blaede"; - public const string EMAIL = "c@ssidyjam.es"; - public const string URL = "https://cassidyjames.com"; - public static GLib.Settings settings; public App () { - Object ( - application_id: APP_ID - ); + Object ( application_id: APP_ID ); } public static App _instance = null; @@ -67,3 +60,4 @@ public class Butler.App : Adw.Application { return app.run (args); } } + diff --git a/src/MainWindow.vala b/src/MainWindow.vala index 95f0fc7..3907009 100644 --- a/src/MainWindow.vala +++ b/src/MainWindow.vala @@ -4,6 +4,7 @@ */ public class Butler.MainWindow : Adw.ApplicationWindow { + public Adw.AboutWindow about_window; public Adw.Toast fullscreen_toast; public Adw.ToastOverlay toast_overlay; public Gtk.Revealer header_revealer; @@ -21,9 +22,7 @@ public class Butler.MainWindow : Adw.ApplicationWindow { Object ( application: application, height_request: 180, - icon_name: APP_ID, resizable: true, - title: App.NAME, width_request: 300 ); add_action_entries (ACTION_ENTRIES, this); @@ -33,6 +32,27 @@ public class Butler.MainWindow : Adw.ApplicationWindow { maximized = App.settings.get_boolean ("window-maximized"); fullscreened = App.settings.get_boolean ("window-fullscreened"); + about_window = new Adw.AboutWindow.from_appdata ( + "/com/cassidyjames/butler/metainfo.xml", VERSION + ) { + transient_for = this, + hide_on_close = true, + + /// The translator credits. Please translate this with your name(s). + translator_credits = _("translator-credits"), + }; + about_window.copyright = "© 2020–%i %s".printf ( + new DateTime.now_local ().get_year (), + about_window.developer_name + ); + about_window.add_link (_("About Home Assistant"), "https://www.home-assistant.io/"); + about_window.add_link (_("Home Assistant Privacy Policy"), "https://www.home-assistant.io/privacy/"); + + // Set MainWindow properties from the AppData already fetched and parsed + // by the AboutWindow construction + icon_name = about_window.application_icon; + title = about_window.application_name; + var site_menu = new Menu (); site_menu.append (_("_Log Out…"), "win.log_out"); @@ -40,7 +60,7 @@ public class Butler.MainWindow : Adw.ApplicationWindow { // TODO: How do I add shortcuts to the menu? app_menu.append (_("_Fullscreen"), "win.toggle_fullscreen"); app_menu.append (_("Change _Server…"), "win.set_server"); - app_menu.append (_("_About %s").printf (App.NAME), "win.about"); + app_menu.append (_("_About %s").printf (title), "win.about"); var menu = new Menu (); menu.append_section (null, site_menu); @@ -76,7 +96,7 @@ public class Butler.MainWindow : Adw.ApplicationWindow { } var status_page = new Adw.StatusPage () { - title = _("%s for Home Assistant").printf (App.NAME), + title = title, description = _("Loading the dashboard…"), icon_name = APP_ID }; @@ -282,33 +302,7 @@ public class Butler.MainWindow : Adw.ApplicationWindow { } private void on_about_activate () { - var about_window = new Adw.AboutWindow () { - transient_for = this, - - application_icon = APP_ID, - application_name = _("%s for Home Assistant").printf (App.NAME), - developer_name = App.DEVELOPER, - version = VERSION, - - comments = _("Butler is a hybrid native + web app for your Home Assistant dashboard"), - - website = App.URL, - issue_url = "https://github.com/cassidyjames/butler/issues", - - // Credits - developers = { "%s <%s>".printf (App.DEVELOPER, App.EMAIL) }, - designers = { "%s %s".printf (App.DEVELOPER, App.URL) }, - - /// The translator credits. Please translate this with your name(s). - translator_credits = _("translator-credits"), - - // Legal - copyright = "Copyright © 2020–2024 %s".printf (App.DEVELOPER), - license_type = Gtk.License.GPL_3_0, - }; - about_window.add_link (_("About Home Assistant"), "https://www.home-assistant.io/"); - about_window.add_link (_("Home Assistant Privacy Policy"), "https://www.home-assistant.io/privacy/"); - about_window.present (); } } + From d253561f54fdefcf3bef8d38029ee5ddec067d9e Mon Sep 17 00:00:00 2001 From: Cassidy James Blaede Date: Fri, 5 Jan 2024 16:36:01 -0700 Subject: [PATCH 2/8] MainWindow: Prepend http:// if no protocol --- src/MainWindow.vala | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/MainWindow.vala b/src/MainWindow.vala index 3907009..306afe0 100644 --- a/src/MainWindow.vala +++ b/src/MainWindow.vala @@ -80,7 +80,7 @@ public class Butler.MainWindow : Adw.ApplicationWindow { reveal_child = !fullscreened }; - fullscreen_toast = new Adw.Toast ("Press Ctrl F or F11 to toggle fullscreen") { + fullscreen_toast = new Adw.Toast (_("Press Ctrl F or F11 to toggle fullscreen")) { action_name = "win.toggle_fullscreen", button_label = _("Exit _Fullscreen") }; @@ -240,14 +240,14 @@ public class Butler.MainWindow : Adw.ApplicationWindow { var server_dialog = new Adw.MessageDialog ( this, - "Set Server URL", - "Enter the full URL including protocol (e.g. http://) and any custom port (e.g. :8123)" + _("Set Server URL"), + _("Enter the full URL including any custom port") ) { body_use_markup = true, default_response = "save", extra_child = server_entry, }; - server_dialog.add_response ("close", "_Cancel"); + server_dialog.add_response ("close", _("_Cancel")); server_dialog.add_response ("demo", _("_Reset to Demo")); server_dialog.set_response_appearance ("demo", Adw.ResponseAppearance.DESTRUCTIVE); @@ -265,6 +265,10 @@ public class Butler.MainWindow : Adw.ApplicationWindow { new_server = default_server; } + if (!new_server.contains ("://")) { + new_server = "http://" + new_server; + } + if (new_server != current_server) { // FIXME: There's currently no validation of this App.settings.set_string ("server", new_server); @@ -282,13 +286,13 @@ public class Butler.MainWindow : Adw.ApplicationWindow { var log_out_dialog = new Adw.MessageDialog ( this, - "Log out of Home Assistant?", - "You will need to re-enter your username and password for %s to log back in.".printf (server) + _("Log out of Home Assistant?"), + _("You will need to re-enter your username and password for %s to log back in.").printf (server) ) { body_use_markup = true, default_response = "log_out" }; - log_out_dialog.add_response ("close", "_Stay Logged In"); + log_out_dialog.add_response ("close", _("_Stay Logged In")); log_out_dialog.add_response ("log_out", _("_Log Out")); log_out_dialog.set_response_appearance ("log_out", Adw.ResponseAppearance.DESTRUCTIVE); From e7183e791a6ccc6dace9b1250183b0f8e9717d9e Mon Sep 17 00:00:00 2001 From: Cassidy James Blaede Date: Fri, 5 Jan 2024 16:40:01 -0700 Subject: [PATCH 3/8] Lint: remove extra newlines --- data/metainfo.xml | 10 +++++++++- src/App.vala | 1 - src/MainWindow.vala | 1 - 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/data/metainfo.xml b/data/metainfo.xml index 498604a..028a1db 100644 --- a/data/metainfo.xml +++ b/data/metainfo.xml @@ -57,8 +57,16 @@ -

Improved About window

+

Small improvements

+
    +
  • Improved about window
  • +
  • Automatically prepend http:// to custom server if omitted
  • +
  • Start preparing for translations
  • +
+ + Automatically prepend http:// to custom server if omitted +
diff --git a/src/App.vala b/src/App.vala index c2b4c40..dda9699 100644 --- a/src/App.vala +++ b/src/App.vala @@ -60,4 +60,3 @@ public class Butler.App : Adw.Application { return app.run (args); } } - diff --git a/src/MainWindow.vala b/src/MainWindow.vala index 306afe0..26b250f 100644 --- a/src/MainWindow.vala +++ b/src/MainWindow.vala @@ -309,4 +309,3 @@ public class Butler.MainWindow : Adw.ApplicationWindow { about_window.present (); } } - From e6f68fe72c950d5ca1508e8584c205c171845e71 Mon Sep 17 00:00:00 2001 From: Cassidy James Blaede Date: Fri, 5 Jan 2024 17:04:06 -0700 Subject: [PATCH 4/8] Metainfo: Better follow guidelines --- data/metainfo.xml | 7 ++++--- src/MainWindow.vala | 1 + 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/data/metainfo.xml b/data/metainfo.xml index 028a1db..9ebfef0 100644 --- a/data/metainfo.xml +++ b/data/metainfo.xml @@ -5,14 +5,14 @@ CC-BY-SA-4.0 GPL-3.0-or-later - Butler for Home Assistant - Control your smart home + Butler + Access your Home Assistant dashboard Cassidy James Blaede Cassidy James Blaede -

Hybrid native + web app for Home Assistant. Butler wraps your Home Assistant dashboard up in a native UI, integrating better with your OS. Native features include:

+

Hybrid native + web companion app for Home Assistant. Butler wraps your dashboard up in a native UI, integrating better with your OS. Native features include:

  • Icon in your App Grid, Applications Menu, Dash, Dock, etc.
  • Native header bar
  • @@ -20,6 +20,7 @@
  • Two-finger swipe and mouse button support to go back/forward between views
  • Cross-desktop light/dark style support (if supported by your Lovelace theme)
+

Butler is designed to make getting at your Home Assistant dashboard easier for kiosks, your laptop/desktop, or your Linux phone. It does not support companion app features from Android and iOS like location services, notifications, or exposing device sensors.

Other features include:

  • Pinch-to-zoom
  • diff --git a/src/MainWindow.vala b/src/MainWindow.vala index 26b250f..41421cb 100644 --- a/src/MainWindow.vala +++ b/src/MainWindow.vala @@ -37,6 +37,7 @@ public class Butler.MainWindow : Adw.ApplicationWindow { ) { transient_for = this, hide_on_close = true, + comments = _("Companion app to access your Home Assistant dashboard"), /// The translator credits. Please translate this with your name(s). translator_credits = _("translator-credits"), From 8c098a7f35808a8f89f83d287c27ed0041043c9b Mon Sep 17 00:00:00 2001 From: Cassidy James Blaede Date: Fri, 5 Jan 2024 23:17:18 -0700 Subject: [PATCH 5/8] WebView: Open new-window links externally --- src/Widgets/WebView.vala | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/src/Widgets/WebView.vala b/src/Widgets/WebView.vala index 0a6c83d..44961e4 100644 --- a/src/Widgets/WebView.vala +++ b/src/Widgets/WebView.vala @@ -9,8 +9,7 @@ public class Butler.WebView : WebKit.WebView { public WebView () { Object ( hexpand: true, - vexpand: true, - user_content_manager: new WebKit.UserContentManager () + vexpand: true ); } @@ -30,28 +29,25 @@ public class Butler.WebView : WebKit.WebView { hardware_acceleration_policy = WebKit.HardwareAccelerationPolicy.ALWAYS }; - var custom_css = new WebKit.UserStyleSheet ( - """ - header, - .header { - app-region: drag; - -webkit-app-region: drag; - } - """, - WebKit.UserContentInjectedFrames.TOP_FRAME, - WebKit.UserStyleLevel.AUTHOR, - null, - null - ); - user_content_manager.add_style_sheet (custom_css); - settings = webkit_settings; - web_context = new WebKit.WebContext (); context_menu.connect (() => { return !is_terminal; }); + decide_policy.connect ((decision, type) => { + if (type == WebKit.PolicyDecisionType.NEW_WINDOW_ACTION) { + try { + new Gtk.UriLauncher ( + ((WebKit.NavigationPolicyDecision)decision). + navigation_action.get_request ().get_uri () + ).launch.begin (null, null); + } catch (Error e) { + critical ("Unable to open externally"); + } + } + }); + var back_click_gesture = new Gtk.GestureClick () { button = 8 }; @@ -65,3 +61,4 @@ public class Butler.WebView : WebKit.WebView { add_controller (forward_click_gesture); } } + From bed99197c77825f011b5d013a4a5915e92a880ab Mon Sep 17 00:00:00 2001 From: Cassidy James Blaede Date: Fri, 5 Jan 2024 23:17:44 -0700 Subject: [PATCH 6/8] MainWindow: Add home button and demo banner --- src/MainWindow.vala | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/src/MainWindow.vala b/src/MainWindow.vala index 41421cb..3d6f52b 100644 --- a/src/MainWindow.vala +++ b/src/MainWindow.vala @@ -5,9 +5,11 @@ public class Butler.MainWindow : Adw.ApplicationWindow { public Adw.AboutWindow about_window; + public Adw.Banner demo_banner; public Adw.Toast fullscreen_toast; public Adw.ToastOverlay toast_overlay; public Gtk.Revealer header_revealer; + public Gtk.Revealer home_revealer; private const GLib.ActionEntry[] ACTION_ENTRIES = { { "toggle_fullscreen", toggle_fullscreen }, @@ -54,6 +56,15 @@ public class Butler.MainWindow : Adw.ApplicationWindow { icon_name = about_window.application_icon; title = about_window.application_name; + var home_button = new Gtk.Button.from_icon_name ("go-home-symbolic") { + tooltip_text = _("Go Home") + }; + + home_revealer = new Gtk.Revealer () { + child = home_button, + transition_type = Gtk.RevealerTransitionType.SLIDE_RIGHT + }; + var site_menu = new Menu (); site_menu.append (_("_Log Out…"), "win.log_out"); @@ -74,6 +85,7 @@ public class Butler.MainWindow : Adw.ApplicationWindow { }; var header = new Adw.HeaderBar (); + header.pack_start (home_revealer); header.pack_end (menu_button); header_revealer = new Gtk.Revealer () { @@ -81,6 +93,11 @@ public class Butler.MainWindow : Adw.ApplicationWindow { reveal_child = !fullscreened }; + demo_banner = new Adw.Banner (_("Browsing Home Assistant Demo")) { + action_name = "win.set_server", + button_label = _("Set _Server…") + }; + fullscreen_toast = new Adw.Toast (_("Press Ctrl F or F11 to toggle fullscreen")) { action_name = "win.toggle_fullscreen", button_label = _("Exit _Fullscreen") @@ -120,6 +137,7 @@ public class Butler.MainWindow : Adw.ApplicationWindow { }; grid.attach (header_revealer, 0, 0); grid.attach (toast_overlay, 0, 1); + grid.attach (demo_banner, 0, 2); set_content (grid); @@ -128,6 +146,10 @@ public class Butler.MainWindow : Adw.ApplicationWindow { set_default_size (window_width, window_height); + home_button.clicked.connect (() => { + web_view.load_uri (server); + }); + close_request.connect (() => { save_window_state (); return Gdk.EVENT_PROPAGATE; @@ -169,7 +191,20 @@ public class Butler.MainWindow : Adw.ApplicationWindow { if (web_view.is_loading) { // TODO: Add a loading progress bar or spinner somewhere? } else { - App.settings.set_string ("current-url", web_view.uri); + string default_server = App.settings.get_default_value ("server").get_string (); + string server = App.settings.get_string ("server"); + string current_url = web_view.uri; + + App.settings.set_string ("current-url", current_url); + + if (current_url.has_prefix (default_server)) { + demo_banner.revealed = true; + } else if (current_url.has_prefix (server)) { + demo_banner.revealed = false; + } else { + demo_banner.revealed = false; + home_revealer.set_reveal_child (true); + } } } From f34878018305fa2492525ade4924fd326bf4f16d Mon Sep 17 00:00:00 2001 From: Cassidy James Blaede Date: Fri, 5 Jan 2024 23:18:55 -0700 Subject: [PATCH 7/8] Lint: remove trailing newline --- src/Widgets/WebView.vala | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Widgets/WebView.vala b/src/Widgets/WebView.vala index 44961e4..7c5fe90 100644 --- a/src/Widgets/WebView.vala +++ b/src/Widgets/WebView.vala @@ -61,4 +61,3 @@ public class Butler.WebView : WebKit.WebView { add_controller (forward_click_gesture); } } - From c562dd87b316e0fc07c258648a5ed7f7a195e233 Mon Sep 17 00:00:00 2001 From: Cassidy James Blaede Date: Fri, 5 Jan 2024 23:30:52 -0700 Subject: [PATCH 8/8] Metainfo: Update 1.0.2 release info --- data/metainfo.xml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/data/metainfo.xml b/data/metainfo.xml index 9ebfef0..78866da 100644 --- a/data/metainfo.xml +++ b/data/metainfo.xml @@ -56,16 +56,19 @@ - +

    Small improvements

    • Improved about window
    • +
    • Open links in default browser
    • Automatically prepend http:// to custom server if omitted
    • Start preparing for translations
    + Better onboarding + Open links in default browser Automatically prepend http:// to custom server if omitted