Refactor main view stack (#251)

Co-authored-by: Adrien Plazas <kekun.plazas@laposte.net>
This commit is contained in:
Bleak Grey 2020-10-15 18:55:13 +03:00 committed by GitHub
parent 1ffd3ba2dc
commit d92672d895
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 1115 additions and 998 deletions

View File

@ -14,6 +14,7 @@
<file preprocess="xml-stripblanks">ui/widgets/list_editor_item.ui</file>
<file preprocess="xml-stripblanks">ui/widgets/attachment_slot.ui</file>
<file preprocess="xml-stripblanks">ui/widgets/compose_attachment.ui</file>
<file preprocess="xml-stripblanks">ui/widgets/adaptive_button.ui</file>
<file preprocess="xml-stripblanks">ui/dialogs/new_account.ui</file>
<file preprocess="xml-stripblanks">ui/dialogs/compose.ui</file>
<file preprocess="xml-stripblanks">ui/dialogs/main.ui</file>

View File

@ -3,85 +3,87 @@
<interface>
<requires lib="gtk+" version="3.20"/>
<requires lib="libhandy" version="1.0"/>
<template class="TootleDialogsCompose" parent="GtkWindow">
<template class="TootleDialogsCompose" parent="HdyWindow">
<property name="can_focus">False</property>
<property name="modal">True</property>
<property name="default_width">500</property>
<property name="default_height">250</property>
<property name="default_height">300</property>
<property name="type_hint">dialog</property>
<child type="titlebar">
<object class="GtkHeaderBar">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkButton" id="close">
<property name="label" translatable="yes">Cancel</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<signal name="clicked" handler="on_close" swapped="no"/>
</object>
<packing>
<property name="position">2</property>
</packing>
</child>
<child type="title">
<object class="HdyViewSwitcherTitle" id="mode_switcher">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stack">mode</property>
</object>
</child>
<child>
<object class="GtkButton" id="commit">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<signal name="clicked" handler="on_commit" swapped="no"/>
<child>
<object class="GtkStack" id="commit_stack">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkLabel" id="commit_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Publish</property>
</object>
<packing>
<property name="name">ready</property>
</packing>
</child>
<child>
<object class="GtkSpinner">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">center</property>
<property name="valign">center</property>
<property name="active">True</property>
</object>
<packing>
<property name="name">working</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
<packing>
<property name="pack_type">end</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<placeholder/>
<object class="HdyHeaderBar">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child type="title">
<object class="HdyViewSwitcherTitle" id="mode_switcher">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stack">mode</property>
</object>
</child>
<child>
<object class="GtkButton" id="commit">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<signal name="clicked" handler="on_commit" swapped="no"/>
<child>
<object class="GtkStack" id="commit_stack">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkLabel" id="commit_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Publish</property>
</object>
<packing>
<property name="name">ready</property>
</packing>
</child>
<child>
<object class="GtkSpinner">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">center</property>
<property name="valign">center</property>
<property name="active">True</property>
</object>
<packing>
<property name="name">working</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
<packing>
<property name="pack_type">end</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkButton" id="close">
<property name="label" translatable="yes">Cancel</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<signal name="clicked" handler="on_close" swapped="no"/>
</object>
<packing>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkStack" id="mode">

View File

@ -2,7 +2,7 @@
<!-- Generated with glade 3.36.0 -->
<interface>
<requires lib="gtk+" version="3.22"/>
<template class="TootleDialogsListEditor" parent="GtkWindow">
<template class="TootleDialogsListEditor" parent="HdyWindow">
<property name="can_focus">False</property>
<property name="modal">True</property>
<property name="default_width">300</property>
@ -17,6 +17,101 @@
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkHeaderBar">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child type="title">
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Name</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="name_entry">
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can_focus">True</property>
<property name="width_chars">20</property>
<signal name="changed" handler="validate" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
<child>
<object class="GtkButton" id="cancel_btn">
<property name="label" translatable="yes">Cancel</property>
<property name="width_request">80</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<signal name="clicked" handler="on_cancel_clicked" swapped="no"/>
</object>
</child>
<child>
<object class="GtkButton" id="save_btn">
<property name="width_request">80</property>
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<signal name="clicked" handler="on_save_clicked" swapped="no"/>
<child>
<object class="GtkStack" id="save_btn_stack">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Save</property>
</object>
<packing>
<property name="name">done</property>
</packing>
</child>
<child>
<object class="GtkSpinner">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">center</property>
<property name="valign">center</property>
<property name="active">True</property>
</object>
<packing>
<property name="name">working</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
<style>
<class name="suggested-action"/>
</style>
</object>
<packing>
<property name="pack_type">end</property>
<property name="position">2</property>
</packing>
</child>
</object>
</child>
<child>
<object class="GtkInfoBar" id="infobar">
<property name="visible">True</property>
@ -83,11 +178,6 @@
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkSearchEntry" id="search_entry">
@ -110,11 +200,6 @@
<property name="placeholder_text" translatable="yes">Search among people you follow</property>
<signal name="search-changed" handler="on_search_changed" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow">
@ -189,106 +274,6 @@
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
</child>
<child type="titlebar">
<object class="GtkHeaderBar">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child type="title">
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Name</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="name_entry">
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can_focus">True</property>
<property name="width_chars">20</property>
<signal name="changed" handler="validate" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
<child>
<object class="GtkButton" id="cancel_btn">
<property name="label" translatable="yes">Cancel</property>
<property name="width_request">80</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<signal name="clicked" handler="on_cancel_clicked" swapped="no"/>
</object>
</child>
<child>
<object class="GtkButton" id="save_btn">
<property name="width_request">80</property>
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<signal name="clicked" handler="on_save_clicked" swapped="no"/>
<child>
<object class="GtkStack" id="save_btn_stack">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Save</property>
</object>
<packing>
<property name="name">done</property>
</packing>
</child>
<child>
<object class="GtkSpinner">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">center</property>
<property name="valign">center</property>
<property name="active">True</property>
</object>
<packing>
<property name="name">working</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
<style>
<class name="suggested-action"/>
</style>
</object>
<packing>
<property name="pack_type">end</property>
<property name="position">2</property>
</packing>
</child>
</object>
</child>

View File

@ -1,192 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.36.0 -->
<!-- Generated with glade 3.22.2 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<requires lib="libhandy" version="1.0"/>
<template class="TootleDialogsMainWindow" parent="GtkWindow">
<template class="TootleDialogsMainWindow" parent="HdyWindow">
<property name="width_request">360</property>
<property name="height_request">600</property>
<property name="can_focus">False</property>
<child>
<object class="GtkBox">
<object class="HdyDeck" id="deck">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<property name="transition_type">slide</property>
<property name="can_swipe_back">True</property>
<property name="can_swipe_forward">True</property>
<child>
<object class="GtkStack" id="view_stack">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="transition_type">slide-left-right</property>
<child>
<object class="GtkStack" id="timeline_stack">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="transition_type">slide-left-right</property>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="name">0</property>
<property name="title">0</property>
</packing>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="HdyViewSwitcherBar" id="switcher_navbar">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stack">timeline_stack</property>
<property name="reveal" bind-source="timeline_switcher" bind-property="title_visible" bind-flags="sync-create">False</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
<child type="titlebar">
<object class="GtkHeaderBar" id="header">
<property name="height_request">48</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="show_close_button">True</property>
<child type="title">
<object class="HdyViewSwitcherTitle" id="timeline_switcher">
<property name="visible">True</property>
<property name="policy">auto</property>
</object>
<packing>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkRevealer" id="view_navigation">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="transition_type">slide-right</property>
<property name="transition_duration">200</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_end">6</property>
<property name="spacing">6</property>
<child>
<object class="GtkButton" id="back_button">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="icon_name">go-previous-symbolic</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkSeparator">
<property name="can_focus">False</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkBox" id="account_actions">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="TootleWidgetsAccountsButton" id="accounts_button">
<property name="visible">True</property>
<style>
<class name="image-button"/>
</style>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="compose_button">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">Compose</property>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="icon_name">document-edit-symbolic</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<style>
<class name="linked"/>
<class name="horizontal"/>
</style>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
</child>
<child>
<object class="GtkRevealer" id="view_controls">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="valign">center</property>
<property name="transition_type">crossfade</property>
<property name="transition_duration">200</property>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="pack_type">end</property>
<property name="position">2</property>
</packing>
<placeholder/>
</child>
</object>
</child>

View File

@ -3,169 +3,117 @@
<interface>
<requires lib="gtk+" version="3.22"/>
<requires lib="libhandy" version="1.0"/>
<template class="TootleDialogsNewAccount" parent="GtkWindow">
<template class="TootleDialogsNewAccount" parent="HdyWindow">
<property name="can_focus">False</property>
<property name="modal">True</property>
<property name="default_width">700</property>
<property name="default_height">500</property>
<child type="titlebar">
<object class="GtkHeaderBar">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="title" translatable="yes">Add Account</property>
<property name="show_close_button">True</property>
<child>
<object class="GtkButton" id="back_button">
<property name="label" translatable="yes">Back</property>
<property name="width_request">80</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<signal name="clicked" handler="on_back_clicked" swapped="no"/>
</object>
</child>
<child>
<object class="GtkButton" id="next_button">
<property name="width_request">80</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<signal name="clicked" handler="on_next_clicked" swapped="no"/>
<child>
<object class="GtkStack">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Next</property>
</object>
<packing>
<property name="name">idle</property>
</packing>
</child>
<child>
<object class="GtkSpinner">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="valign">center</property>
<property name="active">True</property>
</object>
<packing>
<property name="name">spinner</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
<style>
<class name="suggested-action"/>
</style>
</object>
<packing>
<property name="pack_type">end</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
<property name="type_hint">dialog</property>
<child>
<object class="HdyClamp">
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">18</property>
<property name="margin_right">18</property>
<property name="margin_top">18</property>
<property name="margin_bottom">18</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="maximum_size">400</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkStack" id="stack">
<object class="HdyHeaderBar">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="valign">center</property>
<property name="transition_duration">100</property>
<property name="transition_type">crossfade</property>
<property name="title" translatable="yes">Add Account</property>
<property name="show_close_button">True</property>
<child>
<object class="GtkBox" id="instance_step">
<object class="GtkButton" id="back_button">
<property name="label" translatable="yes">Back</property>
<property name="width_request">80</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">24</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<signal name="clicked" handler="on_back_clicked" swapped="no"/>
</object>
</child>
<child>
<object class="GtkButton" id="next_button">
<property name="width_request">80</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<signal name="clicked" handler="on_next_clicked" swapped="no"/>
<child>
<object class="GtkImage">
<object class="GtkStack">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="pixel_size">128</property>
<property name="icon_name">network-server-symbolic</property>
<property name="icon_size">0</property>
<style>
<class name="dim-label"/>
</style>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">What is your instance?</property>
<attributes>
<attribute name="weight" value="ultrabold"/>
<attribute name="scale" value="1.7"/>
</attributes>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_top">24</property>
<property name="orientation">vertical</property>
<property name="spacing">12</property>
<child>
<object class="GtkBox">
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkButton">
<property name="label">https://</property>
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="instance_entry">
<property name="visible">True</property>
<property name="can_focus">True</property>
<signal name="activate" handler="on_next_clicked" swapped="no"/>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<property name="label" translatable="yes">Next</property>
</object>
<packing>
<property name="name">idle</property>
</packing>
</child>
<child>
<object class="GtkSpinner">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="valign">center</property>
<property name="active">True</property>
</object>
<packing>
<property name="name">spinner</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
<style>
<class name="suggested-action"/>
</style>
</object>
<packing>
<property name="pack_type">end</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="HdyClamp">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">18</property>
<property name="margin_right">18</property>
<property name="margin_top">18</property>
<property name="margin_bottom">18</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="maximum_size">400</property>
<child>
<object class="GtkStack" id="stack">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="valign">center</property>
<property name="transition_duration">100</property>
<property name="transition_type">crossfade</property>
<child>
<object class="GtkBox" id="instance_step">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">24</property>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="pixel_size">128</property>
<property name="icon_name">network-server-symbolic</property>
<property name="icon_size">0</property>
<style>
<class name="linked"/>
<class name="dim-label"/>
</style>
</object>
<packing>
@ -177,11 +125,12 @@
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">&lt;a href="https://joinmastodon.org/"&gt;Don't have one yet?&lt;/a&gt;</property>
<property name="use_markup">True</property>
<property name="track_visited_links">False</property>
<property name="xalign">1</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">What is your instance?</property>
<attributes>
<attribute name="weight" value="ultrabold"/>
<attribute name="scale" value="1.7"/>
</attributes>
</object>
<packing>
<property name="expand">False</property>
@ -189,70 +138,97 @@
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="name">instance</property>
</packing>
</child>
<child>
<object class="GtkBox" id="code_step">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="valign">center</property>
<property name="orientation">vertical</property>
<property name="spacing">24</property>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="pixel_size">128</property>
<property name="icon_name">dialog-password-symbolic</property>
<property name="icon_size">0</property>
<style>
<class name="dim-label"/>
</style>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Enter Authorization Code</property>
<attributes>
<attribute name="weight" value="ultrabold"/>
<attribute name="scale" value="1.7"/>
</attributes>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_top">24</property>
<property name="orientation">vertical</property>
<property name="spacing">12</property>
<child>
<object class="GtkEntry" id="code_entry">
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">True</property>
<signal name="activate" handler="on_next_clicked" swapped="no"/>
<property name="can_focus">False</property>
<property name="margin_top">24</property>
<property name="orientation">vertical</property>
<property name="spacing">12</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkButton">
<property name="label">https://</property>
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="instance_entry">
<property name="visible">True</property>
<property name="can_focus">True</property>
<signal name="activate" handler="on_next_clicked" swapped="no"/>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<style>
<class name="linked"/>
</style>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">&lt;a href="https://joinmastodon.org/"&gt;Don't have one yet?&lt;/a&gt;</property>
<property name="use_markup">True</property>
<property name="track_visited_links">False</property>
<property name="xalign">1</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="name">instance</property>
</packing>
</child>
<child>
<object class="GtkBox" id="code_step">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="valign">center</property>
<property name="orientation">vertical</property>
<property name="spacing">24</property>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="pixel_size">128</property>
<property name="icon_name">dialog-password-symbolic</property>
<property name="icon_size">0</property>
<style>
<class name="dim-label"/>
</style>
</object>
<packing>
<property name="expand">False</property>
@ -261,14 +237,102 @@
</packing>
</child>
<child>
<object class="GtkLabel" id="code_label">
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">&lt;a href="tootle://manual_auth"&gt;Try manual authorization&lt;/a&gt;</property>
<property name="use_markup">True</property>
<property name="track_visited_links">False</property>
<property name="xalign">1</property>
<signal name="activate-link" handler="on_activate_code_label_link" swapped="no"/>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Enter Authorization Code</property>
<attributes>
<attribute name="weight" value="ultrabold"/>
<attribute name="scale" value="1.7"/>
</attributes>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_top">24</property>
<property name="orientation">vertical</property>
<property name="spacing">12</property>
<child>
<object class="GtkEntry" id="code_entry">
<property name="visible">True</property>
<property name="can_focus">True</property>
<signal name="activate" handler="on_next_clicked" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="code_label">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">&lt;a href="tootle://manual_auth"&gt;Try manual authorization&lt;/a&gt;</property>
<property name="use_markup">True</property>
<property name="track_visited_links">False</property>
<property name="xalign">1</property>
<signal name="activate-link" handler="on_activate_code_label_link" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="name">code</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkBox" id="done_step">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="valign">center</property>
<property name="orientation">vertical</property>
<property name="spacing">24</property>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="pixel_size">128</property>
<property name="icon_name">emblem-default-symbolic</property>
<property name="icon_size">0</property>
<style>
<class name="dim-label"/>
</style>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="hello_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label">Hello, @user@instance.com!</property>
<attributes>
<attribute name="weight" value="ultrabold"/>
<attribute name="scale" value="1.7"/>
</attributes>
</object>
<packing>
<property name="expand">False</property>
@ -278,64 +342,18 @@
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="name">done</property>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="name">code</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkBox" id="done_step">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="valign">center</property>
<property name="orientation">vertical</property>
<property name="spacing">24</property>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="pixel_size">128</property>
<property name="icon_name">emblem-default-symbolic</property>
<property name="icon_size">0</property>
<style>
<class name="dim-label"/>
</style>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="hello_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label">Hello, @user@instance.com!</property>
<attributes>
<attribute name="weight" value="ultrabold"/>
<attribute name="scale" value="1.7"/>
</attributes>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="name">done</property>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>

View File

@ -49,6 +49,10 @@
<attribute name="action">view.mention</attribute>
<attribute name="target">direct</attribute>
</item>
<item>
<attribute name="label" translatable="yes">Copy Handle</attribute>
<attribute name="action">view.copy_handle</attribute>
</item>
</section>
<section>

View File

@ -3,10 +3,38 @@
<interface>
<requires lib="gtk+" version="3.20"/>
<requires lib="libhandy" version="1.0"/>
<object class="GtkImage" id="image1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="icon_name">go-previous-symbolic</property>
</object>
<template class="TootleViewsBase" parent="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<signal name="size-allocate" handler="on_resized" swapped="no"/>
<child>
<object class="HdyHeaderBar" id="header">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="show_close_button">True</property>
<child>
<object class="GtkButton" id="back_button">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">Back</property>
<property name="image">image1</property>
<signal name="clicked" handler="on_close" swapped="no"/>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow" id="scrolled">
<property name="visible">True</property>
@ -129,7 +157,7 @@
</packing>
</child>
<child>
<object class="GtkBox" id="content">
<object class="GtkBox" id="content_box">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>

View File

@ -130,17 +130,4 @@
<placeholder/>
</child>
</object>
<object class="GtkButton" id="rs_button">
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<child>
<object class="GtkLabel" id="rs_button_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Follow</property>
</object>
</child>
</object>
</interface>

View File

@ -201,19 +201,6 @@
<property name="position">3</property>
</packing>
</child>
<child>
<object class="GtkModelButton" id="item_search">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="text" translatable="yes">Search</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">4</property>
</packing>
</child>
<child>
<object class="GtkModelButton" id="item_prefs">
<property name="visible">True</property>
@ -224,7 +211,7 @@
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">5</property>
<property name="position">4</property>
</packing>
</child>
<child>
@ -238,7 +225,7 @@
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">6</property>
<property name="position">5</property>
</packing>
</child>
</object>

View File

@ -0,0 +1,59 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.2 -->
<interface>
<requires lib="gtk+" version="3.14"/>
<requires lib="libhandy" version="0.0"/>
<object class="GtkImage" id="image1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="icon_name">hjghjg</property>
</object>
<object class="GtkImage" id="image2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-missing-image</property>
</object>
<template class="TootleWidgetsAdaptiveButton" parent="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">end</property>
<child>
<object class="HdySqueezer">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkButton" id="full">
<property name="label">Follow</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="image">image1</property>
<property name="always_show_image">True</property>
<style>
<class name="image-button"/>
<class name="text-button"/>
</style>
</object>
</child>
<child>
<object class="GtkButton" id="mini">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="halign">end</property>
<property name="image">image2</property>
<property name="always_show_image">True</property>
<style>
<class name="image-button"/>
</style>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
</template>
</interface>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.36.0 -->
<!-- Generated with glade 3.22.2 -->
<interface>
<requires lib="gtk+" version="3.22"/>
<template class="TootleWidgetsTimelineMenu" parent="GtkMenuButton">
@ -15,15 +15,43 @@
<property name="halign">center</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel" id="title">
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label">User</property>
<property name="ellipsize">end</property>
<property name="single_line_mode">True</property>
<attributes>
<attribute name="weight" value="bold"/>
</attributes>
<property name="valign">center</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkLabel" id="title">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label">User</property>
<property name="ellipsize">end</property>
<property name="single_line_mode">True</property>
<style>
<class name="title"/>
</style>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="subtitle">
<property name="can_focus">False</property>
<property name="ellipsize">end</property>
<property name="single_line_mode">True</property>
<style>
<class name="subtitle"/>
</style>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
@ -48,13 +76,7 @@
</child>
<style>
<class name="flat"/>
<class name="header-title-buttonx"/>
<class name="header-title-button"/>
</style>
</template>
<object class="GtkPopover" id="popover">
<property name="can_focus">False</property>
<child>
<placeholder/>
</child>
</object>
</interface>

View File

@ -95,6 +95,7 @@ executable(
'src/Widgets/Attachment/Box.vala',
'src/Widgets/Attachment/Slot.vala',
'src/Widgets/Attachment/Picture.vala',
'src/Widgets/AdaptiveButton.vala',
'src/Dialogs/ISavedWindow.vala',
'src/Dialogs/NewAccount.vala',
'src/Dialogs/MainWindow.vala',
@ -103,6 +104,8 @@ executable(
'src/Dialogs/Preferences.vala',
'src/Dialogs/ListEditor.vala',
'src/Views/Base.vala',
'src/Views/TabbedBase.vala',
'src/Views/Main.vala',
'src/Views/Timeline.vala',
'src/Views/Home.vala',
'src/Views/Local.vala',
@ -110,7 +113,7 @@ executable(
'src/Views/Notifications.vala',
'src/Views/Conversations.vala',
'src/Views/Bookmarks.vala',
'src/Views/ExpandedStatus.vala',
'src/Views/Thread.vala',
'src/Views/Profile.vala',
'src/Views/Favorites.vala',
'src/Views/Search.vala',

View File

@ -43,6 +43,8 @@ src/Services/Network.vala
src/Services/Streams.vala
src/Views/Base.vala
src/Views/TabbedBase.vala
src/Views/Main.vala
src/Views/Bookmarks.vala
src/Views/Conversations.vala
src/Views/ExpandedStatus.vala
@ -57,6 +59,7 @@ src/Views/Notifications.vala
src/Views/Profile.vala
src/Views/Search.vala
src/Views/Timeline.vala
src/Views/Thread.vala
src/Widgets/Attachment/Box.vala
src/Widgets/Attachment/Picture.vala

View File

@ -10,7 +10,7 @@ public class Tootle.API.Conversation : Entity, Widgetizable {
}
public override void open () {
var view = new Views.ExpandedStatus (last_status.formal);
var view = new Views.Thread (last_status.formal);
window.open_view (view);
if (unread)

View File

@ -78,7 +78,7 @@ public class Tootle.API.Status : Entity, Widgetizable {
}
public override void open () {
var view = new Views.ExpandedStatus (formal);
var view = new Views.Thread (formal);
window.open_view (view);
}

View File

@ -48,6 +48,7 @@ namespace Tootle {
{ "compose", compose_activated },
{ "back", back_activated },
{ "refresh", refresh_activated },
{ "search", search_activated },
{ "switch-timeline", switch_timeline_activated, "i" }
};
@ -60,6 +61,7 @@ namespace Tootle {
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_SEARCH = {"<Ctrl>F"};
public string[] ACCEL_TIMELINE_0 = {"<Alt>1"};
public string[] ACCEL_TIMELINE_1 = {"<Alt>2"};
public string[] ACCEL_TIMELINE_2 = {"<Alt>3"};
@ -107,6 +109,7 @@ namespace Tootle {
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);
set_accels_for_action ("app.search", ACCEL_SEARCH);
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);
@ -162,6 +165,10 @@ namespace Tootle {
window.back ();
}
void search_activated () {
window.open_view (new Views.Search ());
}
void refresh_activated () {
refresh ();
}

View File

@ -2,7 +2,7 @@ using Gtk;
using Gee;
[GtkTemplate (ui = "/com/github/bleakgrey/tootle/ui/dialogs/compose.ui")]
public class Tootle.Dialogs.Compose : Window {
public class Tootle.Dialogs.Compose : Hdy.Window {
public API.Status? status { get; construct set; }
public string style_class { get; construct set; }

View File

@ -1,7 +1,7 @@
using Gtk;
[GtkTemplate (ui = "/com/github/bleakgrey/tootle/ui/dialogs/list_editor.ui")]
public class Tootle.Dialogs.ListEditor: Gtk.Window {
public class Tootle.Dialogs.ListEditor: Hdy.Window {
[GtkTemplate (ui = "/com/github/bleakgrey/tootle/ui/widgets/list_editor_item.ui")]
class Item : ListBoxRow {

View File

@ -2,182 +2,109 @@ using Gtk;
using Gdk;
[GtkTemplate (ui = "/com/github/bleakgrey/tootle/ui/dialogs/main.ui")]
public class Tootle.Dialogs.MainWindow: Gtk.Window, ISavedWindow {
public class Tootle.Dialogs.MainWindow: Hdy.Window, ISavedWindow {
public const string ZOOM_CLASS = "app-scalable";
public const string ZOOM_CLASS = "app-scalable";
[GtkChild]
protected Stack view_stack;
[GtkChild]
protected Stack timeline_stack;
[GtkChild]
Hdy.Deck deck;
[GtkChild]
public HeaderBar header;
[GtkChild]
protected Revealer view_navigation;
[GtkChild]
protected Revealer view_controls;
[GtkChild]
protected Button back_button;
[GtkChild]
protected Button compose_button;
[GtkChild]
protected Hdy.ViewSwitcherTitle timeline_switcher;
[GtkChild]
protected Hdy.ViewSwitcherBar switcher_navbar;
[GtkChild]
protected Widgets.AccountsButton accounts_button;
Views.Base? last_view = null;
Views.Base? last_view = null;
construct {
settings.bind_property ("dark-theme", Gtk.Settings.get_default (), "gtk-application-prefer-dark-theme", BindingFlags.SYNC_CREATE);
settings.notify["post-text-size"].connect (() => on_zoom_level_changed ());
construct {
back_button.clicked.connect (() => back ());
compose_button.clicked.connect (() => new Dialogs.Compose ());
on_zoom_level_changed ();
deck.notify["visible-child"].connect (on_view_changed);
button_press_event.connect (on_button_press);
restore_state ();
}
timeline_switcher.stack = timeline_stack;
timeline_switcher.valign = Align.FILL;
timeline_stack.notify["visible-child"].connect (on_timeline_changed);
public MainWindow (Gtk.Application app) {
Object (
application: app,
icon_name: Build.DOMAIN,
title: Build.NAME,
resizable: true,
window_position: WindowPosition.CENTER
);
open_view (new Views.Main ());
}
add_timeline_view (new Views.Home (), app.ACCEL_TIMELINE_0, 0);
add_timeline_view (new Views.Notifications (), app.ACCEL_TIMELINE_1, 1);
add_timeline_view (new Views.Local (), app.ACCEL_TIMELINE_2, 2);
add_timeline_view (new Views.Federated (), app.ACCEL_TIMELINE_3, 3);
public Views.Base open_view (Views.Base view) {
deck.add (view);
deck.visible_child = view;
return view;
}
settings.bind_property ("dark-theme", Gtk.Settings.get_default (), "gtk-application-prefer-dark-theme", BindingFlags.SYNC_CREATE);
settings.notify["post-text-size"].connect (() => on_zoom_level_changed ());
public bool back () {
var children = deck.get_children ();
unowned var current = children.find (deck.visible_child);
if (current != null) {
unowned var prev = current.prev;
if (current.prev != null) {
deck.visible_child = prev.data;
(current.data as Views.Base).unused = true;
Timeout.add (deck.transition_duration, clean_unused_views);
}
}
return true;
}
on_zoom_level_changed ();
button_press_event.connect (on_button_press);
update_header ();
restore_state ();
}
public MainWindow (Gtk.Application app) {
Object (
application: app,
icon_name: Build.DOMAIN,
title: Build.NAME,
resizable: true,
window_position: WindowPosition.CENTER
);
}
public int get_visible_id () {
return int.parse (view_stack.get_visible_child_name ());
}
public bool open_view (Views.Base widget) {
var curr = view_stack.visible_child as Views.Base;
if (curr != null)
curr.current = false;
var i = get_visible_id ();
i++;
widget.stack_pos = i;
widget.show ();
view_stack.add_named (widget, i.to_string ());
view_stack.set_visible_child_name (i.to_string ());
update_header ();
widget.current = true;
return true;
}
public bool back () {
var i = get_visible_id ();
if (i == 0)
return false;
var child = view_stack.get_child_by_name (i.to_string ());
view_stack.set_visible_child_name ((i-1).to_string ());
(child as Views.Base).current = false;
child.destroy ();
update_header ();
var curr = view_stack.visible_child as Views.Base;
if (curr != null)
curr.current = true;
return true;
}
public void reopen_view (int view_id) {
var i = get_visible_id ();
while (i != view_id && view_id != 0) {
back ();
i = get_visible_id ();
}
}
bool clean_unused_views () {
deck.get_children ().foreach (c => {
var view = c as Views.Base;
if (view != null && view.unused)
view.destroy ();
});
return Source.REMOVE;
}
public override bool delete_event (Gdk.EventAny event) {
window = null;
return app.on_window_closed ();
}
public void switch_timeline (int32 num) {
timeline_stack.visible_child_name = num.to_string ();
}
[Deprecated]
public void switch_timeline (int32 num) {
}
public void set_header_controls (Widget w) {
reset_header_controls ();
view_controls.add (w);
view_controls.reveal_child = true;
}
public void reset_header_controls () {
view_controls.reveal_child = false;
view_controls.get_children ().@foreach (w => {
view_controls.remove (w);
});
}
bool on_button_press (EventButton ev) {
if (ev.button == 8)
return back ();
return false;
}
bool on_button_press (EventButton ev) {
if (ev.button == 8)
return back ();
return false;
}
void on_zoom_level_changed () {
var css ="""
.%s label {
font-size: %i%;
}
""".printf (ZOOM_CLASS, settings.post_text_size);
void add_timeline_view (Views.Base view, string[] accelerators, int32 num) {
timeline_stack.add_titled (view, num.to_string (), view.label);
timeline_stack.child_set_property (view, "icon-name", view.icon);
view.notify["needs-attention"].connect (() => {
timeline_stack.child_set_property (view, "needs-attention", view.needs_attention);
});
}
try {
app.zoom_css_provider.load_from_data (css);
}
catch (Error e) {
warning (@"Can't set zoom level: $(e.message)");
}
}
void update_header () {
bool primary_mode = get_visible_id () == 0;
switcher_navbar.visible = timeline_switcher.sensitive = primary_mode;
timeline_switcher.opacity = primary_mode ? 1 : 0; //Prevent HeaderBar height jitter
view_navigation.reveal_child = !primary_mode;
void on_view_changed () {
var view = deck.visible_child as Views.Base;
if (primary_mode)
header.custom_title = timeline_switcher;
}
if (last_view != null) {
last_view.current = false;
last_view.on_hidden ();
}
void on_timeline_changed (ParamSpec spec) {
var view = timeline_stack.visible_child as Views.Base;
if (view != null) {
view.current = true;
view.on_shown ();
}
if (last_view != null)
last_view.current = false;
if (view != null) {
view.current = true;
last_view = view;
}
}
void on_zoom_level_changed () {
var css ="""
.%s label {
font-size: %i%;
}
""".printf (ZOOM_CLASS, settings.post_text_size);
try {
app.zoom_css_provider.load_from_data (css);
}
catch (Error e) {
warning (@"Can't set zoom level: $(e.message)");
}
}
last_view = view;
}
}

View File

@ -1,7 +1,7 @@
using Gtk;
[GtkTemplate (ui = "/com/github/bleakgrey/tootle/ui/dialogs/new_account.ui")]
public class Tootle.Dialogs.NewAccount: Gtk.Window {
public class Tootle.Dialogs.NewAccount: Hdy.Window {
const string scopes = "read%20write%20follow";

View File

@ -120,7 +120,7 @@ public class Tootle.Request : Soup.Message {
if (error != null)
throw new Oopsie.INSTANCE (error);
else
return this;
return this;
}
public static string array2string (Gee.ArrayList<string> array, string key) {

View File

@ -47,7 +47,7 @@ public class Tootle.Network : GLib.Object {
requests_processing++;
started ();
message (@"$(mess.method): $(mess.uri.to_string (false))");
// message (@"$(mess.method): $(mess.uri.to_string (false))");
try {
session.queue_message (mess, (sess, msg) => {

View File

@ -3,117 +3,145 @@ using Gtk;
[GtkTemplate (ui = "/com/github/bleakgrey/tootle/ui/views/base.ui")]
public class Tootle.Views.Base : Box {
public static string STATUS_EMPTY = _("Nothing to see here");
public static string STATUS_LOADING = " ";
public static string STATUS_EMPTY = _("Nothing to see here");
public static string STATUS_LOADING = " ";
public int stack_pos { get; set; default = -1; }
public string? icon { get; set; default = null; }
public string label { get; set; default = ""; }
public bool needs_attention { get; set; default = false; }
public bool current { get; set; default = false; }
public bool unused { get; set; default = false; }
public SimpleActionGroup? actions { get; set; }
[GtkChild]
protected ScrolledWindow scrolled;
[GtkChild]
protected Box view;
[GtkChild]
protected Hdy.Clamp clamp;
[GtkChild]
protected Box column_view;
[GtkChild]
protected Stack states;
[GtkChild]
protected Box content;
[GtkChild]
protected ListBox content_list;
[GtkChild]
protected Button status_button;
[GtkChild]
Stack status_stack;
[GtkChild]
Label status_message_label;
public Container content { get; set; }
public string state { get; set; default = "status"; }
public string status_message { get; set; default = STATUS_EMPTY; }
[GtkChild]
protected Hdy.HeaderBar header;
[GtkChild]
protected Button back_button;
public bool empty {
get {
return content_list.get_children ().length () <= 0;
}
}
[GtkChild]
protected ScrolledWindow scrolled;
[GtkChild]
protected Box view;
[GtkChild]
protected Hdy.Clamp clamp;
[GtkChild]
protected Box column_view;
[GtkChild]
protected Stack states;
[GtkChild]
protected Box content_box;
[GtkChild]
protected ListBox content_list;
[GtkChild]
protected Button status_button;
[GtkChild]
Stack status_stack;
[GtkChild]
Label status_message_label;
construct {
status_button.label = _("Reload");
bind_property ("state", states, "visible-child-name", BindingFlags.SYNC_CREATE);
scrolled.edge_reached.connect (pos => {
if (pos == PositionType.BOTTOM)
on_bottom_reached ();
});
content.remove.connect (() => on_content_changed ());
content_list.remove.connect (() => on_content_changed ());
content_list.row_activated.connect (on_content_item_activated);
public string state { get; set; default = "status"; }
public string status_message { get; set; default = STATUS_EMPTY; }
notify["status-message"].connect (() => {
status_message_label.label = @"<span size='large'>$status_message</span>";
status_stack.visible_child_name = status_message == STATUS_LOADING ? "spinner" : "message";
});
public bool empty {
get {
return content.get_children ().length () <= 0;
}
}
notify["current"].connect (() => {
if (current)
on_shown ();
else
on_hidden ();
});
construct {
bind_property ("label", header, "title", BindingFlags.SYNC_CREATE);
size_allocate.connect (on_resized);
get_style_context ().add_class (Dialogs.MainWindow.ZOOM_CLASS);
}
content = content_list;
public virtual void clear (){
content_list.forall (w => {
w.destroy ();
});
state = "status";
}
status_button.label = _("Reload");
bind_property ("state", states, "visible-child-name", BindingFlags.SYNC_CREATE);
scrolled.edge_reached.connect (pos => {
if (pos == PositionType.BOTTOM)
on_bottom_reached ();
});
content.remove.connect (() => on_content_changed ());
content_list.remove.connect (() => on_content_changed ());
content_list.row_activated.connect (on_content_item_activated);
public virtual void on_bottom_reached () {}
public virtual void on_shown () {}
public virtual void on_hidden () {}
notify["status-message"].connect (() => {
status_message_label.label = @"<span size='large'>$status_message</span>";
status_stack.visible_child_name = status_message == STATUS_LOADING ? "spinner" : "message";
});
public virtual void on_content_changed () {
if (empty) {
status_message = STATUS_EMPTY;
state = "status";
}
else {
state = "content";
}
check_resize ();
}
notify["current"].connect (() => {
if (current)
on_shown ();
else
on_hidden ();
});
public virtual void on_error (int32 code, string reason) {
status_message = reason;
status_button.visible = true;
status_button.sensitive = true;
state = "status";
}
scrolled.get_style_context ().add_class (Dialogs.MainWindow.ZOOM_CLASS);
protected void on_resized () {
Allocation alloc;
get_allocation (out alloc);
build_header ();
}
var target_w = clamp.maximum_size;
var view_w = alloc.width;
public virtual void build_header () {}
var ctx = view.get_style_context ();
if (view_w <= target_w && ctx.has_class ("padded"))
ctx.remove_class ("padded");
if (view_w > target_w && !ctx.has_class ("padded"))
ctx.add_class ("padded");
}
public virtual void clear (){
content.forall (w => {
w.destroy ();
});
state = "status";
}
public virtual void on_content_item_activated (ListBoxRow row) {
Signal.emit_by_name (row, "open");
public virtual void on_bottom_reached () {}
public virtual void on_shown () {
if (actions != null)
window.insert_action_group ("view", actions);
}
public virtual void on_hidden () {
if (actions != null)
window.insert_action_group ("view", null);
}
public virtual void on_content_changed () {
if (empty) {
status_message = STATUS_EMPTY;
state = "status";
}
else {
state = "content";
}
check_resize ();
}
public virtual void on_error (int32 code, string reason) {
status_message = reason;
status_button.visible = true;
status_button.sensitive = true;
state = "status";
}
[GtkCallback]
protected void on_resized () {
Allocation alloc;
get_allocation (out alloc);
var target_w = clamp.maximum_size;
var view_w = alloc.width;
var ctx = view.get_style_context ();
if (view_w <= target_w && ctx.has_class ("padded"))
ctx.remove_class ("padded");
if (view_w > target_w && !ctx.has_class ("padded"))
ctx.add_class ("padded");
}
public virtual void on_content_item_activated (ListBoxRow row) {
Signal.emit_by_name (row, "open");
}
[GtkCallback]
void on_close () {
window.back ();
}
}

37
src/Views/Main.vala Normal file
View File

@ -0,0 +1,37 @@
using Gtk;
public class Tootle.Views.Main : Views.TabbedBase {
public Widgets.AccountsButton account_button;
public Button compose_button;
public Button search_button;
public Main () {
add_tab (new Views.Home ());
add_tab (new Views.Notifications ());
add_tab (new Views.Local ());
add_tab (new Views.Federated ());
}
public override void build_header () {
base.build_header ();
back_button.visible = false;
account_button = new Widgets.AccountsButton ();
account_button.show ();
header.pack_start (account_button);
compose_button = new Button.from_icon_name ("document-edit-symbolic");
compose_button.tooltip_text = _("Compose");
compose_button.action_name = "app.compose";
compose_button.show ();
header.pack_start (compose_button);
search_button = new Button.from_icon_name ("edit-find-symbolic");
search_button.tooltip_text = _("Search");
search_button.action_name = "app.search";
search_button.show ();
header.pack_end (search_button);
}
}

View File

@ -8,7 +8,6 @@ public class Tootle.Views.Profile : Views.Timeline {
public bool only_media { get; set; default = false; }
public string source { get; set; default = "statuses"; }
SimpleActionGroup actions;
SimpleAction media_action;
SimpleAction replies_action;
SimpleAction muting_action;
@ -19,14 +18,14 @@ public class Tootle.Views.Profile : Views.Timeline {
ListBox profile_list;
Label relationship;
Widgets.TimelineMenu menu_button;
Button rs_button;
Label rs_button_label;
Widgets.AdaptiveButton rs_button;
SourceFunc? rs_button_action;
weak ListBoxRow note_row;
construct {
build_actions ();
menu_button = new Widgets.TimelineMenu ("profile-menu");
var builder = new Builder.from_resource (@"$(Build.RESOURCES)ui/views/profile_header.ui");
profile_list = builder.get_object ("profile_list") as ListBox;
@ -38,11 +37,15 @@ public class Tootle.Views.Profile : Views.Timeline {
var avatar = builder.get_object ("avatar") as Widgets.Avatar;
avatar.url = profile.avatar;
profile.bind_property ("display-name", menu_button.title, "label", BindingFlags.SYNC_CREATE);
var domain = "@" + profile.domain;
menu_button.title.label = profile.handle.replace (domain, "");
menu_button.subtitle.label = domain;
if ("@" in profile.acct)
menu_button.subtitle.show ();
var handle = builder.get_object ("handle") as Widgets.RichLabel;
profile.bind_property ("acct", handle, "text", BindingFlags.SYNC_CREATE, (b, src, ref target) => {
var text = "@" + (string) src;
profile.bind_property ("display-name", handle, "text", BindingFlags.SYNC_CREATE, (b, src, ref target) => {
var text = (string) src;
target.set_string (@"<span size=\"x-large\" weight=\"bold\">$text</span>");
return true;
});
@ -57,9 +60,6 @@ public class Tootle.Views.Profile : Views.Timeline {
});
relationship = builder.get_object ("relationship") as Label;
rs_button = builder.get_object ("rs_button") as Button;
rs_button.clicked.connect (on_rs_button_clicked);
rs_button_label = builder.get_object ("rs_button_label") as Label;
rs.notify["id"].connect (on_rs_updated);
rebuild_fields ();
@ -77,6 +77,20 @@ public class Tootle.Views.Profile : Views.Timeline {
menu_button.destroy ();
}
public override void build_header () {
rs_button = new Widgets.AdaptiveButton ();
rs_button.clicked.connect (() => {
if (rs_button_action != null) {
rs_button.sensitive = false;
rs_button_action ();
}
});
header.custom_title = menu_button = new Widgets.TimelineMenu ("profile-menu");
if (profile.id != accounts.active.id)
header.pack_end (rs_button);
}
void build_actions () {
actions = new SimpleActionGroup ();
@ -114,6 +128,12 @@ public class Tootle.Views.Profile : Views.Timeline {
});
actions.add_action (mention_action);
var copy_handle_action = new SimpleAction ("copy_handle", null);
copy_handle_action.activate.connect (v => {
Desktop.copy (profile.handle);
});
actions.add_action (copy_handle_action);
muting_action = new SimpleAction.stateful ("muting", null, false);
muting_action.change_state.connect (v => {
var state = v.get_boolean ();
@ -181,24 +201,6 @@ public class Tootle.Views.Profile : Views.Timeline {
}
}
public override void on_shown () {
window.insert_action_group ("view", actions);
window.header.custom_title = menu_button;
menu_button.valign = Align.FILL;
window.set_header_controls (rs_button);
}
public override void on_hidden () {
window.insert_action_group ("view", null);
window.header.custom_title = null;
window.reset_header_controls ();
}
void on_rs_button_clicked () {
rs_button.sensitive = false;
rs.modify (rs.following ? "unfollow" : "follow");
}
void on_rs_updated () {
var label = "";
if (rs_button.sensitive = rs != null) {
@ -209,12 +211,13 @@ public class Tootle.Views.Profile : Views.Timeline {
else if (rs.followed_by)
label = _("Follows you");
var ctx = rs_button.get_style_context ();
ctx.remove_class (STYLE_CLASS_SUGGESTED_ACTION);
ctx.remove_class (STYLE_CLASS_DESTRUCTIVE_ACTION);
ctx.add_class (rs.following ? STYLE_CLASS_DESTRUCTIVE_ACTION : STYLE_CLASS_SUGGESTED_ACTION);
rs_button_label.label = rs.following ? _("Unfollow") : _("Follow");
string action_icon = "";
string action_label = "";
get_rs_button_state (ref action_label, ref action_icon, ref rs_button_action);
rs_button.icon_name = action_icon;
rs_button.label = action_label;
}
relationship.label = label;
@ -223,6 +226,40 @@ public class Tootle.Views.Profile : Views.Timeline {
invalidate_actions (false);
}
void get_rs_button_state (ref string label, ref string icon_name, ref SourceFunc? fn) {
if (rs == null) return;
if (rs.blocking) {
label = _("Unblock");
icon_name = "view-reveal-symbolic";
fn = () => {
blocking_action.change_state (false);
rs_button.sensitive = true;
return true;
};
return;
}
else if (rs.following || rs.requested) {
label = _("Unfollow");
icon_name = "list-remove-symbolic";
fn = () => {
rs.modify ("unfollow");
return true;
};
return;
}
else if (!rs.following) {
label = _("Follow");
icon_name = "list-add-symbolic";
fn = () => {
rs.modify ("follow");
return true;
};
return;
}
}
public override Request append_params (Request req) {
if (page_next == null && source == "statuses") {
req.with_param ("exclude_replies", @"$(!include_replies)");

View File

@ -1,75 +1,82 @@
using Gtk;
public class Tootle.Views.Search : Views.Base {
public class Tootle.Views.Search : Views.TabbedBase {
string query = "";
SearchBar bar;
public string query { get; set; default = ""; }
Hdy.SearchBar bar;
Hdy.Clamp bar_clamp;
SearchEntry entry;
construct {
label = _("Search");
Views.Base accounts_tab;
Views.Base statuses_tab;
Views.Base hashtags_tab;
bar = new SearchBar ();
public Search () {
Object (label: _("Search"));
bar = new Hdy.SearchBar ();
bar.search_mode_enabled = true;
bar.show ();
pack_start (bar, false, false, 0);
reorder_child (bar, 2);
entry = new SearchEntry ();
entry.width_chars = 25;
entry.text = query;
entry.show ();
bar.add (entry);
bar_clamp = new Hdy.Clamp ();
bar_clamp.show ();
bar_clamp.add (entry);
bar.add (bar_clamp);
bar.connect_entry (entry);
entry.activate.connect (() => request ());
entry.icon_press.connect (() => request ());
entry.icon_press.connect (() => {
entry.text = "";
request ();
});
entry.grab_focus_without_selecting ();
status_button.clicked.connect (request);
accounts_tab = add_list_tab (_("Accounts"), "system-users-symbolic");
statuses_tab = add_list_tab (_("Statuses"), "user-available-symbolic");
hashtags_tab = add_list_tab (_("Hashtags"), "emoji-flags-symbolic");
request ();
}
bool append (owned Entity entity) {
bool append (Views.Base tab, owned Entity entity) {
var w = entity.to_widget ();
content_list.insert (w, -1);
tab.content_list.insert (w, -1);
return true;
}
void append_header (string name) {
var w = new Label (@"<span weight='bold' size='medium'>$name</span>");
w.halign = Align.START;
w.margin = 8;
w.use_markup = true;
w.show ();
content_list.insert (w, -1);
}
void request () {
query = entry.text.chug ().chomp ();
if (query == "") {
clear ();
state = "status";
status_message = _("Enter query");
return;
}
clear ();
state = "status";
status_message = STATUS_LOADING;
API.SearchResults.request.begin (query, accounts.active, (obj, res) => {
try {
var results = API.SearchResults.request.end (res);
if (!results.accounts.is_empty) {
append_header (_("People"));
results.accounts.@foreach (append);
results.accounts.@foreach (e => append (accounts_tab, e));
}
if (!results.statuses.is_empty) {
append_header (_("Posts"));
results.statuses.@foreach (append);
results.statuses.@foreach (e => append (statuses_tab, e));
}
if (!results.hashtags.is_empty) {
append_header (_("Hashtags"));
results.hashtags.@foreach (append);
results.hashtags.@foreach (e => append (hashtags_tab, e));
}
on_content_changed ();

116
src/Views/TabbedBase.vala Normal file
View File

@ -0,0 +1,116 @@
using Gtk;
public class Tootle.Views.TabbedBase : Views.Base {
static int ID_COUNTER = 0;
protected Hdy.ViewSwitcherTitle switcher_title;
protected Hdy.ViewSwitcherBar switcher_bar;
protected Stack stack;
Views.Base? last_view = null;
construct {
content = content_box;
content_list.destroy ();
state = "content";
states.get_parent ().remove (states);
view.get_style_context ().remove_class ("app-view");
scrolled.destroy ();
pack_start (states);
stack = new Stack ();
stack.transition_duration = 100;
stack.transition_type = StackTransitionType.CROSSFADE;
stack.notify["visible-child"].connect (on_view_switched);
stack.show ();
content_box.pack_start (stack);
switcher_bar.stack = switcher_title.stack = stack;
}
public override void build_header () {
switcher_title = new Hdy.ViewSwitcherTitle ();
switcher_title.show ();
header.bind_property ("title", switcher_title, "title", BindingFlags.SYNC_CREATE);
header.bind_property ("subtitle", switcher_title, "subtitle", BindingFlags.SYNC_CREATE);
header.custom_title = switcher_title;
switcher_bar = new Hdy.ViewSwitcherBar ();
switcher_bar.show ();
switcher_title.bind_property ("title-visible", switcher_bar, "reveal", BindingFlags.SYNC_CREATE);
pack_end (switcher_bar, false, false, 0);
}
public void add_tab (Views.Base view) {
ID_COUNTER++;
stack.add_titled (view, ID_COUNTER.to_string (), view.label);
stack.child_set_property (view, "icon-name", view.icon);
view.notify["needs-attention"].connect (() => {
stack.child_set_property (view, "needs-attention", view.needs_attention);
});
view.header.hide ();
}
public Views.Base add_list_tab (string label, string icon) {
var tab = new Views.Base ();
tab.label = label;
tab.icon = icon;
add_tab (tab);
return tab;
}
public delegate void TabCB (Views.Base tab);
public void foreach_tab (TabCB cb) {
stack.@foreach (child => {
var tab = child as Views.Base;
if (tab != null)
cb (tab);
});
}
public override void clear () {
foreach_tab (tab => tab.clear ());
on_content_changed ();
}
public override void on_content_changed () {
var empty = true;
foreach_tab (tab => {
tab.visible = !tab.empty;
if (tab.visible)
empty = false;
tab.on_content_changed ();
});
if (empty) {
state = "status";
status_message = STATUS_EMPTY;
}
else {
state = "content";
}
}
void on_view_switched () {
var view = stack.visible_child as Views.Base;
if (last_view != null) {
last_view.current = false;
last_view.on_hidden ();
}
if (view != null) {
header.title = view.label;
view.current = true;
view.on_shown ();
}
last_view = view;
}
}

View File

@ -1,15 +1,16 @@
using Gtk;
public class Tootle.Views.ExpandedStatus : Views.Base, IAccountListener {
public class Tootle.Views.Thread : Views.Base, IAccountListener {
public API.Status root_status { get; construct set; }
protected InstanceAccount? account = null;
protected Widget root_widget;
public ExpandedStatus (API.Status status) {
public Thread (API.Status status) {
Object (
root_status: status,
status_message: STATUS_LOADING
status_message: STATUS_LOADING,
label: _("Conversation")
);
account_listener_init ();
}
@ -61,7 +62,6 @@ public class Tootle.Views.ExpandedStatus : Views.Base, IAccountListener {
int x,y;
translate_coordinates (root_widget, 0, 0, out x, out y);
scrolled.vadjustment.value = (double)(y*-1);
//content_list.select_row (root_widget);
})
.exec ();
}
@ -77,7 +77,7 @@ public class Tootle.Views.ExpandedStatus : Views.Base, IAccountListener {
var node = statuses.get_element (0);
if (node != null){
var status = API.Status.from (node);
window.open_view (new Views.ExpandedStatus (status));
window.open_view (new Views.Thread (status));
}
else
Desktop.open_uri (q);

View File

@ -70,8 +70,6 @@ public class Tootle.Widgets.AccountsButton : Gtk.MenuButton, IAccountListener {
[GtkChild]
ModelButton item_refresh;
[GtkChild]
ModelButton item_search;
[GtkChild]
Button item_favs;
[GtkChild]
Button item_conversations;
@ -82,6 +80,7 @@ public class Tootle.Widgets.AccountsButton : Gtk.MenuButton, IAccountListener {
construct {
account_listener_init ();
get_style_context ().add_class ("image-button");
item_refresh.clicked.connect (() => {
app.refresh ();
@ -103,10 +102,6 @@ public class Tootle.Widgets.AccountsButton : Gtk.MenuButton, IAccountListener {
window.open_view (new Views.Lists ());
popover.popdown ();
});
item_search.clicked.connect (() => {
window.open_view (new Views.Search ());
popover.popdown ();
});
item_prefs.clicked.connect (() => {
Dialogs.Preferences.open ();
popover.popdown ();

View File

@ -0,0 +1,33 @@
using Hdy;
using Gtk;
[GtkTemplate (ui = "/com/github/bleakgrey/tootle/ui/widgets/adaptive_button.ui")]
public class Tootle.Widgets.AdaptiveButton : Box {
public string label { get; set; }
public string icon_name { get; set; default = "image-loading-symbolic"; }
public signal void clicked ();
[GtkChild]
Button full;
[GtkChild]
Button mini;
[GtkChild]
Image image1;
[GtkChild]
Image image2;
construct {
var butts = new Button[]{ full, mini };
bind_property ("label", full, "label", BindingFlags.SYNC_CREATE);
foreach (Button butt in butts) {
bind_property ("tooltip_text", butt, "tooltip_text", BindingFlags.SYNC_CREATE);
butt.clicked.connect (() => clicked ());
}
foreach (Image img in new Image[]{ image1, image2 }) {
bind_property ("icon_name", img, "icon_name", BindingFlags.SYNC_CREATE);
}
}
}

View File

@ -138,7 +138,7 @@ public class Tootle.Widgets.Status : ListBoxRow {
status.formal.bind_property ("pinned", pin_indicator, "visible", BindingFlags.SYNC_CREATE);
bind_property ("avatar_url", avatar, "url", BindingFlags.SYNC_CREATE);
status.bind_property ("has-spoiler", this, "reveal-spoiler", BindingFlags.SYNC_CREATE, (b, src, ref target) => {
status.formal.bind_property ("has-spoiler", this, "reveal-spoiler", BindingFlags.SYNC_CREATE, (b, src, ref target) => {
target.set_boolean (!src.get_boolean ());
return true;
});

View File

@ -5,6 +5,8 @@ public class Tootle.Widgets.TimelineMenu : MenuButton {
[GtkChild]
public Label title;
[GtkChild]
public Label subtitle;
public TimelineMenu (string id) {
var builder = new Builder.from_resource (@"$(Build.RESOURCES)ui/menus.ui");