Skip to content

Commit

Permalink
Save and restore state (#21)
Browse files Browse the repository at this point in the history
* MainWindow: Save and restore state to fix #20

* Save and restore URL

* Update README and metainfo

* Bump version
  • Loading branch information
cassidyjames authored Feb 19, 2021
1 parent 617ec3b commit ac72e4f
Show file tree
Hide file tree
Showing 8 changed files with 121 additions and 41 deletions.
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@ Hybrid native + web app for [Plausible Analytics](https://plausible.io). Designe
Plausible is the simple privacy-friendly alternative to Google Analytics. This app wraps the Plausible web app in a native UI, integrating better with desktop operating systems like elementary OS. Native features include:

- Icon in your Applications Menu, Dock, etc.
- Native header bar replaces web app UI
- Native buttons to go to account settings and log out
- Slimmed down web app UI (no header or footer with external links)
- Native header bar with buttons for account settings and logging out
- Save and restore current view, size, and position when closed and opened
- Two-finger swipe to go back/forward between views

Other features:

- Zoom in/out with Ctrl+Plus/Minus, and it's remembered the next time you use the app
- Slimmed down web app UI (no header or footer with external links)


## Developing and Building

Expand Down
2 changes: 1 addition & 1 deletion data/gresource.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/com/cassidyjames/plausible">
<file alias="Application.css">styles/Application.css</file>
<file alias="App.css">styles/App.css</file>
<file alias="logo-dark.png">logo-dark.png</file>
</gresource>
</gresources>
20 changes: 20 additions & 0 deletions data/gschema.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<schemalist>
<schema path="/com/cassidyjames/plausible/" id="com.cassidyjames.plausible">
<key name="current-url" type="s">
<default>""</default>
<summary>Current URL</summary>
<description>The last-viewed URL for restoring state</description>
</key>
<key name="window-maximized" type="b">
<default>false</default>
<summary>Window maximized</summary>
<description>Whether the window was maximized on last run</description>
</key>
<key name="window-position" type="(ii)">
<default>(-1, -1)</default>
<summary>Window position</summary>
<description>Most recent window position (x, y)</description>
</key>
<key name="window-size" type="(ii)">
<default>(1000, 700)</default>
<summary>Window size</summary>
<description>Most recent window size (width, height)</description>
</key>
<key name="zoom" type="d">
<default>1.0</default>
<summary>Zoom level</summary>
Expand Down
18 changes: 17 additions & 1 deletion data/metainfo.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,18 @@
<metadata_license>CC-BY-SA-4.0</metadata_license>
<project_license>GPL-3.0-only</project_license>
<description>
<p>Hybrid native + web app for Plausible Analytics, the lightweight and open-source website analytics tool.</p>
<p>Hybrid native + web app for Plausible Analytics, the lightweight and open-source website analytics tool. This app wraps the Plausible web app in a native UI, integrating better with desktop operating systems. Native features include:</p>
<ul>
<li>Icon in your Applications Menu, Dock, etc.</li>
<li>Native header bar with buttons for account settings and logging out</li>
<li>Save and restore current view, size, and position when closed and opened</li>
<li>Two-finger swipe to go back/forward between views</li>
</ul>
<p>Other features:</p>
<ul>
<li>Zoom in/out with Ctrl+Plus/Minus, and it's remembered the next time you use the app</li>
<li>Slimmed down web app UI (no header or footer with external links)</li>
</ul>
</description>
<provides>
<binary>com.cassidyjames.plausible</binary>
Expand All @@ -19,6 +30,11 @@
<control>touch</control>
</recommends>
<releases>
<release version="1.1.0" date="2021-02-19">
<description>
<p>Save and restore state when closed and opened</p>
</description>
</release>
<release version="1.0.1" date="2021-02-19">
<description>
<p>Initial release</p>
Expand Down
File renamed without changes.
11 changes: 4 additions & 7 deletions meson.build
Original file line number Diff line number Diff line change
@@ -1,24 +1,22 @@
project(
'com.cassidyjames.plausible',
'vala', 'c',
version: '1.0.1'
version: '1.1.0'
)

gnome = import('gnome')
# i18n = import('i18n')

add_global_arguments('-DGETTEXT_PACKAGE="@0@"'.format(meson.project_name()), language:'c')
# add_project_arguments(['--vapidir', join_paths(meson.current_source_dir(), 'vapi')], language: 'vala')

asresources = gnome.compile_resources (
asresources = gnome.compile_resources(
'as-resources',
join_paths ('data', 'gresource.xml'),
join_paths('data', 'gresource.xml'),
source_dir: 'data'
)

executable(
meson.project_name(),
join_paths('src', 'Application.vala'),
join_paths('src', 'App.vala'),
join_paths('src', 'MainWindow.vala'),
join_paths('src', 'WebContext.vala'),
join_paths('src', 'Widgets', 'WebView.vala'),
Expand All @@ -32,6 +30,5 @@ executable(
)

subdir('data')
# subdir('po')

meson.add_install_script(join_paths('meson', 'post_install.py'))
16 changes: 8 additions & 8 deletions src/Application.vala → src/App.vala
Original file line number Diff line number Diff line change
Expand Up @@ -19,33 +19,33 @@
* Authored by: Cassidy James Blaede <[email protected]>
*/

public class Plausible.Application : Gtk.Application {
public class Plausible.App : Gtk.Application {
public string domain = "plausible.io";
public static GLib.Settings settings;

public Application () {
public App () {
Object (
application_id: "com.cassidyjames.plausible"
);
}

public static Application _instance = null;
public static Application instance {
public static App _instance = null;
public static App instance {
get {
if (_instance == null) {
_instance = new Application ();
_instance = new App ();
}
return _instance;
}
}

static construct {
settings = new Settings (Application.instance.application_id);
settings = new Settings (App.instance.application_id);
}

protected override void activate () {
var provider = new Gtk.CssProvider ();
provider.load_from_resource ("/com/cassidyjames/plausible/Application.css");
provider.load_from_resource ("/com/cassidyjames/plausible/App.css");
Gtk.StyleContext.add_provider_for_screen (
Gdk.Screen.get_default (),
provider,
Expand All @@ -65,7 +65,7 @@ public class Plausible.Application : Gtk.Application {
}

public static int main (string[] args) {
var app = new Application ();
var app = new App ();
return app.run (args);
}
}
88 changes: 67 additions & 21 deletions src/MainWindow.vala
Original file line number Diff line number Diff line change
Expand Up @@ -21,32 +21,29 @@

public class Plausible.MainWindow : Gtk.Window {
private Plausible.WebView web_view;
// private Gtk.Revealer back_revealer;
private Gtk.Revealer account_revealer;
private Gtk.Stack account_stack;
private Gtk.Revealer sites_revealer;
private uint configure_id;

public MainWindow (Gtk.Application application) {
Object (
application: application,
border_width: 0,
icon_name: Application.instance.application_id,
icon_name: App.instance.application_id,
resizable: true,
title: "Plausible",
window_position: Gtk.WindowPosition.CENTER
);
}

construct {
default_height = 700;
default_width = 1000;

Gtk.Settings.get_default ().gtk_application_prefer_dark_theme = true;
Gdk.RGBA rgba = { 0, 0, 0, 1 };
rgba.parse ("#5850EC");
Granite.Widgets.Utils.set_color_primary (this, rgba);

var sites_button = new Gtk.Button.with_label ("My Websites") {
var sites_button = new Gtk.Button.with_label ("Sites") {
valign = Gtk.Align.CENTER
};
sites_button.get_style_context ().add_class ("back-button");
Expand Down Expand Up @@ -79,12 +76,17 @@ public class Plausible.MainWindow : Gtk.Window {
has_subtitle = false,
show_close_button = true
};
// header.pack_start (back_revealer);
header.pack_start (sites_revealer);
header.pack_end (account_revealer);

web_view = new Plausible.WebView ();
web_view.load_uri ("https://" + Application.instance.domain + "/sites");

string current_url = App.settings.get_string ("current-url");
if (current_url != "") {
web_view.load_uri (current_url);
} else {
web_view.load_uri ("https://" + App.instance.domain + "/sites");
}

var logo = new Gtk.Image.from_resource ("/com/cassidyjames/plausible/logo-dark.png") {
expand = true,
Expand All @@ -102,32 +104,47 @@ public class Plausible.MainWindow : Gtk.Window {
set_titlebar (header);
add (stack);

int window_x, window_y;
int window_width, window_height;
App.settings.get ("window-position", "(ii)", out window_x, out window_y);
App.settings.get ("window-size", "(ii)", out window_width, out window_height);

if (window_x != -1 || window_y != -1) {
move (window_x, window_y);
}

resize (window_width, window_height);

if (App.settings.get_boolean ("window-maximized")) {
maximize ();
}

web_view.load_changed.connect ((load_event) => {
if (load_event == WebKit.LoadEvent.FINISHED) {
stack.visible_child_name = "web";
}
});

sites_button.clicked.connect (() => {
web_view.load_uri ("https://" + Application.instance.domain + "/sites");
web_view.load_uri ("https://" + App.instance.domain + "/sites");
});

account_button.clicked.connect (() => {
web_view.load_uri ("https://" + Application.instance.domain + "/settings");
web_view.load_uri ("https://" + App.instance.domain + "/settings");
});

logout_button.clicked.connect (() => {
// NOTE: Plausible expects a POST not just loading the URL
// https://github.com/plausible/analytics/issues/730
// web_view.load_uri ("https://" + Application.instance.domain + "/logout");
// web_view.load_uri ("https://" + App.instance.domain + "/logout");

web_view.get_website_data_manager ().clear.begin (
WebKit.WebsiteDataTypes.COOKIES,
0,
null,
() => {
debug ("Cleared cookies; going home.");
web_view.load_uri ("https://" + Application.instance.domain + "/sites");
web_view.load_uri ("https://" + App.instance.domain + "/sites");
}
);
});
Expand All @@ -137,7 +154,7 @@ public class Plausible.MainWindow : Gtk.Window {
web_view.notify["estimated-load-progress"].connect (on_loading);
web_view.notify["is-loading"].connect (on_loading);

Application.settings.bind ("zoom", web_view, "zoom-level", SettingsBindFlags.DEFAULT);
App.settings.bind ("zoom", web_view, "zoom-level", SettingsBindFlags.DEFAULT);

var accel_group = new Gtk.AccelGroup ();

Expand Down Expand Up @@ -184,27 +201,56 @@ public class Plausible.MainWindow : Gtk.Window {
add_accel_group (accel_group);
}

public override bool configure_event (Gdk.EventConfigure event) {
if (configure_id == 0) {
/* Avoid spamming the settings */
configure_id = Timeout.add (200, () => {
configure_id = 0;

if (is_maximized) {
App.settings.set_boolean ("window-maximized", true);
} else {
App.settings.set_boolean ("window-maximized", false);

int width, height;
get_size (out width, out height);
App.settings.set ("window-size", "(ii)", width, height);

int root_x, root_y;
get_position (out root_x, out root_y);
App.settings.set ("window-position", "(ii)", root_x, root_y);
}

return GLib.Source.REMOVE;
});
}

return base.configure_event (event);
}

private void on_loading () {
// Only do anything once we're done loading
if (! web_view.is_loading) {
sites_revealer.reveal_child = (
web_view.uri != "https://" + Application.instance.domain + "/login" &&
web_view.uri != "https://" + Application.instance.domain + "/register" &&
web_view.uri != "https://" + Application.instance.domain + "/password/request-reset" &&
web_view.uri != "https://" + Application.instance.domain + "/sites"
web_view.uri != "https://" + App.instance.domain + "/login" &&
web_view.uri != "https://" + App.instance.domain + "/register" &&
web_view.uri != "https://" + App.instance.domain + "/password/request-reset" &&
web_view.uri != "https://" + App.instance.domain + "/sites"
);

account_revealer.reveal_child = (
web_view.uri != "https://" + Application.instance.domain + "/login" &&
web_view.uri != "https://" + Application.instance.domain + "/register" &&
web_view.uri != "https://" + Application.instance.domain + "/password/request-reset"
web_view.uri != "https://" + App.instance.domain + "/login" &&
web_view.uri != "https://" + App.instance.domain + "/register" &&
web_view.uri != "https://" + App.instance.domain + "/password/request-reset"
);

if (web_view.uri == "https://" + Application.instance.domain + "/settings") {
if (web_view.uri == "https://" + App.instance.domain + "/settings") {
account_stack.visible_child_name = "logout";
} else {
account_stack.visible_child_name = "account";
}

App.settings.set_string ("current-url", web_view.uri);
}
}

Expand Down

0 comments on commit ac72e4f

Please sign in to comment.