2018-04-14 12:09:06 +00:00
|
|
|
using Gtk;
|
|
|
|
|
2022-11-13 20:57:43 +00:00
|
|
|
namespace Tooth {
|
2018-04-14 12:09:06 +00:00
|
|
|
|
2020-09-05 08:02:42 +00:00
|
|
|
public errordomain Oopsie {
|
|
|
|
USER,
|
|
|
|
PARSING,
|
|
|
|
INSTANCE,
|
|
|
|
INTERNAL
|
|
|
|
}
|
|
|
|
|
|
|
|
public static Application app;
|
|
|
|
|
|
|
|
public static Settings settings;
|
2021-02-12 15:26:37 +00:00
|
|
|
public static AccountStore accounts;
|
2020-09-05 08:02:42 +00:00
|
|
|
public static Network network;
|
|
|
|
public static Streams streams;
|
|
|
|
|
2021-07-23 11:41:03 +00:00
|
|
|
public static EntityCache entity_cache;
|
|
|
|
public static ImageCache image_cache;
|
|
|
|
|
2022-12-23 20:29:22 +00:00
|
|
|
public static GLib.Regex custom_emoji_regex;
|
2022-11-27 01:28:47 +00:00
|
|
|
public static GLib.Regex rtl_regex;
|
2022-11-27 16:05:56 +00:00
|
|
|
public static bool is_rtl;
|
2022-11-27 01:28:47 +00:00
|
|
|
|
2020-09-05 08:02:42 +00:00
|
|
|
public static bool start_hidden = false;
|
|
|
|
|
2022-11-16 11:18:34 +00:00
|
|
|
public class Application : Adw.Application {
|
2020-09-05 08:02:42 +00:00
|
|
|
|
2021-07-23 11:41:03 +00:00
|
|
|
public Dialogs.MainWindow? main_window { get; set; }
|
|
|
|
public Dialogs.NewAccount? add_account_window { get; set; }
|
|
|
|
|
2020-09-05 08:02:42 +00:00
|
|
|
// These are used for the GTK Inspector
|
2022-11-13 20:57:43 +00:00
|
|
|
public Settings app_settings { get {return Tooth.settings; } }
|
|
|
|
public AccountStore app_accounts { get {return Tooth.accounts; } }
|
|
|
|
public Network app_network { get {return Tooth.network; } }
|
|
|
|
public Streams app_streams { get {return Tooth.streams; } }
|
2020-09-05 08:02:42 +00:00
|
|
|
|
|
|
|
public signal void refresh ();
|
|
|
|
public signal void toast (string title);
|
2020-09-10 17:10:24 +00:00
|
|
|
|
|
|
|
public CssProvider css_provider = new CssProvider ();
|
2021-07-23 11:41:03 +00:00
|
|
|
public CssProvider zoom_css_provider = new CssProvider (); //FIXME: Zoom not working
|
2020-09-05 08:02:42 +00:00
|
|
|
|
|
|
|
public const GLib.OptionEntry[] app_options = {
|
|
|
|
{ "hidden", 0, 0, OptionArg.NONE, ref start_hidden, "Do not show main window on start", null },
|
|
|
|
{ null }
|
|
|
|
};
|
|
|
|
|
2022-03-19 08:59:31 +00:00
|
|
|
private const GLib.ActionEntry[] app_entries = {
|
2020-09-05 08:02:42 +00:00
|
|
|
{ "about", about_activated },
|
|
|
|
{ "compose", compose_activated },
|
|
|
|
{ "back", back_activated },
|
|
|
|
{ "refresh", refresh_activated },
|
2020-10-15 15:55:13 +00:00
|
|
|
{ "search", search_activated },
|
2023-02-09 23:02:37 +00:00
|
|
|
{ "quit", quit_activated }
|
2020-09-05 08:02:42 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
construct {
|
|
|
|
application_id = Build.DOMAIN;
|
2020-09-10 17:10:24 +00:00
|
|
|
flags = ApplicationFlags.HANDLES_OPEN;
|
2020-09-05 08:02:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public string[] ACCEL_ABOUT = {"F1"};
|
|
|
|
public string[] ACCEL_NEW_POST = {"<Ctrl>T"};
|
|
|
|
public string[] ACCEL_BACK = {"<Alt>BackSpace", "<Alt>Left"};
|
|
|
|
public string[] ACCEL_REFRESH = {"<Ctrl>R", "F5"};
|
2020-10-15 15:55:13 +00:00
|
|
|
public string[] ACCEL_SEARCH = {"<Ctrl>F"};
|
2023-02-09 23:02:37 +00:00
|
|
|
public string[] ACCEL_QUIT = {"<Ctrl>Q"};
|
2020-09-05 08:02:42 +00:00
|
|
|
|
|
|
|
public static int main (string[] args) {
|
|
|
|
try {
|
|
|
|
var opt_context = new OptionContext ("- Options");
|
|
|
|
opt_context.add_main_entries (app_options, null);
|
|
|
|
opt_context.parse (ref args);
|
|
|
|
}
|
|
|
|
catch (GLib.OptionError e) {
|
|
|
|
warning (e.message);
|
|
|
|
}
|
|
|
|
|
2022-12-23 20:29:22 +00:00
|
|
|
try {
|
|
|
|
custom_emoji_regex = new GLib.Regex("(:[a-zA-Z0-9_]{2,}:)", GLib.RegexCompileFlags.OPTIMIZE);
|
|
|
|
} catch (GLib.RegexError e) {
|
|
|
|
warning (e.message);
|
|
|
|
}
|
|
|
|
|
2022-11-27 01:28:47 +00:00
|
|
|
try {
|
|
|
|
rtl_regex = new GLib.Regex("[\u0591-\u07FF\uFB1D-\uFDFD\uFE70-\uFEFC]", GLib.RegexCompileFlags.OPTIMIZE, GLib.RegexMatchFlags.ANCHORED);
|
|
|
|
} catch (GLib.RegexError e) {
|
|
|
|
warning (e.message);
|
|
|
|
}
|
|
|
|
|
2020-09-05 08:02:42 +00:00
|
|
|
app = new Application ();
|
|
|
|
return app.run (args);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected override void startup () {
|
|
|
|
base.startup ();
|
2021-02-12 15:26:37 +00:00
|
|
|
try {
|
2023-02-21 16:18:53 +00:00
|
|
|
var lines = troubleshooting.split ("\n");
|
|
|
|
foreach (unowned string line in lines) {
|
|
|
|
message (line);
|
|
|
|
}
|
2021-07-23 11:41:03 +00:00
|
|
|
Adw.init ();
|
2021-02-12 15:26:37 +00:00
|
|
|
|
|
|
|
settings = new Settings ();
|
|
|
|
streams = new Streams ();
|
|
|
|
network = new Network ();
|
2021-07-23 11:41:03 +00:00
|
|
|
entity_cache = new EntityCache ();
|
|
|
|
image_cache = new ImageCache ();
|
|
|
|
accounts = new SecretAccountStore();
|
2021-02-12 15:26:37 +00:00
|
|
|
accounts.init ();
|
|
|
|
|
2022-11-20 23:28:49 +00:00
|
|
|
// css_provider.load_from_resource (@"$(Build.RESOURCES)app.css");
|
2021-07-23 11:41:03 +00:00
|
|
|
StyleContext.add_provider_for_display (Gdk.Display.get_default (), css_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
|
|
|
|
StyleContext.add_provider_for_display (Gdk.Display.get_default (), zoom_css_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
|
2021-02-12 15:26:37 +00:00
|
|
|
}
|
|
|
|
catch (Error e) {
|
2023-02-24 04:19:16 +00:00
|
|
|
var msg = "Could not start application: %s".printf (e.message);
|
2021-02-12 15:26:37 +00:00
|
|
|
inform (Gtk.MessageType.ERROR, _("Error"), msg);
|
|
|
|
error (msg);
|
|
|
|
}
|
2020-09-10 17:10:24 +00:00
|
|
|
|
2022-12-22 22:39:55 +00:00
|
|
|
var style_manager = Adw.StyleManager.get_default ();
|
|
|
|
ColorScheme color_scheme = (ColorScheme) settings.get_enum ("color-scheme");
|
|
|
|
style_manager.color_scheme = color_scheme.to_adwaita_scheme ();
|
|
|
|
|
2020-09-05 08:02:42 +00:00
|
|
|
set_accels_for_action ("app.about", ACCEL_ABOUT);
|
|
|
|
set_accels_for_action ("app.compose", ACCEL_NEW_POST);
|
|
|
|
set_accels_for_action ("app.back", ACCEL_BACK);
|
|
|
|
set_accels_for_action ("app.refresh", ACCEL_REFRESH);
|
2020-10-15 15:55:13 +00:00
|
|
|
set_accels_for_action ("app.search", ACCEL_SEARCH);
|
2023-02-09 23:02:37 +00:00
|
|
|
set_accels_for_action ("app.quit", ACCEL_QUIT);
|
2020-09-05 08:02:42 +00:00
|
|
|
add_action_entries (app_entries, this);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected override void activate () {
|
2020-09-10 17:10:24 +00:00
|
|
|
present_window ();
|
2020-09-05 08:02:42 +00:00
|
|
|
|
|
|
|
if (start_hidden) {
|
|
|
|
start_hidden = false;
|
|
|
|
return;
|
|
|
|
}
|
2022-12-22 22:27:00 +00:00
|
|
|
settings.delay ();
|
|
|
|
}
|
|
|
|
|
|
|
|
protected override void shutdown () {
|
|
|
|
settings.apply ();
|
|
|
|
base.shutdown ();
|
2020-09-10 17:10:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public override void open (File[] files, string hint) {
|
|
|
|
foreach (File file in files) {
|
|
|
|
string uri = file.get_uri ();
|
2021-07-23 11:41:03 +00:00
|
|
|
if (add_account_window != null)
|
|
|
|
add_account_window.redirect (uri);
|
2020-09-10 17:10:24 +00:00
|
|
|
else
|
|
|
|
warning (@"Received an unexpected uri to open: $uri");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2020-09-05 08:02:42 +00:00
|
|
|
|
2022-11-16 21:21:43 +00:00
|
|
|
public void present_window (bool destroy_main = false) {
|
2021-02-12 15:26:37 +00:00
|
|
|
if (accounts.saved.is_empty) {
|
2022-11-16 21:21:43 +00:00
|
|
|
if (main_window != null && destroy_main)
|
2022-11-16 23:17:42 +00:00
|
|
|
main_window.hide();
|
2020-09-10 17:10:24 +00:00
|
|
|
message ("Presenting NewAccount dialog");
|
2021-07-23 11:41:03 +00:00
|
|
|
if (add_account_window == null)
|
2020-09-10 17:10:24 +00:00
|
|
|
new Dialogs.NewAccount ();
|
2021-07-23 11:41:03 +00:00
|
|
|
add_account_window.present ();
|
2020-09-10 17:10:24 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
message ("Presenting MainWindow");
|
2022-11-27 16:05:56 +00:00
|
|
|
if (main_window == null) {
|
2021-07-23 11:41:03 +00:00
|
|
|
main_window = new Dialogs.MainWindow (this);
|
2022-12-11 00:23:29 +00:00
|
|
|
is_rtl = Gtk.Widget.get_default_direction() == Gtk.TextDirection.RTL;
|
2022-11-27 16:05:56 +00:00
|
|
|
}
|
2021-07-23 11:41:03 +00:00
|
|
|
main_window.present ();
|
2020-09-10 17:10:24 +00:00
|
|
|
}
|
2022-12-13 17:28:17 +00:00
|
|
|
main_window.close_request.connect(on_window_closed);
|
2020-09-10 17:10:24 +00:00
|
|
|
}
|
|
|
|
|
2022-12-13 17:28:17 +00:00
|
|
|
public bool on_window_closed () {
|
|
|
|
if (!settings.work_in_background || accounts.saved.is_empty) {
|
|
|
|
main_window.hide_on_close = false;
|
|
|
|
} else {
|
|
|
|
main_window.hide_on_close = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
2020-09-05 08:02:42 +00:00
|
|
|
|
|
|
|
void compose_activated () {
|
|
|
|
new Dialogs.Compose ();
|
|
|
|
}
|
|
|
|
|
|
|
|
void back_activated () {
|
2021-07-23 11:41:03 +00:00
|
|
|
main_window.back ();
|
2020-09-05 08:02:42 +00:00
|
|
|
}
|
|
|
|
|
2020-10-15 15:55:13 +00:00
|
|
|
void search_activated () {
|
2021-07-23 11:41:03 +00:00
|
|
|
main_window.open_view (new Views.Search ());
|
2020-10-15 15:55:13 +00:00
|
|
|
}
|
|
|
|
|
2023-02-09 23:02:37 +00:00
|
|
|
void quit_activated () {
|
|
|
|
app.quit ();
|
|
|
|
}
|
|
|
|
|
2020-09-05 08:02:42 +00:00
|
|
|
void refresh_activated () {
|
|
|
|
refresh ();
|
|
|
|
}
|
|
|
|
|
2023-02-21 16:18:53 +00:00
|
|
|
string troubleshooting = "os: %s %s\nprefix: %s\nflatpak: %s\nversion: %s (%s)\ngtk: %u.%u.%u (%d.%d.%d)\nlibadwaita: %u.%u.%u (%d.%d.%d)\nlibsoup: %u.%u.%u (%d.%d.%d)\n".printf(
|
|
|
|
GLib.Environment.get_os_info ("NAME"), GLib.Environment.get_os_info ("VERSION"),
|
|
|
|
Build.PREFIX,
|
2023-01-11 03:34:24 +00:00
|
|
|
(GLib.Environment.get_variable("FLATPAK_ID") != null || GLib.File.new_for_path("/.flatpak-info").query_exists()).to_string(),
|
2023-01-12 19:20:11 +00:00
|
|
|
Build.VERSION, Build.PROFILE,
|
2023-01-11 03:34:24 +00:00
|
|
|
Gtk.get_major_version(), Gtk.get_minor_version(), Gtk.get_micro_version(),
|
|
|
|
Gtk.MAJOR_VERSION, Gtk.MINOR_VERSION, Gtk.MICRO_VERSION,
|
|
|
|
Adw.get_major_version(), Adw.get_minor_version(), Adw.get_micro_version(),
|
2023-01-11 15:54:04 +00:00
|
|
|
Adw.MAJOR_VERSION, Adw.MINOR_VERSION, Adw.MICRO_VERSION,
|
|
|
|
Soup.get_major_version(), Soup.get_minor_version(), Soup.get_micro_version(),
|
|
|
|
Soup.MAJOR_VERSION, Soup.MINOR_VERSION, Soup.MICRO_VERSION
|
2023-01-11 03:34:24 +00:00
|
|
|
);
|
|
|
|
|
2020-09-05 08:02:42 +00:00
|
|
|
void about_activated () {
|
2023-02-21 16:18:53 +00:00
|
|
|
const string[] ARTISTS = {
|
2022-11-14 10:47:51 +00:00
|
|
|
"Tobias Bernard"
|
|
|
|
};
|
|
|
|
|
2023-02-21 16:18:53 +00:00
|
|
|
const string[] DEVELOPERS = {
|
2022-11-14 10:47:51 +00:00
|
|
|
"bleak_grey",
|
|
|
|
"Evangelos \"GeopJr\" Paterakis"
|
|
|
|
};
|
|
|
|
|
2023-02-21 16:18:53 +00:00
|
|
|
const string COPYRIGHT = "© 2022 bleak_grey\n© 2022 Evangelos \"GeopJr\" Paterakis";
|
|
|
|
|
2022-11-13 21:03:12 +00:00
|
|
|
var dialog = new Adw.AboutWindow () {
|
2021-07-23 11:41:03 +00:00
|
|
|
transient_for = main_window,
|
|
|
|
modal = true,
|
|
|
|
|
2022-11-13 21:03:12 +00:00
|
|
|
application_icon = Build.DOMAIN,
|
|
|
|
application_name = Build.NAME,
|
2021-07-23 11:41:03 +00:00
|
|
|
version = Build.VERSION,
|
2022-11-13 21:03:12 +00:00
|
|
|
support_url = Build.SUPPORT_WEBSITE,
|
2021-07-23 11:41:03 +00:00
|
|
|
license_type = License.GPL_3_0_ONLY,
|
2023-02-21 16:18:53 +00:00
|
|
|
copyright = COPYRIGHT,
|
|
|
|
developers = DEVELOPERS,
|
|
|
|
artists = ARTISTS,
|
2023-01-11 03:34:24 +00:00
|
|
|
debug_info = troubleshooting,
|
|
|
|
debug_info_filename = @"$(Build.NAME).txt",
|
2023-02-21 16:18:53 +00:00
|
|
|
// translators: Name <email@domain.com> or Name https://website.example
|
|
|
|
translator_credits = _("translator-credits")
|
2021-07-23 11:41:03 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
// For some obscure reason, const arrays produce duplicates in the credits.
|
|
|
|
// Static functions seem to avoid this peculiar behavior.
|
2022-12-02 23:22:35 +00:00
|
|
|
// dialog.translator_credits = Build.TRANSLATOR != " " ? Build.TRANSLATOR : null;
|
2021-07-23 11:41:03 +00:00
|
|
|
|
|
|
|
dialog.present ();
|
2020-09-05 08:02:42 +00:00
|
|
|
}
|
|
|
|
|
2021-07-23 11:41:03 +00:00
|
|
|
public void inform (Gtk.MessageType type, string text, string? msg = null, Gtk.Window? win = main_window){
|
2020-09-05 08:02:42 +00:00
|
|
|
var dlg = new Gtk.MessageDialog (
|
2020-09-10 17:10:24 +00:00
|
|
|
win,
|
2020-09-05 08:02:42 +00:00
|
|
|
Gtk.DialogFlags.MODAL,
|
2020-09-10 17:10:24 +00:00
|
|
|
type,
|
2020-09-05 08:02:42 +00:00
|
|
|
Gtk.ButtonsType.OK,
|
|
|
|
null
|
|
|
|
);
|
2020-09-10 17:10:24 +00:00
|
|
|
dlg.text = text;
|
2020-09-05 08:02:42 +00:00
|
|
|
dlg.secondary_text = msg;
|
2020-09-10 17:10:24 +00:00
|
|
|
dlg.transient_for = win;
|
2021-07-23 11:41:03 +00:00
|
|
|
// dlg.run ();
|
2020-09-05 08:02:42 +00:00
|
|
|
dlg.destroy ();
|
|
|
|
}
|
2019-03-09 11:42:27 +00:00
|
|
|
|
2022-11-16 21:23:00 +00:00
|
|
|
public Adw.MessageDialog question (string text, string? msg = null, Gtk.Window? win = main_window, string yes_label = _("Yes"), Adw.ResponseAppearance yes_appearence = Adw.ResponseAppearance.DEFAULT, string no_label = _("Cancel"), Adw.ResponseAppearance no_appearence = Adw.ResponseAppearance.DEFAULT) {
|
|
|
|
var dlg = new Adw.MessageDialog (
|
2020-09-10 17:10:24 +00:00
|
|
|
win,
|
2022-11-16 21:23:00 +00:00
|
|
|
text,
|
|
|
|
msg
|
2020-09-05 08:02:42 +00:00
|
|
|
);
|
2022-11-16 21:23:00 +00:00
|
|
|
|
|
|
|
dlg.add_response("no", no_label);
|
|
|
|
dlg.set_response_appearance("no", no_appearence);
|
|
|
|
|
|
|
|
dlg.add_response("yes", yes_label);
|
|
|
|
dlg.set_response_appearance("yes", yes_appearence);
|
|
|
|
|
2020-09-05 08:02:42 +00:00
|
|
|
dlg.transient_for = win;
|
2022-11-16 21:23:00 +00:00
|
|
|
return dlg;
|
2020-07-28 18:30:45 +00:00
|
|
|
}
|
|
|
|
|
2020-09-05 08:02:42 +00:00
|
|
|
}
|
2018-04-14 12:09:06 +00:00
|
|
|
|
|
|
|
}
|