Implement #104
This commit is contained in:
parent
2726886130
commit
7206ca2385
|
@ -70,7 +70,7 @@ executable(
|
|||
dependency('gtk+-3.0', version: '>=3.22.0'),
|
||||
dependency('glib-2.0', version: '>=2.30.0'),
|
||||
dependency('gee-0.8', version: '>=0.8.5'),
|
||||
dependency('granite'),
|
||||
dependency('granite', version: '>=5.2.0'),
|
||||
dependency('json-glib-1.0'),
|
||||
dependency('libsoup-2.4')
|
||||
],
|
||||
|
|
|
@ -6,7 +6,7 @@ namespace Tootle {
|
|||
public static Application app;
|
||||
public static MainWindow? window;
|
||||
public static Window window_dummy;
|
||||
|
||||
|
||||
public static Settings settings;
|
||||
public static Accounts accounts;
|
||||
public static Network network;
|
||||
|
@ -16,7 +16,7 @@ namespace Tootle {
|
|||
public static bool start_hidden = false;
|
||||
|
||||
public class Application : Granite.Application {
|
||||
|
||||
|
||||
public abstract signal void refresh ();
|
||||
public abstract signal void toast (string title);
|
||||
public abstract signal void error (string title, string text);
|
||||
|
@ -32,7 +32,7 @@ namespace Tootle {
|
|||
{"refresh", refresh_activated },
|
||||
{"switch-timeline", switch_timeline_activated, "i" }
|
||||
};
|
||||
|
||||
|
||||
construct {
|
||||
application_id = "com.github.bleakgrey.tootle";
|
||||
flags = ApplicationFlags.FLAGS_NONE;
|
||||
|
@ -40,9 +40,17 @@ namespace Tootle {
|
|||
build_version = "0.2.0";
|
||||
}
|
||||
|
||||
public string[] ACCEL_NEW_POST = {"<Ctrl>T"};
|
||||
public string[] ACCEL_BACK = {"<Alt>BackSpace", "<Alt>Left"};
|
||||
public string[] ACCEL_REFRESH = {"<Ctrl>R", "F5"};
|
||||
public string[] ACCEL_TIMELINE_0 = {"<Alt>1"};
|
||||
public string[] ACCEL_TIMELINE_1 = {"<Alt>2"};
|
||||
public string[] ACCEL_TIMELINE_2 = {"<Alt>3"};
|
||||
public string[] ACCEL_TIMELINE_3 = {"<Alt>4"};
|
||||
|
||||
public static int main (string[] args) {
|
||||
Gtk.init (ref args);
|
||||
|
||||
|
||||
try {
|
||||
var opt_context = new OptionContext ("- Options");
|
||||
opt_context.add_main_entries (app_options, null);
|
||||
|
@ -51,48 +59,48 @@ namespace Tootle {
|
|||
catch (GLib.OptionError e) {
|
||||
warning (e.message);
|
||||
}
|
||||
|
||||
|
||||
app = new Application ();
|
||||
return app.run (args);
|
||||
}
|
||||
|
||||
|
||||
protected override void startup () {
|
||||
base.startup ();
|
||||
Granite.Services.Logger.DisplayLevel = Granite.Services.LogLevel.INFO;
|
||||
|
||||
|
||||
settings = new Settings ();
|
||||
accounts = new Accounts ();
|
||||
network = new Network ();
|
||||
image_cache = new ImageCache ();
|
||||
watchlist = new Watchlist ();
|
||||
accounts.init ();
|
||||
|
||||
|
||||
app.error.connect (app.on_error);
|
||||
|
||||
|
||||
window_dummy = new Window ();
|
||||
add_window (window_dummy);
|
||||
|
||||
set_accels_for_action ("app.compose-toot", {"<Ctrl>T"});
|
||||
set_accels_for_action ("app.back", {"<Alt>BackSpace", "<Alt>Left"});
|
||||
set_accels_for_action ("app.refresh", {"<Ctrl>R", "F5"});
|
||||
set_accels_for_action ("app.switch-timeline(0)", {"<Alt>1"});
|
||||
set_accels_for_action ("app.switch-timeline(1)", {"<Alt>2"});
|
||||
set_accels_for_action ("app.switch-timeline(2)", {"<Alt>3"});
|
||||
set_accels_for_action ("app.switch-timeline(3)", {"<Alt>4"});
|
||||
set_accels_for_action ("app.compose-toot", ACCEL_NEW_POST);
|
||||
set_accels_for_action ("app.back", ACCEL_BACK);
|
||||
set_accels_for_action ("app.refresh", ACCEL_REFRESH);
|
||||
set_accels_for_action ("app.switch-timeline(0)", ACCEL_TIMELINE_0);
|
||||
set_accels_for_action ("app.switch-timeline(1)", ACCEL_TIMELINE_1);
|
||||
set_accels_for_action ("app.switch-timeline(2)", ACCEL_TIMELINE_2);
|
||||
set_accels_for_action ("app.switch-timeline(3)", ACCEL_TIMELINE_3);
|
||||
add_action_entries (app_entries, this);
|
||||
}
|
||||
|
||||
|
||||
protected override void activate () {
|
||||
if (window != null) {
|
||||
window.present ();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (start_hidden) {
|
||||
start_hidden = false;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
debug ("Creating new window");
|
||||
if (accounts.is_empty ())
|
||||
NewAccountDialog.open ();
|
||||
|
@ -101,7 +109,7 @@ namespace Tootle {
|
|||
window.present ();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected void on_error (string title, string msg){
|
||||
var message_dialog = new Granite.MessageDialog.with_image_from_icon_name (title, msg, "dialog-warning");
|
||||
message_dialog.transient_for = window;
|
||||
|
@ -125,7 +133,7 @@ namespace Tootle {
|
|||
int32 timeline_no = parameter.get_int32 ();
|
||||
window.switch_timeline (timeline_no);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -21,15 +21,15 @@ public class Tootle.Desktop {
|
|||
// Download a file from the web to a user's configured Downloads folder
|
||||
public static void download_file (string url) {
|
||||
debug ("Downloading file: %s", url);
|
||||
|
||||
|
||||
var i = url.last_index_of ("/");
|
||||
var name = url.substring (i + 1, url.length - i - 1);
|
||||
if (name == null)
|
||||
name = "unknown";
|
||||
|
||||
|
||||
var dir_path = "%s/%s".printf (GLib.Environment.get_user_special_dir (UserDirectory.DOWNLOAD), app.program_name);
|
||||
var file_path = "%s/%s".printf (dir_path, name);
|
||||
|
||||
|
||||
var msg = new Soup.Message("GET", url);
|
||||
msg.finished.connect(() => {
|
||||
try {
|
||||
|
@ -51,10 +51,14 @@ public class Tootle.Desktop {
|
|||
});
|
||||
network.queue (msg);
|
||||
}
|
||||
|
||||
|
||||
public static string fallback_icon (string normal, string fallback) {
|
||||
var theme = Gtk.IconTheme.get_default ();
|
||||
return theme.has_icon (normal) ? normal : fallback;
|
||||
}
|
||||
|
||||
|
||||
public static void set_hotkey_tooltip (Gtk.Widget widget, string? description, string[] accelerators) {
|
||||
widget.tooltip_markup = Granite.markup_accel_tooltip (accelerators, description);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -48,12 +48,13 @@ public class Tootle.MainWindow: Gtk.Window {
|
|||
button_back.label = _("Back");
|
||||
button_back.get_style_context ().add_class (Granite.STYLE_CLASS_BACK_BUTTON);
|
||||
button_back.clicked.connect (() => back ());
|
||||
Desktop.set_hotkey_tooltip (button_back, null, app.ACCEL_BACK);
|
||||
|
||||
button_toot = new Button ();
|
||||
button_toot.valign = Align.CENTER;
|
||||
button_toot.tooltip_text = _("Toot");
|
||||
button_toot.image = new Image.from_icon_name ("document-edit-symbolic", IconSize.LARGE_TOOLBAR);
|
||||
button_toot.clicked.connect (() => PostDialog.open ());
|
||||
Desktop.set_hotkey_tooltip (button_toot, _("Toot"), app.ACCEL_NEW_POST);
|
||||
|
||||
button_mode = new Granite.Widgets.ModeButton ();
|
||||
button_mode.get_style_context ().add_class ("mode");
|
||||
|
@ -76,10 +77,10 @@ public class Tootle.MainWindow: Gtk.Window {
|
|||
grid = new Grid ();
|
||||
grid.attach (primary_stack, 0, 0, 1, 1);
|
||||
|
||||
add_header_view (home);
|
||||
add_header_view (notifications);
|
||||
add_header_view (local);
|
||||
add_header_view (federated);
|
||||
add_header_view (home, app.ACCEL_TIMELINE_0, 0);
|
||||
add_header_view (notifications, app.ACCEL_TIMELINE_1, 1);
|
||||
add_header_view (local, app.ACCEL_TIMELINE_2, 2);
|
||||
add_header_view (federated, app.ACCEL_TIMELINE_3, 3);
|
||||
button_mode.set_active (0);
|
||||
|
||||
toast = new Granite.Widgets.Toast ("");
|
||||
|
@ -112,12 +113,12 @@ public class Tootle.MainWindow: Gtk.Window {
|
|||
});
|
||||
}
|
||||
|
||||
private void add_header_view (AbstractView view) {
|
||||
private void add_header_view (AbstractView view, string[] accelerators, int32 num) {
|
||||
var img = new Image.from_icon_name (view.get_icon (), IconSize.LARGE_TOOLBAR);
|
||||
img.tooltip_text = view.get_name ();
|
||||
Desktop.set_hotkey_tooltip (img, view.get_name (), accelerators);
|
||||
button_mode.append (img);
|
||||
view.image = img;
|
||||
secondary_stack.add_named (view, view.get_name ());
|
||||
secondary_stack.add_named (view, num.to_string ());
|
||||
|
||||
if (view is NotificationsView)
|
||||
img.pixel_size = 20; // For some reason Notifications icon is too small without this
|
||||
|
@ -196,7 +197,7 @@ public class Tootle.MainWindow: Gtk.Window {
|
|||
var visible = secondary_stack.get_visible_child () as AbstractView;
|
||||
visible.current = false;
|
||||
|
||||
secondary_stack.set_visible_child_name (widget.tooltip_text);
|
||||
secondary_stack.set_visible_child_name (button_mode.selected.to_string ());
|
||||
|
||||
visible = secondary_stack.get_visible_child () as AbstractView;
|
||||
visible.current = true;
|
||||
|
|
|
@ -15,20 +15,20 @@ public class Tootle.AccountsButton : Gtk.MenuButton{
|
|||
Gtk.ModelButton item_watchlist;
|
||||
|
||||
private class AccountItemView : Gtk.ListBoxRow{
|
||||
|
||||
|
||||
private Gtk.Grid grid;
|
||||
public Gtk.Label display_name;
|
||||
public Gtk.Label instance;
|
||||
public Gtk.Button button;
|
||||
public int id = -1;
|
||||
|
||||
|
||||
construct {
|
||||
can_default = false;
|
||||
|
||||
|
||||
grid = new Gtk.Grid ();
|
||||
grid.margin = 6;
|
||||
grid.margin_start = 14;
|
||||
|
||||
|
||||
display_name = new Gtk.Label ("");
|
||||
display_name.hexpand = true;
|
||||
display_name.halign = Gtk.Align.START;
|
||||
|
@ -38,18 +38,18 @@ public class Tootle.AccountsButton : Gtk.MenuButton{
|
|||
button = new Gtk.Button.from_icon_name ("close-symbolic", Gtk.IconSize.SMALL_TOOLBAR);
|
||||
button.receives_default = false;
|
||||
button.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT);
|
||||
|
||||
|
||||
grid.attach(display_name, 1, 0, 1, 1);
|
||||
grid.attach(instance, 1, 1, 1, 1);
|
||||
grid.attach(button, 2, 0, 2, 2);
|
||||
add (grid);
|
||||
show_all ();
|
||||
}
|
||||
|
||||
|
||||
public AccountItemView (){
|
||||
button.clicked.connect (() => accounts.remove (id));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
construct{
|
||||
|
@ -57,36 +57,37 @@ public class Tootle.AccountsButton : Gtk.MenuButton{
|
|||
avatar.button_press_event.connect(event => {
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
list = new Gtk.ListBox ();
|
||||
|
||||
|
||||
var item_separator = new Gtk.Separator (Gtk.Orientation.HORIZONTAL);
|
||||
item_separator.hexpand = true;
|
||||
|
||||
item_refresh = new Gtk.ModelButton ();
|
||||
|
||||
item_refresh = new Gtk.ModelButton ();
|
||||
item_refresh.text = _("Refresh");
|
||||
item_refresh.clicked.connect (() => app.refresh ());
|
||||
|
||||
item_favs = new Gtk.ModelButton ();
|
||||
Desktop.set_hotkey_tooltip (item_refresh, null, app.ACCEL_REFRESH);
|
||||
|
||||
item_favs = new Gtk.ModelButton ();
|
||||
item_favs.text = _("Favorites");
|
||||
item_favs.clicked.connect (() => window.open_view (new FavoritesView ()));
|
||||
|
||||
item_direct = new Gtk.ModelButton ();
|
||||
|
||||
item_direct = new Gtk.ModelButton ();
|
||||
item_direct.text = _("Direct Messages");
|
||||
item_direct.clicked.connect (() => window.open_view (new DirectView ()));
|
||||
|
||||
item_search = new Gtk.ModelButton ();
|
||||
|
||||
item_search = new Gtk.ModelButton ();
|
||||
item_search.text = _("Search");
|
||||
item_search.clicked.connect (() => window.open_view (new SearchView ()));
|
||||
|
||||
item_watchlist = new Gtk.ModelButton ();
|
||||
|
||||
item_watchlist = new Gtk.ModelButton ();
|
||||
item_watchlist.text = _("Watchlist");
|
||||
item_watchlist.clicked.connect (() => WatchlistDialog.open ());
|
||||
|
||||
item_settings = new Gtk.ModelButton ();
|
||||
|
||||
item_settings = new Gtk.ModelButton ();
|
||||
item_settings.text = _("Settings");
|
||||
item_settings.clicked.connect (() => SettingsDialog.open ());
|
||||
|
||||
|
||||
grid = new Gtk.Grid ();
|
||||
grid.orientation = Gtk.Orientation.VERTICAL;
|
||||
grid.width_request = 200;
|
||||
|
@ -100,7 +101,7 @@ public class Tootle.AccountsButton : Gtk.MenuButton{
|
|||
grid.attach(item_watchlist, 0, 9, 1, 1);
|
||||
grid.attach(item_settings, 0, 10, 1, 1);
|
||||
grid.show_all ();
|
||||
|
||||
|
||||
menu = new Gtk.Popover (null);
|
||||
menu.add (grid);
|
||||
|
||||
|
@ -108,7 +109,7 @@ public class Tootle.AccountsButton : Gtk.MenuButton{
|
|||
popover = menu;
|
||||
add (avatar);
|
||||
show_all ();
|
||||
|
||||
|
||||
accounts.updated.connect (accounts_updated);
|
||||
accounts.switched.connect (account_switched);
|
||||
list.row_activated.connect (row => {
|
||||
|
@ -121,11 +122,11 @@ public class Tootle.AccountsButton : Gtk.MenuButton{
|
|||
AccountView.open_from_id (accounts.current.id);
|
||||
else
|
||||
accounts.switch_account (widget.id);
|
||||
|
||||
|
||||
menu.popdown ();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private void accounts_updated (GenericArray<InstanceAccount> accounts) {
|
||||
list.forall (widget => widget.destroy ());
|
||||
int i = -1;
|
||||
|
@ -137,7 +138,7 @@ public class Tootle.AccountsButton : Gtk.MenuButton{
|
|||
widget.instance.label = account.get_pretty_instance ();
|
||||
list.add (widget);
|
||||
});
|
||||
|
||||
|
||||
var add_account = new AccountItemView ();
|
||||
add_account.display_name.label = _("<b>New Account</b>");
|
||||
add_account.instance.label = _("Click to add");
|
||||
|
@ -145,14 +146,14 @@ public class Tootle.AccountsButton : Gtk.MenuButton{
|
|||
list.add (add_account);
|
||||
update_selection ();
|
||||
}
|
||||
|
||||
|
||||
private void account_switched (Account? account) {
|
||||
if (account == null)
|
||||
avatar.show_default (AVATAR_SIZE);
|
||||
else
|
||||
network.load_avatar (account.avatar, avatar, get_avatar_size ());
|
||||
}
|
||||
|
||||
|
||||
private void update_selection () {
|
||||
var id = settings.current_account;
|
||||
var row = list.get_row_at_index (id);
|
||||
|
|
Loading…
Reference in New Issue