Browse Source

components: Port to Blueprint

fractal-13
Kévin Commaille 7 months ago
parent
commit
b12050a64c
No known key found for this signature in database
GPG Key ID: F26F4BE20A08255B
  1. 28
      po/POTFILES.in
  2. 2
      src/account_chooser_dialog/account_row.blp
  3. 4
      src/account_switcher/account_switcher_button.blp
  4. 2
      src/account_switcher/session_item.blp
  5. 35
      src/blp-resources.in
  6. 134
      src/components/action_button.blp
  7. 144
      src/components/action_button.ui
  8. 85
      src/components/avatar/editable.blp
  9. 95
      src/components/avatar/editable.ui
  10. 11
      src/components/avatar/mod.blp
  11. 16
      src/components/avatar/mod.ui
  12. 38
      src/components/camera/qrcode_scanner.blp
  13. 45
      src/components/camera/qrcode_scanner.ui
  14. 15
      src/components/context_menu_bin.blp
  15. 18
      src/components/context_menu_bin.ui
  16. 275
      src/components/crypto/identity_setup_view.blp
  17. 301
      src/components/crypto/identity_setup_view.ui
  18. 507
      src/components/crypto/recovery_setup_view.blp
  19. 557
      src/components/crypto/recovery_setup_view.ui
  20. 120
      src/components/dialogs/auth/in_browser_page.blp
  21. 129
      src/components/dialogs/auth/in_browser_page.ui
  22. 15
      src/components/dialogs/auth/mod.blp
  23. 16
      src/components/dialogs/auth/mod.ui
  24. 98
      src/components/dialogs/auth/password_page.blp
  25. 105
      src/components/dialogs/auth/password_page.ui
  26. 197
      src/components/dialogs/room_preview.blp
  27. 215
      src/components/dialogs/room_preview.ui
  28. 6
      src/components/dialogs/toastable.blp
  29. 8
      src/components/dialogs/toastable.ui
  30. 21
      src/components/dialogs/user_profile.blp
  31. 27
      src/components/dialogs/user_profile.ui
  32. 23
      src/components/loading/bin.blp
  33. 29
      src/components/loading/bin.ui
  34. 8
      src/components/media/audio_player.blp
  35. 10
      src/components/media/audio_player.ui
  36. 27
      src/components/media/content_viewer.blp
  37. 36
      src/components/media/content_viewer.ui
  38. 21
      src/components/media/location_viewer.blp
  39. 20
      src/components/media/location_viewer.ui
  40. 32
      src/components/media/video_player.blp
  41. 35
      src/components/media/video_player.ui
  42. 18
      src/components/pill/mod.blp
  43. 26
      src/components/pill/mod.ui
  44. 38
      src/components/pill/search_entry.blp
  45. 45
      src/components/pill/search_entry.ui
  46. 37
      src/components/pill/source_row.blp
  47. 55
      src/components/pill/source_row.ui
  48. 44
      src/components/power_level_selection/combo_box.blp
  49. 50
      src/components/power_level_selection/combo_box.ui
  50. 154
      src/components/power_level_selection/popover.blp
  51. 184
      src/components/power_level_selection/popover.ui
  52. 125
      src/components/power_level_selection/row.blp
  53. 132
      src/components/power_level_selection/row.ui
  54. 24
      src/components/rows/button_count_row.blp
  55. 24
      src/components/rows/button_count_row.ui
  56. 14
      src/components/rows/check_loading_row.blp
  57. 16
      src/components/rows/check_loading_row.ui
  58. 47
      src/components/rows/combo_loading_row.blp
  59. 51
      src/components/rows/combo_loading_row.ui
  60. 24
      src/components/rows/copyable_row.blp
  61. 25
      src/components/rows/copyable_row.ui
  62. 20
      src/components/rows/entry_add_row.blp
  63. 20
      src/components/rows/entry_add_row.ui
  64. 32
      src/components/rows/loading_button_row.blp
  65. 30
      src/components/rows/loading_button_row.ui
  66. 31
      src/components/rows/loading_row.blp
  67. 36
      src/components/rows/loading_row.ui
  68. 19
      src/components/rows/removable_row.blp
  69. 20
      src/components/rows/removable_row.ui
  70. 103
      src/components/rows/substring_entry_row.blp
  71. 104
      src/components/rows/substring_entry_row.ui
  72. 24
      src/components/rows/switch_loading_row.blp
  73. 26
      src/components/rows/switch_loading_row.ui
  74. 233
      src/components/user_page.blp
  75. 264
      src/components/user_page.ui
  76. 35
      src/ui-resources.gresource.xml
  77. 2
      src/window.blp

28
po/POTFILES.in

@ -9,33 +9,33 @@ src/account_switcher/account_switcher_button.blp
src/account_switcher/account_switcher_popover.blp
src/account_switcher/session_item.blp
src/application.rs
src/components/action_button.ui
src/components/action_button.blp
src/components/avatar/editable.rs
src/components/avatar/editable.ui
src/components/avatar/editable.blp
src/components/camera/qrcode_scanner.rs
src/components/camera/qrcode_scanner.ui
src/components/camera/qrcode_scanner.blp
src/components/camera/viewfinder.rs
src/components/crypto/identity_setup_view.rs
src/components/crypto/identity_setup_view.ui
src/components/crypto/identity_setup_view.blp
src/components/crypto/recovery_setup_view.rs
src/components/crypto/recovery_setup_view.ui
src/components/dialogs/auth/in_browser_page.ui
src/components/crypto/recovery_setup_view.blp
src/components/dialogs/auth/in_browser_page.blp
src/components/dialogs/auth/mod.rs
src/components/dialogs/auth/mod.ui
src/components/dialogs/auth/password_page.ui
src/components/dialogs/auth/mod.blp
src/components/dialogs/auth/password_page.blp
src/components/dialogs/message_dialogs.rs
src/components/dialogs/room_preview.rs
src/components/dialogs/room_preview.ui
src/components/dialogs/user_profile.ui
src/components/dialogs/room_preview.blp
src/components/dialogs/user_profile.blp
src/components/offline_banner.rs
src/components/media/content_viewer.rs
src/components/media/location_viewer.rs
src/components/pill/at_room.rs
src/components/power_level_selection/popover.ui
src/components/power_level_selection/row.ui
src/components/rows/loading_row.ui
src/components/power_level_selection/popover.blp
src/components/power_level_selection/row.blp
src/components/rows/loading_row.blp
src/components/user_page.rs
src/components/user_page.ui
src/components/user_page.blp
src/contrib/qr_code.rs
src/error_page.blp
src/error_page.rs

2
src/account_chooser_dialog/account_row.blp

@ -8,7 +8,7 @@ template $AccountChooserDialogRow: Gtk.ListBoxRow {
spacing: 10;
$Avatar avatar {
size: "40";
size: 40;
}
Gtk.Box {

4
src/account_switcher/account_switcher_button.blp

@ -16,8 +16,8 @@ template $AccountSwitcherButton: Gtk.ToggleButton {
]
child: $Avatar {
size: "24";
size: 24;
data: bind template.root as <$Window>.session-selection as <$FixedSelection>.selected-item as <$SessionInfo>.avatar-data;
accessible-role: "presentation";
accessible-role: presentation;
};
}

2
src/account_switcher/session_item.blp

@ -12,7 +12,7 @@ template $SessionItemRow: Gtk.ListBoxRow {
spacing: 10;
$AvatarWithSelection avatar {
size: "40";
size: 40;
}
Gtk.Box {

35
src/blp-resources.in

@ -6,5 +6,40 @@ account_switcher/account_switcher_button.blp
account_switcher/account_switcher_popover.blp
account_switcher/avatar_with_selection.blp
account_switcher/session_item.blp
components/action_button.blp
components/avatar/editable.blp
components/avatar/mod.blp
components/camera/qrcode_scanner.blp
components/context_menu_bin.blp
components/crypto/identity_setup_view.blp
components/crypto/recovery_setup_view.blp
components/dialogs/auth/in_browser_page.blp
components/dialogs/auth/mod.blp
components/dialogs/auth/password_page.blp
components/dialogs/room_preview.blp
components/dialogs/toastable.blp
components/dialogs/user_profile.blp
components/loading/bin.blp
components/media/audio_player.blp
components/media/content_viewer.blp
components/media/location_viewer.blp
components/media/video_player.blp
components/pill/mod.blp
components/pill/search_entry.blp
components/pill/source_row.blp
components/power_level_selection/combo_box.blp
components/power_level_selection/popover.blp
components/power_level_selection/row.blp
components/rows/button_count_row.blp
components/rows/check_loading_row.blp
components/rows/combo_loading_row.blp
components/rows/copyable_row.blp
components/rows/entry_add_row.blp
components/rows/loading_button_row.blp
components/rows/loading_row.blp
components/rows/removable_row.blp
components/rows/substring_entry_row.blp
components/rows/switch_loading_row.blp
components/user_page.blp
error_page.blp
window.blp

134
src/components/action_button.blp

@ -0,0 +1,134 @@
using Gtk 4.0;
using Adw 1;
template $ActionButton: Adw.Bin {
Gtk.Stack stack {
transition-type: crossfade;
Gtk.StackPage {
name: "default";
child: Gtk.Button button_default {
styles [
"circular",
]
valign: center;
icon-name: bind template.icon-name;
action-name: bind template.action-name;
action-target: bind template.action-target;
clicked => $button_clicked() swapped;
};
}
Gtk.StackPage {
name: "confirm";
child: Gtk.Button {
styles [
"circular",
"suggested-action",
]
tooltip-text: _("Confirm Change");
valign: center;
icon-name: "checkmark-symbolic";
action-name: bind template.action-name;
action-target: bind template.action-target;
clicked => $button_clicked() swapped;
};
}
Gtk.StackPage {
name: "retry";
child: Gtk.Button {
styles [
"circular",
"suggested-action",
]
tooltip-text: _("Try Again");
valign: center;
icon-name: "refresh-symbolic";
action-name: bind template.action-name;
action-target: bind template.action-target;
clicked => $button_clicked() swapped;
};
}
Gtk.StackPage {
name: "loading";
title: _("Loading");
child: Gtk.Button {
styles [
"circular",
]
focusable: false;
can-target: false;
valign: center;
Adw.Spinner {
valign: center;
halign: center;
height-request: 20;
width-request: 20;
}
};
}
Gtk.StackPage {
name: "success";
title: _("Success");
child: Gtk.Button {
styles [
"suggested-action",
"circular",
"success",
]
focusable: false;
can-target: false;
valign: center;
icon-name: "checkmark-symbolic";
};
}
Gtk.StackPage {
name: "warning";
title: _("Warning");
child: Gtk.Button button_warning {
styles [
"circular",
"warning",
]
focusable: false;
can-target: false;
valign: center;
icon-name: "warning-symbolic";
};
}
Gtk.StackPage {
name: "error";
title: _("Error");
child: Gtk.Button {
styles [
"circular",
"error",
]
focusable: false;
can-target: false;
valign: center;
icon-name: "error-symbolic";
};
}
}
}

144
src/components/action_button.ui

@ -1,144 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="ActionButton" parent="AdwBin">
<child>
<object class="GtkStack" id="stack">
<property name="transition-type">crossfade</property>
<child>
<object class="GtkStackPage">
<property name="name">default</property>
<property name="child">
<object class="GtkButton" id="button_default">
<style>
<class name="circular"/>
</style>
<property name="valign">center</property>
<property name="icon-name" bind-source="ActionButton" bind-property="icon-name" bind-flags="sync-create"/>
<property name="action-name" bind-source="ActionButton" bind-property="action-name" bind-flags="sync-create"/>
<property name="action-target" bind-source="ActionButton" bind-property="action-target" bind-flags="sync-create"/>
<signal name="clicked" handler="button_clicked" swapped="true"/>
</object>
</property>
</object>
</child>
<child>
<object class="GtkStackPage">
<property name="name">confirm</property>
<property name="child">
<object class="GtkButton">
<style>
<class name="circular"/>
<class name="suggested-action"/>
</style>
<property name="tooltip-text" translatable="yes">Confirm Change</property>
<property name="valign">center</property>
<property name="icon-name">checkmark-symbolic</property>
<property name="action-name" bind-source="ActionButton" bind-property="action-name" bind-flags="sync-create"/>
<property name="action-target" bind-source="ActionButton" bind-property="action-target" bind-flags="sync-create"/>
<signal name="clicked" handler="button_clicked" swapped="true"/>
</object>
</property>
</object>
</child>
<child>
<object class="GtkStackPage">
<property name="name">retry</property>
<property name="child">
<object class="GtkButton">
<style>
<class name="circular"/>
<class name="suggested-action"/>
</style>
<property name="tooltip-text" translatable="yes">Try Again</property>
<property name="valign">center</property>
<property name="icon-name">refresh-symbolic</property>
<property name="action-name" bind-source="ActionButton" bind-property="action-name" bind-flags="sync-create"/>
<property name="action-target" bind-source="ActionButton" bind-property="action-target" bind-flags="sync-create"/>
<signal name="clicked" handler="button_clicked" swapped="true"/>
</object>
</property>
</object>
</child>
<child>
<object class="GtkStackPage">
<property name="name">loading</property>
<property name="title" translatable="yes">Loading</property>
<property name="child">
<object class="GtkButton">
<style>
<class name="circular"/>
</style>
<property name="focusable">false</property>
<property name="can-target">false</property>
<property name="valign">center</property>
<child>
<object class="AdwSpinner">
<property name="valign">center</property>
<property name="halign">center</property>
<property name="height-request">20</property>
<property name="width-request">20</property>
</object>
</child>
</object>
</property>
</object>
</child>
<child>
<object class="GtkStackPage">
<property name="name">success</property>
<property name="title" translatable="yes">Success</property>
<property name="child">
<object class="GtkButton">
<style>
<class name="suggested-action"/>
<class name="circular"/>
<class name="success"/>
</style>
<property name="focusable">false</property>
<property name="can-target">false</property>
<property name="valign">center</property>
<property name="icon-name">checkmark-symbolic</property>
</object>
</property>
</object>
</child>
<child>
<object class="GtkStackPage">
<property name="name">warning</property>
<property name="title" translatable="yes">Warning</property>
<property name="child">
<object class="GtkButton" id="button_warning">
<style>
<class name="circular"/>
<class name="warning"/>
</style>
<property name="focusable">false</property>
<property name="can-target">false</property>
<property name="valign">center</property>
<property name="icon-name">warning-symbolic</property>
</object>
</property>
</object>
</child>
<child>
<object class="GtkStackPage">
<property name="name">error</property>
<property name="title" translatable="yes">Error</property>
<property name="child">
<object class="GtkButton">
<style>
<class name="circular"/>
<class name="error"/>
</style>
<property name="focusable">false</property>
<property name="can-target">false</property>
<property name="valign">center</property>
<property name="icon-name">error-symbolic</property>
</object>
</property>
</object>
</child>
</object>
</child>
</template>
</interface>

85
src/components/avatar/editable.blp

@ -0,0 +1,85 @@
using Gtk 4.0;
using Adw 1;
template $EditableAvatar: Adw.Bin {
accessible-role: group;
Gtk.Overlay {
halign: center;
Gtk.Stack stack {
transition-type: crossfade;
Gtk.StackPage {
name: "default";
child: $Avatar {
size: 128;
data: bind template.data;
};
}
Gtk.StackPage {
name: "temp";
child: Adw.Avatar temp_avatar {
size: 128;
show-initials: true;
text: bind template.data as <$AvatarData>.display-name;
custom-image: bind template.temp-paintable;
};
}
}
[overlay]
Gtk.Image error_img {
styles [
"osd",
"circular",
]
visible: false;
halign: center;
valign: center;
icon-name: "error-symbolic";
icon-size: large;
layout {
measure: true;
}
}
[overlay]
Adw.Bin button_remove_bin {
styles [
"cutout",
]
halign: end;
valign: start;
$ActionButton button_remove {
icon-name: "remove-symbolic";
action-name: "editable-avatar.remove-avatar";
default-state-tooltip-text: _("Remove Avatar");
}
}
[overlay]
Adw.Bin {
styles [
"cutout",
]
visible: bind template.editable;
halign: end;
valign: end;
$ActionButton button_edit {
icon-name: "edit-symbolic";
action-name: "editable-avatar.edit-avatar";
default-state-tooltip-text: _("Select New Avatar");
}
}
}
}

95
src/components/avatar/editable.ui

@ -1,95 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="EditableAvatar" parent="AdwBin">
<property name="accessible-role">group</property>
<child>
<object class="GtkOverlay">
<property name="halign">center</property>
<child>
<object class="GtkStack" id="stack">
<property name="transition-type">crossfade</property>
<child>
<object class="GtkStackPage">
<property name="name">default</property>
<property name="child">
<object class="Avatar">
<property name="size">128</property>
<property name="data" bind-source="EditableAvatar" bind-property="data" bind-flags="sync-create"/>
</object>
</property>
</object>
</child>
<child>
<object class="GtkStackPage">
<property name="name">temp</property>
<property name="child">
<object class="AdwAvatar" id="temp_avatar">
<property name="size">128</property>
<property name="show-initials">true</property>
<binding name="text">
<lookup name="display-name">
<lookup name="data">
EditableAvatar
</lookup>
</lookup>
</binding>
<property name="custom-image" bind-source="EditableAvatar" bind-property="temp-paintable" bind-flags="sync-create"/>
</object>
</property>
</object>
</child>
</object>
</child>
<child type="overlay">
<object class="GtkImage" id="error_img">
<style>
<class name="osd"/>
<class name="circular"/>
</style>
<property name="visible">False</property>
<property name="halign">center</property>
<property name="valign">center</property>
<property name="icon-name">error-symbolic</property>
<property name="icon-size">large</property>
<layout>
<property name="measure">true</property>
</layout>
</object>
</child>
<child type="overlay">
<object class="AdwBin" id="button_remove_bin">
<style>
<class name="cutout" />
</style>
<property name="halign">end</property>
<property name="valign">start</property>
<child>
<object class="ActionButton" id="button_remove">
<property name="icon-name">remove-symbolic</property>
<property name="action-name">editable-avatar.remove-avatar</property>
<property name="default-state-tooltip-text" translatable="yes">Remove Avatar</property>
</object>
</child>
</object>
</child>
<child type="overlay">
<object class="AdwBin">
<style>
<class name="cutout" />
</style>
<property name="visible" bind-source="EditableAvatar" bind-property="editable" bind-flags="sync-create"/>
<property name="halign">end</property>
<property name="valign">end</property>
<child>
<object class="ActionButton" id="button_edit">
<property name="icon-name">edit-symbolic</property>
<property name="action-name">editable-avatar.edit-avatar</property>
<property name="default-state-tooltip-text" translatable="yes">Select New Avatar</property>
</object>
</child>
</object>
</child>
</object>
</child>
</template>
</interface>

11
src/components/avatar/mod.blp

@ -0,0 +1,11 @@
using Gtk 4.0;
using Adw 1;
template $Avatar: Adw.Bin {
notify::scale-factor => $update_scale_factor() swapped;
child: Adw.Avatar avatar {
show-initials: true;
text: bind template.data as <$AvatarData>.display-name;
};
}

16
src/components/avatar/mod.ui

@ -1,16 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="Avatar" parent="AdwBin">
<signal name="notify::scale-factor" handler="update_scale_factor" swapped="yes" />
<property name="child">
<object class="AdwAvatar" id="avatar">
<property name="show-initials">True</property>
<binding name="text">
<lookup name="display-name" type="AvatarData">
<lookup name="data">Avatar</lookup>
</lookup>
</binding>
</object>
</property>
</template>
</interface>

38
src/components/camera/qrcode_scanner.blp

@ -0,0 +1,38 @@
using Gtk 4.0;
using Adw 1;
template $QrCodeScanner: Adw.Bin {
accessibility {
label: _("QR Code Scanner");
}
Gtk.Stack stack {
transition-type: crossfade;
Gtk.StackPage {
name: "loading";
title: _("Loading");
child: Adw.Spinner {};
}
Gtk.StackPage {
name: "no-camera";
title: _("Could Not Connect to Camera");
child: Gtk.Box {
orientation: vertical;
Gtk.Image {
icon-name: "no-camera-symbolic";
pixel-size: 148;
accessible-role: presentation;
}
Gtk.Label no_camera_label {
label: _("Could Not Connect to Camera");
}
};
}
}
}

45
src/components/camera/qrcode_scanner.ui

@ -1,45 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="QrCodeScanner" parent="AdwBin">
<accessibility>
<property name="label">QR Code Scanner</property>
</accessibility>
<child>
<object class="GtkStack" id="stack">
<property name="transition-type">crossfade</property>
<child>
<object class="GtkStackPage">
<property name="name">loading</property>
<property name="title" translatable="yes">Loading</property>
<property name="child">
<object class="AdwSpinner" />
</property>
</object>
</child>
<child>
<object class="GtkStackPage">
<property name="name">no-camera</property>
<property name="title" translatable="yes">Could Not Connect to Camera</property>
<property name="child">
<object class="GtkBox">
<property name="orientation">vertical</property>
<child>
<object class="GtkImage">
<property name="icon-name">no-camera-symbolic</property>
<property name="pixel-size">148</property>
<property name="accessible-role">presentation</property>
</object>
</child>
<child>
<object class="GtkLabel" id="no_camera_label">
<property name="label" translatable="yes">Could Not Connect to Camera</property>
</object>
</child>
</object>
</property>
</object>
</child>
</object>
</child>
</template>
</interface>

15
src/components/context_menu_bin.blp

@ -0,0 +1,15 @@
using Gtk 4.0;
template $ContextMenuBin: Gtk.Widget {
focusable: true;
Gtk.GestureClick click_gesture {
button: 3;
exclusive: true;
}
Gtk.GestureLongPress long_press_gesture {
touch-only: true;
exclusive: true;
}
}

18
src/components/context_menu_bin.ui

@ -1,18 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="ContextMenuBin" parent="GtkWidget">
<property name="focusable">True</property>
<child>
<object class="GtkGestureClick" id="click_gesture">
<property name="button">3</property>
<property name="exclusive">True</property>
</object>
</child>
<child>
<object class="GtkGestureLongPress" id="long_press_gesture">
<property name="touch_only">True</property>
<property name="exclusive">True</property>
</object>
</child>
</template>
</interface>

275
src/components/crypto/identity_setup_view.blp

@ -0,0 +1,275 @@
using Gtk 4.0;
using Adw 1;
template $CryptoIdentitySetupView: Adw.Bin {
child: Adw.NavigationView navigation {
Adw.NavigationPage {
tag: "choose-method";
title: _("Verify Your New Session");
shown => $grab_focus() swapped;
child: Adw.ToolbarView {
[top]
Adw.HeaderBar {
show-title: false;
}
content: Gtk.ScrolledWindow {
hscrollbar-policy: never;
propagate-natural-height: true;
vexpand: true;
child: Adw.Clamp {
maximum-size: 400;
tightening-threshold: 300;
child: Gtk.Box {
orientation: vertical;
spacing: 18;
valign: center;
halign: center;
Gtk.Label {
label: _("Verify Your New Session");
wrap: true;
wrap-mode: word_char;
justify: center;
styles [
"title-1",
]
}
Gtk.Label {
label: _("Verifying your session allows you and the people you chat with to be sure that no one is trying to impersonate you or intercept your conversations.");
wrap: true;
wrap-mode: word_char;
justify: center;
styles [
"body",
]
}
$LoadingButton send_request_btn {
can-shrink: true;
content-label: _("Verify With Another Session");
halign: center;
clicked => $send_request() swapped;
styles [
"pill",
]
}
Gtk.Label {
label: _("No other devices logged into this account?");
wrap: true;
wrap-mode: word_char;
justify: center;
}
Gtk.Button use_recovery_btn {
can-shrink: true;
label: _("Recover Account");
halign: center;
clicked => $recover() swapped;
styles [
"pill",
]
}
Gtk.Button {
can-shrink: true;
label: _("Reset");
halign: center;
clicked => $reset() swapped;
styles [
"pill",
]
}
};
};
};
};
}
Adw.NavigationPage {
tag: "verify";
title: _("Identity Verification");
shown => $grab_focus() swapped;
child: Adw.ToolbarView {
[top]
Adw.HeaderBar {
show-title: false;
}
content: $IdentityVerificationView verification_page {};
};
}
Adw.NavigationPage {
tag: "bootstrap";
title: _("Set Up Crypto Identity");
shown => $grab_focus() swapped;
child: Adw.ToolbarView {
[top]
Adw.HeaderBar {
show-title: false;
}
content: Gtk.ScrolledWindow {
hscrollbar-policy: never;
propagate-natural-height: true;
vexpand: true;
child: Adw.Clamp {
maximum-size: 400;
tightening-threshold: 300;
child: Gtk.Box {
orientation: vertical;
spacing: 18;
valign: center;
halign: center;
Gtk.Label {
label: _("Set Up Crypto Identity");
wrap: true;
wrap-mode: word_char;
justify: center;
styles [
"title-1",
]
}
Gtk.Label {
label: _("Your crypto identity allows you to verify other Matrix accounts and automatically trust their verified sessions.");
wrap: true;
wrap-mode: word_char;
justify: center;
styles [
"body",
]
}
Gtk.Label {
label: _("You need to set up a crypto identity, since it has never been created.");
wrap: true;
wrap-mode: word_char;
justify: center;
styles [
"body",
]
}
$LoadingButton bootstrap_btn {
content-label: _("Set Up");
halign: center;
clicked => $bootstrap_cross_signing() swapped;
styles [
"suggested-action",
"pill",
]
}
};
};
};
};
}
Adw.NavigationPage {
tag: "reset";
title: _("Reset Crypto Identity");
shown => $grab_focus() swapped;
child: Adw.ToolbarView {
[top]
Adw.HeaderBar {
show-title: false;
}
content: Gtk.ScrolledWindow {
hscrollbar-policy: never;
propagate-natural-height: true;
vexpand: true;
child: Adw.Clamp {
maximum-size: 400;
tightening-threshold: 300;
child: Gtk.Box {
orientation: vertical;
spacing: 18;
valign: center;
halign: center;
Gtk.Label {
label: _("Reset Crypto Identity");
wrap: true;
wrap-mode: word_char;
justify: center;
styles [
"title-1",
]
}
Gtk.Label {
label: _("Your crypto identity allows you to verify other Matrix accounts and automatically trust their verified sessions.");
wrap: true;
wrap-mode: word_char;
justify: center;
styles [
"body",
]
}
Gtk.Label {
label: _("You should reset your crypto identity if a device that does not belong to you managed to be verified.");
wrap: true;
wrap-mode: word_char;
justify: center;
styles [
"body",
]
}
Gtk.Label {
label: _("To proceed, you will also need to reset your account recovery key.");
wrap: true;
wrap-mode: word_char;
justify: center;
styles [
"body",
]
}
Gtk.Button reset_btn {
can-shrink: true;
label: _("Reset");
halign: center;
clicked => $reset() swapped;
styles [
"pill",
]
}
};
};
};
};
}
};
}

301
src/components/crypto/identity_setup_view.ui

@ -1,301 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="CryptoIdentitySetupView" parent="AdwBin">
<property name="child">
<object class="AdwNavigationView" id="navigation">
<child>
<object class="AdwNavigationPage">
<property name="tag">choose-method</property>
<property name="title" translatable="yes">Verify Your New Session</property>
<signal name="shown" handler="grab_focus" swapped="yes" />
<property name="child">
<object class="AdwToolbarView">
<child type="top">
<object class="AdwHeaderBar">
<property name="show-title">False</property>
</object>
</child>
<property name="content">
<object class="GtkScrolledWindow">
<property name="hscrollbar-policy">never</property>
<property name="propagate-natural-height">True</property>
<property name="vexpand">True</property>
<property name="child">
<object class="AdwClamp">
<property name="maximum-size">400</property>
<property name="tightening-threshold">300</property>
<property name="child">
<object class="GtkBox">
<property name="orientation">vertical</property>
<property name="spacing">18</property>
<property name="valign">center</property>
<property name="halign">center</property>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">Verify Your New Session</property>
<property name="wrap">True</property>
<property name="wrap-mode">word-char</property>
<property name="justify">center</property>
<style>
<class name="title-1"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">Verifying your session allows you and the people you chat with to be sure that no one is trying to impersonate you or intercept your conversations.</property>
<property name="wrap">True</property>
<property name="wrap-mode">word-char</property>
<property name="justify">center</property>
<style>
<class name="body"/>
</style>
</object>
</child>
<child>
<object class="LoadingButton" id="send_request_btn">
<property name="can-shrink">true</property>
<property name="content-label" translatable="yes">Verify With Another Session</property>
<property name="halign">center</property>
<signal name="clicked" handler="send_request" swapped="yes"/>
<style>
<class name="pill"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">No other devices logged into this account?</property>
<property name="wrap">True</property>
<property name="wrap-mode">word-char</property>
<property name="justify">center</property>
</object>
</child>
<child>
<object class="GtkButton" id="use_recovery_btn">
<property name="can-shrink">true</property>
<property name="label" translatable="yes">Recover Account</property>
<property name="halign">center</property>
<signal name="clicked" handler="recover" swapped="yes" />
<style>
<class name="pill"/>
</style>
</object>
</child>
<child>
<object class="GtkButton">
<property name="can-shrink">true</property>
<property name="label" translatable="yes">Reset</property>
<property name="halign">center</property>
<signal name="clicked" handler="reset" swapped="yes" />
<style>
<class name="pill"/>
</style>
</object>
</child>
</object>
</property>
</object>
</property>
</object>
</property>
</object>
</property>
</object>
</child>
<child>
<object class="AdwNavigationPage">
<property name="tag">verify</property>
<property name="title" translatable="yes">Identity Verification</property>
<signal name="shown" handler="grab_focus" swapped="yes" />
<property name="child">
<object class="AdwToolbarView">
<child type="top">
<object class="AdwHeaderBar">
<property name="show-title">False</property>
</object>
</child>
<property name="content">
<object class="IdentityVerificationView" id="verification_page"/>
</property>
</object>
</property>
</object>
</child>
<child>
<object class="AdwNavigationPage">
<property name="tag">bootstrap</property>
<property name="title" translatable="yes">Set Up Crypto Identity</property>
<signal name="shown" handler="grab_focus" swapped="yes" />
<property name="child">
<object class="AdwToolbarView">
<child type="top">
<object class="AdwHeaderBar">
<property name="show-title">False</property>
</object>
</child>
<property name="content">
<object class="GtkScrolledWindow">
<property name="hscrollbar-policy">never</property>
<property name="propagate-natural-height">True</property>
<property name="vexpand">True</property>
<property name="child">
<object class="AdwClamp">
<property name="maximum-size">400</property>
<property name="tightening-threshold">300</property>
<property name="child">
<object class="GtkBox">
<property name="orientation">vertical</property>
<property name="spacing">18</property>
<property name="valign">center</property>
<property name="halign">center</property>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">Set Up Crypto Identity</property>
<property name="wrap">True</property>
<property name="wrap-mode">word-char</property>
<property name="justify">center</property>
<style>
<class name="title-1"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">Your crypto identity allows you to verify other Matrix accounts and automatically trust their verified sessions.</property>
<property name="wrap">True</property>
<property name="wrap-mode">word-char</property>
<property name="justify">center</property>
<style>
<class name="body"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">You need to set up a crypto identity, since it has never been created.</property>
<property name="wrap">True</property>
<property name="wrap-mode">word-char</property>
<property name="justify">center</property>
<style>
<class name="body"/>
</style>
</object>
</child>
<child>
<object class="LoadingButton" id="bootstrap_btn">
<property name="content-label" translatable="yes">Set Up</property>
<property name="halign">center</property>
<signal name="clicked" handler="bootstrap_cross_signing" swapped="yes"/>
<style>
<class name="suggested-action"/>
<class name="pill"/>
</style>
</object>
</child>
</object>
</property>
</object>
</property>
</object>
</property>
</object>
</property>
</object>
</child>
<child>
<object class="AdwNavigationPage">
<property name="tag">reset</property>
<property name="title" translatable="yes">Reset Crypto Identity</property>
<signal name="shown" handler="grab_focus" swapped="yes" />
<property name="child">
<object class="AdwToolbarView">
<child type="top">
<object class="AdwHeaderBar">
<property name="show-title">False</property>
</object>
</child>
<property name="content">
<object class="GtkScrolledWindow">
<property name="hscrollbar-policy">never</property>
<property name="propagate-natural-height">True</property>
<property name="vexpand">True</property>
<property name="child">
<object class="AdwClamp">
<property name="maximum-size">400</property>
<property name="tightening-threshold">300</property>
<property name="child">
<object class="GtkBox">
<property name="orientation">vertical</property>
<property name="spacing">18</property>
<property name="valign">center</property>
<property name="halign">center</property>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">Reset Crypto Identity</property>
<property name="wrap">True</property>
<property name="wrap-mode">word-char</property>
<property name="justify">center</property>
<style>
<class name="title-1"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">Your crypto identity allows you to verify other Matrix accounts and automatically trust their verified sessions.</property>
<property name="wrap">True</property>
<property name="wrap-mode">word-char</property>
<property name="justify">center</property>
<style>
<class name="body"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">You should reset your crypto identity if a device that does not belong to you managed to be verified.</property>
<property name="wrap">True</property>
<property name="wrap-mode">word-char</property>
<property name="justify">center</property>
<style>
<class name="body"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">To proceed, you will also need to reset your account recovery key.</property>
<property name="wrap">True</property>
<property name="wrap-mode">word-char</property>
<property name="justify">center</property>
<style>
<class name="body"/>
</style>
</object>
</child>
<child>
<object class="GtkButton" id="reset_btn">
<property name="can-shrink">true</property>
<property name="label" translatable="yes">Reset</property>
<property name="halign">center</property>
<signal name="clicked" handler="reset" swapped="yes" />
<style>
<class name="pill"/>
</style>
</object>
</child>
</object>
</property>
</object>
</property>
</object>
</property>
</object>
</property>
</object>
</child>
</object>
</property>
</template>
</interface>

507
src/components/crypto/recovery_setup_view.blp

@ -0,0 +1,507 @@
using Gtk 4.0;
using Adw 1;
template $CryptoRecoverySetupView: Adw.Bin {
child: Adw.NavigationView navigation {
Adw.NavigationPage {
tag: "recover";
title: _("Recover Account");
shown => $grab_focus() swapped;
child: Adw.ToolbarView {
[top]
Adw.HeaderBar {
show-title: false;
}
content: Gtk.ScrolledWindow {
hscrollbar-policy: never;
propagate-natural-height: true;
vexpand: true;
child: Adw.Clamp {
maximum-size: 400;
tightening-threshold: 300;
child: Gtk.Box {
orientation: vertical;
spacing: 18;
valign: center;
halign: center;
Gtk.Label {
label: _("Recover Account");
wrap: true;
wrap-mode: word_char;
justify: center;
styles [
"title-1",
]
}
Gtk.Label {
label: _("Restore full access to your account.");
wrap: true;
wrap-mode: word_char;
justify: center;
}
Gtk.Label {
label: _("To access the recovery data, we need the recovery passphrase or the recovery key that is usually set up when you create your account.");
wrap: true;
wrap-mode: word_char;
justify: center;
styles [
"body",
]
}
Gtk.ListBox {
styles [
"boxed-list",
]
Adw.PasswordEntryRow recover_entry {
title: _("Recovery Passphrase or Key");
changed => $recover_entry_changed() swapped;
}
}
$LoadingButton recover_btn {
sensitive: false;
can-shrink: true;
label: _("Recover");
halign: center;
clicked => $recover() swapped;
styles [
"suggested-action",
"pill",
]
}
Gtk.Label {
label: _("Lost your recovery passphrase or key?");
wrap: true;
wrap-mode: word_char;
justify: center;
}
Gtk.Button {
can-shrink: true;
halign: center;
label: _("Reset");
action-name: "navigation.push";
action-target: "'reset'";
styles [
"pill",
]
}
};
};
};
};
}
Adw.NavigationPage reset_page {
tag: "reset";
title: _("Reset Account Recovery");
shown => $grab_focus() swapped;
child: Adw.ToolbarView {
[top]
Adw.HeaderBar {
show-title: false;
}
content: Gtk.ScrolledWindow {
hscrollbar-policy: never;
propagate-natural-height: true;
vexpand: true;
child: Adw.Clamp {
maximum-size: 400;
tightening-threshold: 300;
child: Gtk.Box {
orientation: vertical;
spacing: 18;
valign: center;
halign: center;
Gtk.Label {
label: _("Reset Account Recovery");
wrap: true;
wrap-mode: word_char;
justify: center;
styles [
"title-1",
]
}
Gtk.Label {
label: _("Resetting account recovery can allow you to fix or reset part or all of your recovery setup.");
wrap: true;
wrap-mode: word_char;
justify: center;
styles [
"body",
]
}
Gtk.ListBox {
styles [
"boxed-list",
]
$SwitchLoadingRow reset_identity_row {
title: _("Reset Crypto Identity");
}
$SwitchLoadingRow reset_backup_row {
title: _("Reset Room Encryption Keys Backup");
}
}
Gtk.Label {
label: _("If you do not provide a new recovery passphrase, a recovery key will be created.");
wrap: true;
wrap-mode: word_char;
justify: center;
styles [
"body",
]
}
Gtk.Label {
label: _("You should not reuse the password of your Matrix account as a passphrase. Otherwise, if someone manages to get your account password, they will also be able to access all your encrypted conversations and to impersonate you.");
wrap: true;
wrap-mode: word_char;
justify: center;
styles [
"body",
]
}
Gtk.ListBox {
styles [
"boxed-list",
]
Adw.PasswordEntryRow reset_entry {
title: _("Recovery Passphrase (Optional)");
}
}
$LoadingButton reset_btn {
label: _("Reset");
halign: center;
clicked => $reset() swapped;
styles [
"destructive-action",
"pill",
]
}
};
};
};
};
}
Adw.NavigationPage {
tag: "enable";
title: _("Set Up Account Recovery");
shown => $grab_focus() swapped;
child: Adw.ToolbarView {
[top]
Adw.HeaderBar {
show-title: false;
}
content: Gtk.ScrolledWindow {
hscrollbar-policy: never;
propagate-natural-height: true;
vexpand: true;
child: Adw.Clamp {
maximum-size: 400;
tightening-threshold: 300;
child: Gtk.Box {
orientation: vertical;
spacing: 18;
valign: center;
halign: center;
Gtk.Label {
label: _("Set Up Account Recovery");
wrap: true;
wrap-mode: word_char;
justify: center;
styles [
"title-1",
]
}
Gtk.Label {
label: _("Account recovery allows you to recover your crypto identity and to read your encrypted messages even if you lose access to all your sessions.");
wrap: true;
wrap-mode: word_char;
justify: center;
styles [
"body",
]
}
Gtk.Label {
label: _("If you do not provide a recovery passphrase, a recovery key will be created.");
wrap: true;
wrap-mode: word_char;
justify: center;
styles [
"body",
]
}
Gtk.Label {
label: _("You should not reuse the password of your Matrix account as a passphrase. Otherwise, if someone manages to get your account password, they will also be able to access all your encrypted conversations and to impersonate you.");
wrap: true;
wrap-mode: word_char;
justify: center;
styles [
"body",
]
}
Gtk.ListBox {
styles [
"boxed-list",
]
Adw.PasswordEntryRow enable_entry {
title: _("Recovery Passphrase (Optional)");
}
}
$LoadingButton enable_btn {
can-shrink: true;
label: _("Set Up");
halign: "center";
clicked => $enable() swapped;
styles [
"suggested-action",
"pill",
]
}
};
};
};
};
}
Adw.NavigationPage {
tag: "success";
title: _("Account Recovery Set Up Successfully");
can-pop: false;
shown => $grab_focus() swapped;
child: Adw.ToolbarView {
[top]
Adw.HeaderBar {
show-title: false;
}
content: Gtk.ScrolledWindow {
hscrollbar-policy: never;
propagate-natural-height: true;
vexpand: true;
child: Adw.Clamp {
maximum-size: 400;
tightening-threshold: 300;
child: Gtk.Box {
orientation: vertical;
spacing: 18;
valign: center;
halign: center;
Gtk.Label {
label: _("Account Recovery Set Up Successfully");
wrap: true;
wrap-mode: word_char;
justify: center;
styles [
"title-1",
]
}
Gtk.Label success_description {
wrap: true;
wrap-mode: word_char;
justify: center;
}
Gtk.Box success_key_box {
Gtk.Label success_key_label {
wrap: true;
wrap-mode: word;
selectable: true;
xalign: 0.0;
hexpand: true;
margin-start: 12;
margin-end: 12;
margin-top: 12;
margin-bottom: 12;
styles [
"monospace",
]
}
Gtk.Button success_key_copy_btn {
icon-name: "copy-symbolic";
tooltip-text: _("Copy Recovery Key");
valign: center;
margin-end: 12;
clicked => $copy_key() swapped;
styles [
"flat",
]
}
styles [
"card",
]
}
Gtk.Button success_confirm_btn {
can-shrink: true;
label: _("_Done");
use-underline: true;
halign: center;
clicked => $emit_completed() swapped;
styles [
"suggested-action",
"pill",
]
}
};
};
};
};
}
Adw.NavigationPage {
tag: "incomplete";
title: _("Account Recovery Incomplete");
can-pop: false;
shown => $grab_focus() swapped;
child: Adw.ToolbarView {
[top]
Adw.HeaderBar {
show-title: false;
}
content: Gtk.ScrolledWindow {
hscrollbar-policy: never;
propagate-natural-height: true;
vexpand: true;
child: Adw.Clamp {
maximum-size: 400;
tightening-threshold: 300;
child: Gtk.Box {
orientation: vertical;
spacing: 18;
valign: center;
halign: center;
Gtk.Label {
label: _("Account Recovery Incomplete");
wrap: true;
wrap-mode: word_char;
justify: center;
styles [
"title-1",
]
}
Gtk.Label {
label: _("The recovery was successful but the recovery data was incomplete.");
wrap: true;
wrap-mode: word_char;
justify: center;
}
Gtk.Label {
label: _("To fix this, you should reset the recovery from a session that has all the data, and attempt to recover this session again.");
wrap: true;
wrap-mode: word_char;
justify: center;
}
Gtk.Label {
label: _("Note that account recovery can have a different name in other Matrix clients, like “key backup” or “secure backup”.");
wrap: true;
wrap-mode: word_char;
justify: center;
}
Gtk.Button incomplete_confirm_btn {
can-shrink: true;
label: _("_Done");
use-underline: true;
halign: center;
clicked => $emit_completed() swapped;
styles [
"suggested-action",
"pill",
]
}
Gtk.Label {
label: _("Alternatively, you can reset Account Recovery");
wrap: true;
wrap-mode: word_char;
justify: center;
}
Gtk.Button {
can-shrink: true;
label: _("Reset");
halign: center;
clicked => $show_reset() swapped;
styles [
"pill",
]
}
};
};
};
};
}
};
}

557
src/components/crypto/recovery_setup_view.ui

@ -1,557 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="CryptoRecoverySetupView" parent="AdwBin">
<property name="child">
<object class="AdwNavigationView" id="navigation">
<child>
<object class="AdwNavigationPage">
<property name="tag">recover</property>
<property name="title" translatable="yes">Recover Account</property>
<signal name="shown" handler="grab_focus" swapped="yes" />
<property name="child">
<object class="AdwToolbarView">
<child type="top">
<object class="AdwHeaderBar">
<property name="show-title">False</property>
</object>
</child>
<property name="content">
<object class="GtkScrolledWindow">
<property name="hscrollbar-policy">never</property>
<property name="propagate-natural-height">True</property>
<property name="vexpand">True</property>
<property name="child">
<object class="AdwClamp">
<property name="maximum-size">400</property>
<property name="tightening-threshold">300</property>
<property name="child">
<object class="GtkBox">
<property name="orientation">vertical</property>
<property name="spacing">18</property>
<property name="valign">center</property>
<property name="halign">center</property>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">Recover Account</property>
<property name="wrap">True</property>
<property name="wrap-mode">word-char</property>
<property name="justify">center</property>
<style>
<class name="title-1"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">Restore full access to your account.</property>
<property name="wrap">True</property>
<property name="wrap-mode">word-char</property>
<property name="justify">center</property>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">To access the recovery data, we need the recovery passphrase or the recovery key that is usually set up when you create your account.</property>
<property name="wrap">True</property>
<property name="wrap-mode">word-char</property>
<property name="justify">center</property>
<style>
<class name="body"/>
</style>
</object>
</child>
<child>
<object class="GtkListBox">
<style>
<class name="boxed-list" />
</style>
<child>
<object class="AdwPasswordEntryRow" id="recover_entry">
<property name="title" translatable="yes">Recovery Passphrase or Key</property>
<signal name="changed" handler="recover_entry_changed" swapped="yes" />
</object>
</child>
</object>
</child>
<child>
<object class="LoadingButton" id="recover_btn">
<property name="sensitive">False</property>
<property name="can-shrink">True</property>
<property name="label" translatable="yes">Recover</property>
<property name="halign">center</property>
<signal name="clicked" handler="recover" swapped="yes" />
<style>
<class name="suggested-action"/>
<class name="pill"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">Lost your recovery passphrase or key?</property>
<property name="wrap">True</property>
<property name="wrap-mode">word-char</property>
<property name="justify">center</property>
</object>
</child>
<child>
<object class="GtkButton">
<property name="can-shrink">true</property>
<property name="halign">center</property>
<property name="label" translatable="yes">Reset</property>
<property name="action-name">navigation.push</property>
<property name="action-target">'reset'</property>
<style>
<class name="pill"/>
</style>
</object>
</child>
</object>
</property>
</object>
</property>
</object>
</property>
</object>
</property>
</object>
</child>
<child>
<object class="AdwNavigationPage" id="reset_page">
<property name="tag">reset</property>
<property name="title" translatable="yes">Reset Account Recovery</property>
<signal name="shown" handler="grab_focus" swapped="yes" />
<property name="child">
<object class="AdwToolbarView">
<child type="top">
<object class="AdwHeaderBar">
<property name="show-title">False</property>
</object>
</child>
<property name="content">
<object class="GtkScrolledWindow">
<property name="hscrollbar-policy">never</property>
<property name="propagate-natural-height">True</property>
<property name="vexpand">True</property>
<property name="child">
<object class="AdwClamp">
<property name="maximum-size">400</property>
<property name="tightening-threshold">300</property>
<property name="child">
<object class="GtkBox">
<property name="orientation">vertical</property>
<property name="spacing">18</property>
<property name="valign">center</property>
<property name="halign">center</property>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">Reset Account Recovery</property>
<property name="wrap">True</property>
<property name="wrap-mode">word-char</property>
<property name="justify">center</property>
<style>
<class name="title-1"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">Resetting account recovery can allow you to fix or reset part or all of your recovery setup.</property>
<property name="wrap">True</property>
<property name="wrap-mode">word-char</property>
<property name="justify">center</property>
<style>
<class name="body"/>
</style>
</object>
</child>
<child>
<object class="GtkListBox">
<style>
<class name="boxed-list" />
</style>
<child>
<object class="SwitchLoadingRow" id="reset_identity_row">
<property name="title" translatable="yes">Reset Crypto Identity</property>
</object>
</child>
<child>
<object class="SwitchLoadingRow" id="reset_backup_row">
<property name="title" translatable="yes">Reset Room Encryption Keys Backup</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">If you do not provide a new recovery passphrase, a recovery key will be created.</property>
<property name="wrap">True</property>
<property name="wrap-mode">word-char</property>
<property name="justify">center</property>
<style>
<class name="body"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">You should not reuse the password of your Matrix account as a passphrase. Otherwise, if someone manages to get your account password, they will also be able to access all your encrypted conversations and to impersonate you.</property>
<property name="wrap">True</property>
<property name="wrap-mode">word-char</property>
<property name="justify">center</property>
<style>
<class name="body"/>
</style>
</object>
</child>
<child>
<object class="GtkListBox">
<style>
<class name="boxed-list" />
</style>
<child>
<object class="AdwPasswordEntryRow" id="reset_entry">
<property name="title" translatable="yes">Recovery Passphrase (Optional)</property>
</object>
</child>
</object>
</child>
<child>
<object class="LoadingButton" id="reset_btn">
<property name="label" translatable="yes">Reset</property>
<property name="halign">center</property>
<signal name="clicked" handler="reset" swapped="yes"/>
<style>
<class name="destructive-action"/>
<class name="pill"/>
</style>
</object>
</child>
</object>
</property>
</object>
</property>
</object>
</property>
</object>
</property>
</object>
</child>
<child>
<object class="AdwNavigationPage">
<property name="tag">enable</property>
<property name="title" translatable="yes">Set Up Account Recovery</property>
<signal name="shown" handler="grab_focus" swapped="yes" />
<property name="child">
<object class="AdwToolbarView">
<child type="top">
<object class="AdwHeaderBar">
<property name="show-title">False</property>
</object>
</child>
<property name="content">
<object class="GtkScrolledWindow">
<property name="hscrollbar-policy">never</property>
<property name="propagate-natural-height">True</property>
<property name="vexpand">True</property>
<property name="child">
<object class="AdwClamp">
<property name="maximum-size">400</property>
<property name="tightening-threshold">300</property>
<property name="child">
<object class="GtkBox">
<property name="orientation">vertical</property>
<property name="spacing">18</property>
<property name="valign">center</property>
<property name="halign">center</property>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">Set Up Account Recovery</property>
<property name="wrap">True</property>
<property name="wrap-mode">word-char</property>
<property name="justify">center</property>
<style>
<class name="title-1"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">Account recovery allows you to recover your crypto identity and to read your encrypted messages even if you lose access to all your sessions.</property>
<property name="wrap">True</property>
<property name="wrap-mode">word-char</property>
<property name="justify">center</property>
<style>
<class name="body"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">If you do not provide a recovery passphrase, a recovery key will be created.</property>
<property name="wrap">True</property>
<property name="wrap-mode">word-char</property>
<property name="justify">center</property>
<style>
<class name="body"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">You should not reuse the password of your Matrix account as a passphrase. Otherwise, if someone manages to get your account password, they will also be able to access all your encrypted conversations and to impersonate you.</property>
<property name="wrap">True</property>
<property name="wrap-mode">word-char</property>
<property name="justify">center</property>
<style>
<class name="body"/>
</style>
</object>
</child>
<child>
<object class="GtkListBox">
<style>
<class name="boxed-list" />
</style>
<child>
<object class="AdwPasswordEntryRow" id="enable_entry">
<property name="title" translatable="yes">Recovery Passphrase (Optional)</property>
</object>
</child>
</object>
</child>
<child>
<object class="LoadingButton" id="enable_btn">
<property name="can-shrink">True</property>
<property name="label" translatable="yes">Set Up</property>
<property name="halign">center</property>
<signal name="clicked" handler="enable" swapped="yes" />
<style>
<class name="suggested-action"/>
<class name="pill"/>
</style>
</object>
</child>
</object>
</property>
</object>
</property>
</object>
</property>
</object>
</property>
</object>
</child>
<child>
<object class="AdwNavigationPage">
<property name="tag">success</property>
<property name="title" translatable="yes">Account Recovery Set Up Successfully</property>
<property name="can-pop">False</property>
<signal name="shown" handler="grab_focus" swapped="yes" />
<property name="child">
<object class="AdwToolbarView">
<child type="top">
<object class="AdwHeaderBar">
<property name="show-title">False</property>
</object>
</child>
<property name="content">
<object class="GtkScrolledWindow">
<property name="hscrollbar-policy">never</property>
<property name="propagate-natural-height">True</property>
<property name="vexpand">True</property>
<property name="child">
<object class="AdwClamp">
<property name="maximum-size">400</property>
<property name="tightening-threshold">300</property>
<property name="child">
<object class="GtkBox">
<property name="orientation">vertical</property>
<property name="spacing">18</property>
<property name="valign">center</property>
<property name="halign">center</property>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">Account Recovery Set Up Successfully</property>
<property name="wrap">True</property>
<property name="wrap-mode">word-char</property>
<property name="justify">center</property>
<style>
<class name="title-1"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel" id="success_description">
<property name="wrap">True</property>
<property name="wrap-mode">word-char</property>
<property name="justify">center</property>
</object>
</child>
<child>
<object class="GtkBox" id="success_key_box">
<child>
<object class="GtkLabel" id="success_key_label">
<property name="wrap">True</property>
<property name="wrap-mode">word</property>
<property name="selectable">True</property>
<property name="xalign">0.0</property>
<property name="hexpand">True</property>
<property name="margin-start">12</property>
<property name="margin-end">12</property>
<property name="margin-top">12</property>
<property name="margin-bottom">12</property>
<style>
<class name="monospace" />
</style>
</object>
</child>
<child>
<object class="GtkButton" id="success_key_copy_btn">
<property name="icon-name">copy-symbolic</property>
<property name="tooltip-text" translatable="yes">Copy Recovery Key</property>
<property name="valign">center</property>
<property name="margin-end">12</property>
<signal name="clicked" handler="copy_key" swapped="yes" />
<style>
<class name="flat" />
</style>
</object>
</child>
<style>
<class name="card" />
</style>
</object>
</child>
<child>
<object class="GtkButton" id="success_confirm_btn">
<property name="can-shrink">True</property>
<property name="label" translatable="yes">_Done</property>
<property name="use-underline">True</property>
<property name="halign">center</property>
<signal name="clicked" handler="emit_completed" swapped="yes" />
<style>
<class name="suggested-action"/>
<class name="pill"/>
</style>
</object>
</child>
</object>
</property>
</object>
</property>
</object>
</property>
</object>
</property>
</object>
</child>
<child>
<object class="AdwNavigationPage">
<property name="tag">incomplete</property>
<property name="title" translatable="yes">Account Recovery Incomplete</property>
<property name="can-pop">False</property>
<signal name="shown" handler="grab_focus" swapped="yes" />
<property name="child">
<object class="AdwToolbarView">
<child type="top">
<object class="AdwHeaderBar">
<property name="show-title">False</property>
</object>
</child>
<property name="content">
<object class="GtkScrolledWindow">
<property name="hscrollbar-policy">never</property>
<property name="propagate-natural-height">True</property>
<property name="vexpand">True</property>
<property name="child">
<object class="AdwClamp">
<property name="maximum-size">400</property>
<property name="tightening-threshold">300</property>
<property name="child">
<object class="GtkBox">
<property name="orientation">vertical</property>
<property name="spacing">18</property>
<property name="valign">center</property>
<property name="halign">center</property>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">Account Recovery Incomplete</property>
<property name="wrap">True</property>
<property name="wrap-mode">word-char</property>
<property name="justify">center</property>
<style>
<class name="title-1"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">The recovery was successful but the recovery data was incomplete.</property>
<property name="wrap">True</property>
<property name="wrap-mode">word-char</property>
<property name="justify">center</property>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">To fix this, you should reset the recovery from a session that has all the data, and attempt to recover this session again.</property>
<property name="wrap">True</property>
<property name="wrap-mode">word-char</property>
<property name="justify">center</property>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">Note that account recovery can have a different name in other Matrix clients, like “key backup” or “secure backup”.</property>
<property name="wrap">True</property>
<property name="wrap-mode">word-char</property>
<property name="justify">center</property>
</object>
</child>
<child>
<object class="GtkButton" id="incomplete_confirm_btn">
<property name="can-shrink">True</property>
<property name="label" translatable="yes">_Done</property>
<property name="use-underline">True</property>
<property name="halign">center</property>
<signal name="clicked" handler="emit_completed" swapped="yes" />
<style>
<class name="suggested-action"/>
<class name="pill"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">Alternatively, you can reset Account Recovery</property>
<property name="wrap">True</property>
<property name="wrap-mode">word-char</property>
<property name="justify">center</property>
</object>
</child>
<child>
<object class="GtkButton">
<property name="can-shrink">true</property>
<property name="label" translatable="yes">Reset</property>
<property name="halign">center</property>
<signal name="clicked" handler="show_reset" swapped="yes" />
<style>
<class name="pill"/>
</style>
</object>
</child>
</object>
</property>
</object>
</property>
</object>
</property>
</object>
</property>
</object>
</child>
</object>
</property>
</template>
</interface>

120
src/components/dialogs/auth/in_browser_page.blp

@ -0,0 +1,120 @@
using Gtk 4.0;
using Adw 1;
template $AuthDialogInBrowserPage: Adw.Bin {
child: Gtk.WindowHandle {
child: Gtk.Box {
orientation: vertical;
Gtk.ScrolledWindow {
propagate-natural-width: true;
propagate-natural-height: true;
hscrollbar-policy: never;
styles [
"body-scrolled-window",
"undershoot-bottom",
]
child: Gtk.Box {
orientation: vertical;
styles [
"message-area",
"has-heading",
"has-body",
]
Adw.Bin {
styles [
"heading-bin",
]
Gtk.Label {
justify: center;
xalign: 0.5;
label: _("Authentication");
styles [
"title-2",
]
}
}
Gtk.Label {
vexpand: true;
wrap: true;
wrap-mode: word_char;
justify: center;
xalign: 0.5;
label: _("Please authenticate the operation via the browser and, once completed, press confirm");
styles [
"body",
]
}
Gtk.Button launch_url_btn {
margin-top: 6;
can-shrink: true;
halign: center;
clicked => $launch_url() swapped;
styles [
"suggested-action",
"pill",
"large",
"image-text-button",
]
child: Gtk.Box {
halign: center;
Gtk.Label {
label: _("Contin_ue");
use-underline: true;
ellipsize: end;
mnemonic-widget: launch_url_btn;
}
Gtk.Image {
icon-name: "external-link-symbolic";
accessible-role: presentation;
valign: center;
}
};
}
};
}
Adw.WrapBox {
child-spacing: 12;
line-spacing: 12;
justify: fill;
justify-last-line: true;
styles [
"response-area",
]
Gtk.Button {
can-shrink: true;
use-underline: true;
label: _("_Cancel");
action-name: "auth-dialog.close";
}
$LoadingButton confirm_button {
sensitive: false;
can-shrink: true;
content-label: _("C_onfirm");
clicked => $proceed() swapped;
styles [
"suggested-action",
]
}
}
};
};
}

129
src/components/dialogs/auth/in_browser_page.ui

@ -1,129 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="AuthDialogInBrowserPage" parent="AdwBin">
<property name="child">
<object class="GtkWindowHandle">
<property name="child">
<object class="GtkBox">
<property name="orientation">vertical</property>
<child>
<object class="GtkScrolledWindow">
<property name="propagate-natural-width">True</property>
<property name="propagate-natural-height">True</property>
<property name="hscrollbar-policy">never</property>
<style>
<class name="body-scrolled-window"/>
<class name="undershoot-bottom"/>
</style>
<property name="child">
<object class="GtkBox">
<property name="orientation">vertical</property>
<style>
<class name="message-area"/>
<class name="has-heading"/>
<class name="has-body"/>
</style>
<child>
<object class="AdwBin">
<style>
<class name="heading-bin"/>
</style>
<child>
<object class="GtkLabel">
<property name="justify">center</property>
<property name="xalign">0.5</property>
<property name="label" translatable="yes">Authentication</property>
<style>
<class name="title-2"/>
</style>
</object>
</child>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="vexpand">True</property>
<property name="wrap">True</property>
<property name="wrap-mode">word-char</property>
<property name="justify">center</property>
<property name="xalign">0.5</property>
<property name="label" translatable="yes">Please authenticate the operation via the browser and, once completed, press confirm</property>
<style>
<class name="body"/>
</style>
</object>
</child>
<child>
<object class="GtkButton" id="launch_url_btn">
<property name="margin-top">6</property>
<property name="can-shrink">true</property>
<property name="halign">center</property>
<signal name="clicked" handler="launch_url" swapped="yes"/>
<style>
<class name="suggested-action"/>
<class name="pill"/>
<class name="large"/>
<class name="image-text-button"/>
</style>
<property name="child">
<object class="GtkBox">
<property name="halign">center</property>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">Contin_ue</property>
<property name="use-underline">True</property>
<property name="ellipsize">end</property>
<property name="mnemonic-widget">launch_url_btn</property>
</object>
</child>
<child>
<object class="GtkImage">
<property name="icon-name">external-link-symbolic</property>
<property name="accessible-role">presentation</property>
<property name="valign">center</property>
</object>
</child>
</object>
</property>
</object>
</child>
</object>
</property>
</object>
</child>
<child>
<object class="AdwWrapBox">
<property name="child-spacing">12</property>
<property name="line-spacing">12</property>
<property name="justify">fill</property>
<property name="justify-last-line">True</property>
<style>
<class name="response-area"/>
</style>
<child>
<object class="GtkButton">
<property name="can-shrink">True</property>
<property name="use-underline">True</property>
<property name="label" translatable="yes">_Cancel</property>
<property name="action-name">auth-dialog.close</property>
</object>
</child>
<child>
<object class="LoadingButton" id="confirm_button">
<property name="sensitive">False</property>
<property name="can-shrink">True</property>
<property name="content-label" translatable="yes">C_onfirm</property>
<signal name="clicked" handler="proceed" swapped="yes"/>
<style>
<class name="suggested-action"/>
</style>
</object>
</child>
</object>
</child>
</object>
</property>
</object>
</property>
</template>
</interface>

15
src/components/dialogs/auth/mod.blp

@ -0,0 +1,15 @@
using Gtk 4.0;
template $AuthDialog: $ToastableDialog {
title: _("Authentication");
follows-content-size: true;
presentation-mode: floating;
styles [
"alert",
]
child-content: Gtk.Stack stack {
transition-type: slide_left;
};
}

16
src/components/dialogs/auth/mod.ui

@ -1,16 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="AuthDialog" parent="ToastableDialog">
<property name="title" translatable="yes">Authentication</property>
<property name="follows-content-size">True</property>
<property name="presentation-mode">floating</property>
<style>
<class name="alert"/>
</style>
<property name="child-content">
<object class="GtkStack" id="stack">
<property name="transition-type">slide-left</property>
</object>
</property>
</template>
</interface>

98
src/components/dialogs/auth/password_page.blp

@ -0,0 +1,98 @@
using Gtk 4.0;
using Adw 1;
template $AuthDialogPasswordPage: Adw.Bin {
child: Gtk.WindowHandle {
child: Gtk.Box {
orientation: vertical;
Gtk.ScrolledWindow {
propagate-natural-width: true;
propagate-natural-height: true;
hscrollbar-policy: never;
styles [
"body-scrolled-window",
"undershoot-bottom",
]
child: Gtk.Box {
orientation: vertical;
styles [
"message-area",
"has-heading",
"has-body",
]
Adw.Bin {
styles [
"heading-bin",
]
Gtk.Label {
justify: center;
xalign: 0.5;
label: _("Authentication");
styles [
"title-2",
]
}
}
Gtk.Label {
vexpand: true;
wrap: true;
wrap-mode: word_char;
justify: center;
xalign: 0.5;
label: _("Please authenticate the operation with your password");
styles [
"body",
]
}
Gtk.PasswordEntry password {
margin-top: 6;
margin-start: 24;
margin-end: 24;
activates-default: true;
show-peek-icon: true;
changed => $update_confirm() swapped;
}
};
}
Adw.WrapBox {
child-spacing: 12;
line-spacing: 12;
justify: fill;
justify-last-line: true;
styles [
"response-area",
]
Gtk.Button {
can-shrink: true;
use-underline: true;
label: _("_Cancel");
action-name: "auth-dialog.close";
}
$LoadingButton confirm_button {
sensitive: false;
can-shrink: true;
content-label: _("C_onfirm");
clicked => $proceed() swapped;
styles [
"suggested-action",
]
}
}
};
};
}

105
src/components/dialogs/auth/password_page.ui

@ -1,105 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="AuthDialogPasswordPage" parent="AdwBin">
<property name="child">
<object class="GtkWindowHandle">
<property name="child">
<object class="GtkBox">
<property name="orientation">vertical</property>
<child>
<object class="GtkScrolledWindow">
<property name="propagate-natural-width">True</property>
<property name="propagate-natural-height">True</property>
<property name="hscrollbar-policy">never</property>
<style>
<class name="body-scrolled-window"/>
<class name="undershoot-bottom"/>
</style>
<property name="child">
<object class="GtkBox">
<property name="orientation">vertical</property>
<style>
<class name="message-area"/>
<class name="has-heading"/>
<class name="has-body"/>
</style>
<child>
<object class="AdwBin">
<style>
<class name="heading-bin"/>
</style>
<child>
<object class="GtkLabel">
<property name="justify">center</property>
<property name="xalign">0.5</property>
<property name="label" translatable="yes">Authentication</property>
<style>
<class name="title-2"/>
</style>
</object>
</child>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="vexpand">True</property>
<property name="wrap">True</property>
<property name="wrap-mode">word-char</property>
<property name="justify">center</property>
<property name="xalign">0.5</property>
<property name="label" translatable="yes">Please authenticate the operation with your password</property>
<style>
<class name="body"/>
</style>
</object>
</child>
<child>
<object class="GtkPasswordEntry" id="password">
<property name="margin-top">6</property>
<property name="margin-start">24</property>
<property name="margin-end">24</property>
<property name="activates-default">True</property>
<property name="show-peek-icon">True</property>
<signal name="changed" handler="update_confirm" swapped="yes" />
</object>
</child>
</object>
</property>
</object>
</child>
<child>
<object class="AdwWrapBox">
<property name="child-spacing">12</property>
<property name="line-spacing">12</property>
<property name="justify">fill</property>
<property name="justify-last-line">True</property>
<style>
<class name="response-area"/>
</style>
<child>
<object class="GtkButton">
<property name="can-shrink">True</property>
<property name="use-underline">True</property>
<property name="label" translatable="yes">_Cancel</property>
<property name="action-name">auth-dialog.close</property>
</object>
</child>
<child>
<object class="LoadingButton" id="confirm_button">
<property name="sensitive">False</property>
<property name="can-shrink">True</property>
<property name="content-label" translatable="yes">C_onfirm</property>
<signal name="clicked" handler="proceed" swapped="yes"/>
<style>
<class name="suggested-action"/>
</style>
</object>
</child>
</object>
</child>
</object>
</property>
</object>
</property>
</template>
</interface>

197
src/components/dialogs/room_preview.blp

@ -0,0 +1,197 @@
using Gtk 4.0;
using Adw 1;
template $RoomPreviewDialog: $ToastableDialog {
title: _("Join a Room");
content-width: 480;
content-height: 500;
child-content: Adw.ToolbarView {
[top]
Adw.HeaderBar {
show-title: false;
[start]
Gtk.Button go_back_btn {
visible: false;
icon-name: "go-previous-symbolic";
clicked => $go_back() swapped;
tooltip-text: _("Back");
}
}
[top]
Adw.Clamp {
hexpand: true;
child: Gtk.Box {
orientation: vertical;
spacing: 18;
margin-start: 12;
margin-end: 12;
Gtk.Label heading {
wrap: true;
wrap-mode: word_char;
max-width-chars: 20;
justify: center;
xalign: 0.5;
label: _("Join a Room");
styles [
"title-2",
]
}
};
}
content: Gtk.Stack stack {
Gtk.StackPage {
name: "entry";
child: Gtk.ScrolledWindow {
hscrollbar-policy: never;
propagate-natural-height: true;
child: Adw.Clamp {
margin-start: 12;
margin-end: 12;
child: Gtk.Box entry_page {
orientation: vertical;
valign: center;
spacing: 24;
Gtk.Label look_up_instructions {
wrap: true;
wrap-mode: word_char;
justify: center;
use-markup: true;
label: _("Enter a room ID, room alias, or link to look up a room");
styles [
"body",
]
}
Gtk.SearchEntry search_entry {
accessibility {
described-by: [
look_up_instructions,
];
}
search-changed => $update_entry_page() swapped;
activate => $look_up_room() swapped;
}
$LoadingButton look_up_btn {
content-label: _("Look Up");
halign: center;
clicked => $look_up_room() swapped;
styles [
"suggested-action",
"standalone-button",
"pill",
]
}
};
};
};
}
Gtk.StackPage {
name: "loading";
child: Adw.Spinner {};
}
Gtk.StackPage {
name: "details";
child: Gtk.ScrolledWindow {
child: Adw.Clamp {
margin-start: 12;
margin-end: 12;
child: Gtk.Box {
orientation: vertical;
valign: center;
spacing: 12;
$Avatar room_avatar {
size: 128;
accessible-role: presentation;
}
Gtk.Label room_name {
wrap: true;
wrap-mode: word_char;
justify: center;
styles [
"title-3",
]
}
Gtk.Label room_alias {
wrap: true;
wrap-mode: word_char;
justify: center;
styles [
"dimmed",
]
}
Gtk.Label room_topic {
wrap: true;
wrap-mode: word_char;
justify: center;
use-markup: true;
selectable: true;
styles [
"body",
]
}
Gtk.Box room_members_box {
halign: center;
spacing: 6;
Gtk.Image {
icon-name: "users-symbolic";
accessible-role: presentation;
styles [
"dimmed",
]
}
Gtk.Label room_members_count {
styles [
"dimmed",
]
}
}
$LoadingButton view_or_join_btn {
margin-top: 12;
halign: center;
clicked => $view_or_join_room() swapped;
styles [
"suggested-action",
"standalone-button",
"pill",
]
}
};
};
};
}
};
};
}

215
src/components/dialogs/room_preview.ui

@ -1,215 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="RoomPreviewDialog" parent="ToastableDialog">
<property name="title" translatable="yes">Join a Room</property>
<property name="content-width">480</property>
<property name="content-height">500</property>
<property name="child-content">
<object class="AdwToolbarView">
<child type="top">
<object class="AdwHeaderBar">
<property name="show-title">False</property>
<child type="start">
<object class="GtkButton" id="go_back_btn">
<property name="visible">False</property>
<property name="icon-name">go-previous-symbolic</property>
<signal name="clicked" handler="go_back" swapped="yes"/>
<property name="tooltip-text" translatable="yes">Back</property>
</object>
</child>
</object>
</child>
<child type="top">
<object class="AdwClamp">
<property name="hexpand">True</property>
<property name="child">
<object class="GtkBox">
<property name="orientation">vertical</property>
<property name="spacing">18</property>
<property name="margin-start">12</property>
<property name="margin-end">12</property>
<child>
<object class="GtkLabel" id="heading">
<property name="wrap">True</property>
<property name="wrap-mode">word-char</property>
<property name="max-width-chars">20</property>
<property name="justify">center</property>
<property name="xalign">0.5</property>
<property name="label" translatable="yes">Join a Room</property>
<style>
<class name="title-2"/>
</style>
</object>
</child>
</object>
</property>
</object>
</child>
<property name="content">
<object class="GtkStack" id="stack">
<child>
<object class="GtkStackPage">
<property name="name">entry</property>
<property name="child">
<object class="GtkScrolledWindow">
<property name="hscrollbar-policy">never</property>
<property name="propagate-natural-height">True</property>
<property name="child">
<object class="AdwClamp">
<property name="margin-start">12</property>
<property name="margin-end">12</property>
<property name="child">
<object class="GtkBox" id="entry_page">
<property name="orientation">vertical</property>
<property name="valign">center</property>
<property name="spacing">24</property>
<child>
<object class="GtkLabel" id="look_up_instructions">
<property name="wrap">True</property>
<property name="wrap-mode">word-char</property>
<property name="justify">center</property>
<property name="use-markup">True</property>
<property name="label" translatable="yes">Enter a room ID, room alias, or link to look up a room</property>
<style>
<class name="body"/>
</style>
</object>
</child>
<child>
<object class="GtkSearchEntry" id="search_entry">
<accessibility>
<relation name="described-by">look_up_instructions</relation>
</accessibility>
<signal name="search-changed" handler="update_entry_page" swapped="yes"/>
<signal name="activate" handler="look_up_room" swapped="yes"/>
</object>
</child>
<child>
<object class="LoadingButton" id="look_up_btn">
<!-- Translators: This is a verb, as in 'Look up Room'. -->
<property name="content-label" translatable="yes">Look Up</property>
<property name="halign">center</property>
<signal name="clicked" handler="look_up_room" swapped="yes"/>
<style>
<class name="suggested-action"/>
<class name="standalone-button"/>
<class name="pill"/>
</style>
</object>
</child>
</object>
</property>
</object>
</property>
</object>
</property>
</object>
</child>
<child>
<object class="GtkStackPage">
<property name="name">loading</property>
<property name="child">
<object class="AdwSpinner" />
</property>
</object>
</child>
<child>
<object class="GtkStackPage">
<property name="name">details</property>
<property name="child">
<object class="GtkScrolledWindow">
<property name="child">
<object class="AdwClamp">
<property name="margin-start">12</property>
<property name="margin-end">12</property>
<property name="child">
<object class="GtkBox">
<property name="orientation">vertical</property>
<property name="valign">center</property>
<property name="spacing">12</property>
<child>
<object class="Avatar" id="room_avatar">
<property name="size">128</property>
<property name="accessible-role">presentation</property>
</object>
</child>
<child>
<object class="GtkLabel" id="room_name">
<property name="wrap">true</property>
<property name="wrap-mode">word-char</property>
<property name="justify">center</property>
<style>
<class name="title-3"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel" id="room_alias">
<property name="wrap">true</property>
<property name="wrap-mode">word-char</property>
<property name="justify">center</property>
<style>
<class name="dimmed"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel" id="room_topic">
<property name="wrap">true</property>
<property name="wrap-mode">word-char</property>
<property name="justify">center</property>
<property name="use-markup">True</property>
<property name="selectable">True</property>
<style>
<class name="body"/>
</style>
</object>
</child>
<child>
<object class="GtkBox" id="room_members_box">
<property name="halign">center</property>
<property name="spacing">6</property>
<child>
<object class="GtkImage">
<property name="icon-name">users-symbolic</property>
<property name="accessible-role">presentation</property>
<style>
<class name="dimmed"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel" id="room_members_count">
<style>
<class name="dimmed"/>
</style>
</object>
</child>
</object>
</child>
<child>
<object class="LoadingButton" id="view_or_join_btn">
<property name="margin-top">12</property>
<property name="halign">center</property>
<signal name="clicked" handler="view_or_join_room" swapped="yes"/>
<style>
<class name="suggested-action"/>
<class name="standalone-button"/>
<class name="pill"/>
</style>
</object>
</child>
</object>
</property>
</object>
</property>
</object>
</property>
</object>
</child>
</object>
</property>
</object>
</property>
</template>
</interface>

6
src/components/dialogs/toastable.blp

@ -0,0 +1,6 @@
using Gtk 4.0;
using Adw 1;
template $ToastableDialog: Adw.Dialog {
child: Adw.ToastOverlay toast_overlay {};
}

8
src/components/dialogs/toastable.ui

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="ToastableDialog" parent="AdwDialog">
<property name="child">
<object class="AdwToastOverlay" id="toast_overlay"/>
</property>
</template>
</interface>

21
src/components/dialogs/user_profile.blp

@ -0,0 +1,21 @@
using Gtk 4.0;
using Adw 1;
template $UserProfileDialog: $ToastableDialog {
title: _("User Profile");
content-width: 500;
child-content: Gtk.Stack stack {
Gtk.StackPage {
name: "loading";
child: Adw.Spinner {};
}
Gtk.StackPage {
name: "details";
child: $UserPage user_page {};
}
};
}

27
src/components/dialogs/user_profile.ui

@ -1,27 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="UserProfileDialog" parent="ToastableDialog">
<property name="title" translatable="yes">User Profile</property>
<property name="content-width">500</property>
<property name="child-content">
<object class="GtkStack" id="stack">
<child>
<object class="GtkStackPage">
<property name="name">loading</property>
<property name="child">
<object class="AdwSpinner" />
</property>
</object>
</child>
<child>
<object class="GtkStackPage">
<property name="name">details</property>
<property name="child">
<object class="UserPage" id="user_page"/>
</property>
</object>
</child>
</object>
</property>
</template>
</interface>

23
src/components/loading/bin.blp

@ -0,0 +1,23 @@
using Gtk 4.0;
using Adw 1;
template $LoadingBin: Gtk.Widget {
Gtk.Stack stack {
transition-type: crossfade;
Gtk.StackPage {
name: "child";
child: Adw.Bin child_bin {};
}
Gtk.StackPage {
name: "loading";
child: Adw.Spinner {
valign: center;
halign: center;
};
}
}
}

29
src/components/loading/bin.ui

@ -1,29 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="LoadingBin" parent="GtkWidget">
<child>
<object class="GtkStack" id="stack">
<property name="transition-type">crossfade</property>
<child>
<object class="GtkStackPage">
<property name="name">child</property>
<property name="child">
<object class="AdwBin" id="child_bin"/>
</property>
</object>
</child>
<child>
<object class="GtkStackPage">
<property name="name">loading</property>
<property name="child">
<object class="AdwSpinner">
<property name="valign">center</property>
<property name="halign">center</property>
</object>
</property>
</object>
</child>
</object>
</child>
</template>
</interface>

8
src/components/media/audio_player.blp

@ -0,0 +1,8 @@
using Gtk 4.0;
using Adw 1;
template $AudioPlayer: Adw.Bin {
Gtk.MediaControls {
media-stream: bind template.media-file;
}
}

10
src/components/media/audio_player.ui

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="AudioPlayer" parent="AdwBin">
<child>
<object class="GtkMediaControls">
<property name="media-stream" bind-source="AudioPlayer" bind-property="media-file" bind-flags="sync-create"/>
</object>
</child>
</template>
</interface>

27
src/components/media/content_viewer.blp

@ -0,0 +1,27 @@
using Gtk 4.0;
using Adw 1;
template $MediaContentViewer: $ContextMenuBin {
child: Gtk.Stack stack {
Gtk.StackPage {
name: "loading";
child: Adw.Spinner {};
}
Gtk.StackPage {
name: "viewer";
child: Adw.Bin viewer {
map => $update_animated_paintable_state() swapped;
unmap => $update_animated_paintable_state() swapped;
};
}
Gtk.StackPage {
name: "fallback";
child: Adw.StatusPage fallback {};
}
};
}

36
src/components/media/content_viewer.ui

@ -1,36 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="MediaContentViewer" parent="ContextMenuBin">
<property name="child">
<object class="GtkStack" id="stack">
<child>
<object class="GtkStackPage">
<property name="name">loading</property>
<property name="child">
<object class="AdwSpinner"/>
</property>
</object>
</child>
<child>
<object class="GtkStackPage">
<property name="name">viewer</property>
<property name="child">
<object class="AdwBin" id="viewer">
<signal name="map" handler="update_animated_paintable_state" swapped="yes"/>
<signal name="unmap" handler="update_animated_paintable_state" swapped="yes"/>
</object>
</property>
</object>
</child>
<child>
<object class="GtkStackPage">
<property name="name">fallback</property>
<property name="child">
<object class="AdwStatusPage" id="fallback"/>
</property>
</object>
</child>
</object>
</property>
</template>
</interface>

21
src/components/media/location_viewer.blp

@ -0,0 +1,21 @@
using Gtk 4.0;
using Adw 1;
Gtk.Image marker_img {
icon-name: "map-marker-symbolic";
pixel-size: 32;
styles [
"map-marker",
]
}
template $LocationViewer: Adw.Bin {
child: $ShumateSimpleMap map {
overflow: hidden;
styles [
"map",
]
};
}

20
src/components/media/location_viewer.ui

@ -1,20 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<object class="GtkImage" id="marker_img">
<property name="icon-name">map-marker-symbolic</property>
<property name="pixel-size">32</property>
<style>
<class name="map-marker" />
</style>
</object>
<template class="LocationViewer" parent="AdwBin">
<property name="child">
<object class="ShumateSimpleMap" id="map">
<property name="overflow">hidden</property>
<style>
<class name="map"/>
</style>
</object>
</property>
</template>
</interface>

32
src/components/media/video_player.blp

@ -0,0 +1,32 @@
using Gtk 4.0;
using Adw 1;
$GstPlay player {
video-renderer: $VideoPlayerRenderer video_renderer {};
}
template $VideoPlayer: Adw.Bin {
Gtk.Overlay {
Gtk.Picture video {
paintable: bind video_renderer.paintable;
}
[overlay]
Gtk.Label timestamp {
styles [
"osd",
"timestamp",
]
visible: false;
halign: start;
valign: start;
margin-start: 5;
margin-top: 5;
layout {
measure: true;
}
}
}
}

35
src/components/media/video_player.ui

@ -1,35 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<object class="GstPlay" id="player">
<property name="video-renderer">
<object class="VideoPlayerRenderer" id="video_renderer"/>
</property>
</object>
<template class="VideoPlayer" parent="AdwBin">
<child>
<object class="GtkOverlay">
<child>
<object class="GtkPicture" id="video">
<property name="paintable" bind-source="video_renderer" bind-property="paintable" bind-flags="sync-create"/>
</object>
</child>
<child type="overlay">
<object class="GtkLabel" id="timestamp">
<style>
<class name="osd"/>
<class name="timestamp"/>
</style>
<property name="visible">false</property>
<property name="halign">start</property>
<property name="valign">start</property>
<property name="margin-start">5</property>
<property name="margin-top">5</property>
<layout>
<property name="measure">true</property>
</layout>
</object>
</child>
</object>
</child>
</template>
</interface>

18
src/components/pill/mod.blp

@ -0,0 +1,18 @@
using Gtk 4.0;
template $Pill: Gtk.Widget {
valign: center;
Gtk.Box content {
spacing: 6;
margin-end: 6;
$Avatar avatar {
size: 24;
accessible-role: presentation;
data: bind template.source as <$PillSource>.avatar-data;
}
Gtk.Label display_name {}
}
}

26
src/components/pill/mod.ui

@ -1,26 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="Pill" parent="GtkWidget">
<property name="valign">center</property>
<child>
<object class="GtkBox" id="content">
<property name="spacing">6</property>
<property name="margin-end">6</property>
<child>
<object class="Avatar" id="avatar">
<property name="size">24</property>
<property name="accessible-role">presentation</property>
<binding name="data">
<lookup name="avatar-data">
<lookup name="source">Pill</lookup>
</lookup>
</binding>
</object>
</child>
<child>
<object class="GtkLabel" id="display_name"/>
</child>
</object>
</child>
</template>
</interface>

38
src/components/pill/search_entry.blp

@ -0,0 +1,38 @@
using Gtk 4.0;
using Adw 1;
template $PillSearchEntry: Adw.Bin {
accessible-role: search;
child: $CustomEntry {
Gtk.Box {
spacing: 6;
Gtk.Image {
icon-name: "system-search-symbolic";
accessible-role: presentation;
}
Gtk.ScrolledWindow {
vexpand: true;
hexpand: true;
vscrollbar-policy: external;
max-content-height: 200;
propagate-natural-height: true;
Gtk.TextView text_view {
height-request: 38;
hexpand: true;
justification: left;
wrap-mode: word_char;
accepts-tab: false;
pixels-above-lines: 6;
pixels-below-lines: 11;
pixels-inside-wrap: 11;
buffer: Gtk.TextBuffer text_buffer {};
}
}
}
};
}

45
src/components/pill/search_entry.ui

@ -1,45 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="PillSearchEntry" parent="AdwBin">
<property name="accessible-role">search</property>
<property name="child">
<object class="CustomEntry">
<child>
<object class="GtkBox">
<property name="spacing">6</property>
<child>
<object class="GtkImage">
<property name="icon-name">system-search-symbolic</property>
<property name="accessible-role">presentation</property>
</object>
</child>
<child>
<object class="GtkScrolledWindow">
<property name="vexpand">True</property>
<property name="hexpand">True</property>
<property name="vscrollbar-policy">external</property>
<property name="max-content-height">200</property>
<property name="propagate-natural-height">True</property>
<child>
<object class="GtkTextView" id="text_view">
<property name="height-request">38</property>
<property name="hexpand">True</property>
<property name="justification">left</property>
<property name="wrap-mode">word-char</property>
<property name="accepts-tab">False</property>
<property name="pixels-above-lines">6</property>
<property name="pixels-below-lines">11</property>
<property name="pixels-inside-wrap">11</property>
<property name="buffer">
<object class="GtkTextBuffer" id="text_buffer"/>
</property>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</property>
</template>
</interface>

37
src/components/pill/source_row.blp

@ -0,0 +1,37 @@
using Gtk 4.0;
template $PillSourceRow: ListBoxRow {
Gtk.Box {
spacing: 10;
$Avatar avatar {
size: 36;
accessible-role: presentation;
data: bind template.source as <$PillSource>.avatar-data;
}
Gtk.Box {
spacing: 3;
orientation: vertical;
Gtk.Label display_name {
xalign: 0.0;
hexpand: true;
ellipsize: end;
label: bind template.source as <$PillSource>.display-name;
}
Gtk.Label id {
xalign: 0.0;
hexpand: true;
ellipsize: end;
label: bind template.source as <$PillSource>.identifier;
styles [
"dimmed",
"caption",
]
}
}
}
}

55
src/components/pill/source_row.ui

@ -1,55 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="PillSourceRow" parent="GtkListBoxRow">
<child>
<object class="GtkBox">
<property name="spacing">10</property>
<child>
<object class="Avatar" id="avatar">
<property name="size">36</property>
<property name="accessible-role">presentation</property>
<binding name="data">
<lookup name="avatar-data">
<lookup name="source">PillSourceRow</lookup>
</lookup>
</binding>
</object>
</child>
<child>
<object class="GtkBox">
<property name="spacing">3</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkLabel" id="display_name">
<property name="xalign">0.0</property>
<property name="hexpand">True</property>
<property name="ellipsize">end</property>
<binding name="label">
<lookup name="display-name">
<lookup name="source">PillSourceRow</lookup>
</lookup>
</binding>
</object>
</child>
<child>
<object class="GtkLabel" id="id">
<property name="xalign">0.0</property>
<property name="hexpand">True</property>
<property name="ellipsize">end</property>
<binding name="label">
<lookup name="identifier">
<lookup name="source">PillSourceRow</lookup>
</lookup>
</binding>
<style>
<class name="dimmed"/>
<class name="caption"/>
</style>
</object>
</child>
</object>
</child>
</object>
</child>
</template>
</interface>

44
src/components/power_level_selection/combo_box.blp

@ -0,0 +1,44 @@
using Gtk 4.0;
template $PowerLevelSelectionComboBox: Gtk.ToggleButton {
accessible-role: combo_box;
width-request: 170;
active: bind popover.visible;
notify::active => $active_changed() swapped;
styles [
"combo",
]
child: Gtk.Box {
Gtk.Box selected_box {
accessible-role: group;
spacing: 12;
margin-end: 6;
hexpand: true;
Gtk.Label selected_level_label {}
$RoleBadge selected_role_badge {
valign: center;
}
}
Gtk.Image {
icon-name: "pan-down-symbolic";
accessible-role: presentation;
halign: end;
valign: center;
styles [
"dropdown-arrow",
]
}
$PowerLevelSelectionPopover popover {
has-arrow: false;
permissions: bind template.permissions;
selected-power-level: bind template.selected-power-level bidirectional;
}
};
}

50
src/components/power_level_selection/combo_box.ui

@ -1,50 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="PowerLevelSelectionComboBox" parent="GtkToggleButton">
<property name="accessible-role">combo-box</property>
<property name="width-request">170</property>
<property name="active" bind-source="popover" bind-property="visible" bind-flags="sync-create" />
<signal name="notify::active" handler="active_changed" swapped="yes" />
<style>
<class name="combo" />
</style>
<property name="child">
<object class="GtkBox">
<child>
<object class="GtkBox" id="selected_box">
<property name="accessible-role">group</property>
<property name="spacing">12</property>
<property name="margin-end">6</property>
<property name="hexpand">True</property>
<child>
<object class="GtkLabel" id="selected_level_label" />
</child>
<child>
<object class="RoleBadge" id="selected_role_badge">
<property name="valign">center</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkImage">
<property name="icon-name">pan-down-symbolic</property>
<property name="accessible-role">presentation</property>
<property name="halign">end</property>
<property name="valign">center</property>
<style>
<class name="dropdown-arrow" />
</style>
</object>
</child>
<child>
<object class="PowerLevelSelectionPopover" id="popover">
<property name="has-arrow">false</property>
<property name="permissions" bind-source="PowerLevelSelectionComboBox" bind-property="permissions" bind-flags="sync-create"/>
<property name="selected-power-level" bind-source="PowerLevelSelectionComboBox" bind-property="selected-power-level" bind-flags="sync-create | bidirectional"/>
</object>
</child>
</object>
</property>
</template>
</interface>

154
src/components/power_level_selection/popover.blp

@ -0,0 +1,154 @@
using Gtk 4.0;
using Adw 1;
template $PowerLevelSelectionPopover: Gtk.Popover {
styles [
"menu",
"role-selection-popover",
]
child: Gtk.ScrolledWindow {
hscrollbar-policy: never;
max-content-height: 400;
propagate-natural-width: true;
propagate-natural-height: true;
child: Gtk.Box {
orientation: vertical;
Gtk.ListBox {
row-activated => $row_activated() swapped;
Gtk.ListBoxRow admin_row {
selectable: false;
child: Gtk.Box {
accessible-role: group;
spacing: 6;
Gtk.Label {
label: "100";
width-chars: 3;
xalign: 1.0;
}
$RoleBadge {
role: administrator;
valign: center;
}
Image admin_selected {
icon-name: "object-select-symbolic";
accessible-role: presentation;
}
};
}
Gtk.ListBoxRow mod_row {
selectable: false;
child: Gtk.Box {
accessible-role: group;
spacing: 6;
Gtk.Label {
label: "50";
width-chars: 3;
xalign: 1.0;
}
$RoleBadge {
role: moderator;
valign: center;
}
Gtk.Image mod_selected {
icon-name: "object-select-symbolic";
accessible-role: presentation;
}
};
}
Gtk.ListBoxRow default_row {
selectable: false;
child: Gtk.Box {
accessible-role: group;
spacing: 6;
Gtk.Label default_pl_label {
width-chars: 3;
xalign: 1.0;
}
$RoleBadge {
role: default;
valign: center;
}
Gtk.Image default_selected {
icon-name: "object-select-symbolic";
accessible-role: presentation;
}
};
}
Gtk.ListBoxRow muted_row {
selectable: false;
child: Gtk.Box {
accessible-role: group;
spacing: 6;
Gtk.Label muted_pl_label {
width-chars: 3;
xalign: 1.0;
}
$RoleBadge {
role: muted;
valign: center;
}
Gtk.Image muted_selected {
icon-name: "object-select-symbolic";
accessible-role: presentation;
}
};
}
}
Gtk.Separator {}
Gtk.ListBox {
Adw.SpinRow custom_row {
selectable: false;
title: _("Custom");
numeric: true;
adjustment: Gtk.Adjustment custom_adjustment {
lower: -9007199254740991;
upper: 100;
page-increment: 10;
step-increment: 1;
notify::value => $custom_value_changed() swapped;
};
Gtk.Button custom_confirm {
icon-name: "checkmark-symbolic";
tooltip-text: _("Confirm Custom Role");
clicked => $custom_value_confirmed() swapped;
valign: center;
sensitive: false;
styles [
"suggested-action",
"circular",
"spin-confirm",
]
}
}
}
};
};
}

184
src/components/power_level_selection/popover.ui

@ -1,184 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="PowerLevelSelectionPopover" parent="GtkPopover">
<style>
<class name="menu" />
<class name="role-selection-popover" />
</style>
<property name="child">
<object class="GtkScrolledWindow">
<property name="hscrollbar_policy">never</property>
<property name="max-content-height">400</property>
<property name="propagate-natural-width">True</property>
<property name="propagate-natural-height">True</property>
<property name="child">
<object class="GtkBox">
<property name="orientation">vertical</property>
<child>
<object class="GtkListBox">
<signal name="row-activated" handler="row_activated" swapped="true" />
<child>
<object class="GtkListBoxRow" id="admin_row">
<property name="selectable">False</property>
<property name="child">
<object class="GtkBox">
<property name="accessible-role">group</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel">
<property name="label">100</property>
<property name="width-chars">3</property>
<property name="xalign">1.0</property>
</object>
</child>
<child>
<object class="RoleBadge">
<property name="role">administrator</property>
<property name="valign">center</property>
</object>
</child>
<child>
<object class="GtkImage" id="admin_selected">
<property name="icon-name">object-select-symbolic</property>
<property name="accessible-role">presentation</property>
</object>
</child>
</object>
</property>
</object>
</child>
<child>
<object class="GtkListBoxRow" id="mod_row">
<property name="selectable">False</property>
<property name="child">
<object class="GtkBox">
<property name="accessible-role">group</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel">
<property name="label">50</property>
<property name="width-chars">3</property>
<property name="xalign">1.0</property>
</object>
</child>
<child>
<object class="RoleBadge">
<property name="role">moderator</property>
<property name="valign">center</property>
</object>
</child>
<child>
<object class="GtkImage" id="mod_selected">
<property name="icon-name">object-select-symbolic</property>
<property name="accessible-role">presentation</property>
</object>
</child>
</object>
</property>
</object>
</child>
<child>
<object class="GtkListBoxRow" id="default_row">
<property name="selectable">False</property>
<property name="child">
<object class="GtkBox">
<property name="accessible-role">group</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel" id="default_pl_label">
<property name="width-chars">3</property>
<property name="xalign">1.0</property>
</object>
</child>
<child>
<object class="RoleBadge">
<property name="role">default</property>
<property name="valign">center</property>
</object>
</child>
<child>
<object class="GtkImage" id="default_selected">
<property name="icon-name">object-select-symbolic</property>
<property name="accessible-role">presentation</property>
</object>
</child>
</object>
</property>
</object>
</child>
<child>
<object class="GtkListBoxRow" id="muted_row">
<property name="selectable">False</property>
<property name="child">
<object class="GtkBox">
<property name="accessible-role">group</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel" id="muted_pl_label">
<property name="width-chars">3</property>
<property name="xalign">1.0</property>
</object>
</child>
<child>
<object class="RoleBadge">
<property name="role">muted</property>
<property name="valign">center</property>
</object>
</child>
<child>
<object class="GtkImage" id="muted_selected">
<property name="icon-name">object-select-symbolic</property>
<property name="accessible-role">presentation</property>
</object>
</child>
</object>
</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkSeparator" />
</child>
<child>
<object class="GtkListBox">
<child>
<object class="AdwSpinRow" id="custom_row">
<property name="selectable">False</property>
<!-- Translators: As in 'Custom role'. -->
<property name="title" translatable="yes">Custom</property>
<property name="numeric">True</property>
<property name="adjustment">
<object class="GtkAdjustment" id="custom_adjustment">
<!-- js_int::MIN_SAFE_INT -->
<property name="lower">-9007199254740991</property>
<property name="upper">100</property>
<property name="page-increment">10</property>
<property name="step-increment">1</property>
<signal name="notify::value" handler="custom_value_changed" swapped="yes" />
</object>
</property>
<child>
<object class="GtkButton" id="custom_confirm">
<property name="icon-name">checkmark-symbolic</property>
<property name="tooltip-text" translatable="yes">Confirm Custom Role</property>
<signal name="clicked" handler="custom_value_confirmed" swapped="yes" />
<property name="valign">center</property>
<property name="sensitive">False</property>
<style>
<class name="suggested-action" />
<class name="circular" />
<class name="spin-confirm" />
</style>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</property>
</object>
</property>
</template>
</interface>

125
src/components/power_level_selection/row.blp

@ -0,0 +1,125 @@
using Gtk 4.0;
using Adw 1;
template $PowerLevelSelectionRow: Adw.PreferencesRow {
selectable: false;
activatable: bind template.read-only inverted;
accessible-role: combo_box;
action-name: "power-level-selection-row.popup";
accessibility {
labelled-by: [
title,
];
}
styles [
"combo",
]
child: Gtk.Box header {
valign: center;
hexpand: false;
styles [
"header",
]
Gtk.Box title_box {
orientation: vertical;
valign: center;
hexpand: true;
styles [
"title",
]
Gtk.Label title {
ellipsize: none;
label: bind template.title;
lines: 0;
mnemonic-widget: template;
wrap: true;
wrap-mode: word_char;
xalign: 0;
styles [
"title",
]
}
Adw.Bin subtitle_bin {
visible: bind template.use-subtitle;
}
}
Gtk.Box suffixes {
styles [
"suffixes",
]
Adw.Bin combo_selection_bin {
visible: bind template.use-subtitle inverted;
}
Gtk.Box arrow_box {
visible: bind template.read-only inverted;
valign: center;
$LoadingBin loading_bin {
child: Image {
icon-name: "pan-down-symbolic";
accessible-role: presentation;
styles [
"dropdown-arrow",
]
};
}
$PowerLevelSelectionPopover popover {
notify::visible => $popover_visible() swapped;
notify::selected-power-level => $power_level_changed() swapped;
permissions: bind template.permissions;
}
}
}
};
}
Gtk.Box selected_box {
accessible-role: group;
spacing: 12;
margin-end: 6;
Gtk.Label selected_level_label {}
Gtk.MenuButton creator_info_button {
icon-name: "info-symbolic";
tooltip-text: _("More Information");
valign: center;
styles [
"flat",
]
popover: Gtk.Popover {
child: Gtk.Label {
halign: center;
margin-bottom: 6;
margin-top: 6;
margin-start: 6;
margin-end: 6;
max-width-chars: 50;
valign: center;
wrap: true;
wrap-mode: word_char;
label: _("Creator is an immutable role that can be attributed to several users when creating a room. Creators always have a higher power level than any other room members, except other creators, and have the permission to do anything in the room. The only way to demote a creator is to replace the current room with another one with a different creator, by upgrading the room for example.");
};
};
}
$RoleBadge selected_role_badge {
valign: center;
}
}

132
src/components/power_level_selection/row.ui

@ -1,132 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="PowerLevelSelectionRow" parent="AdwPreferencesRow">
<property name="selectable">False</property>
<property name="activatable" bind-source="PowerLevelSelectionRow" bind-property="read-only" bind-flags="sync-create | invert-boolean" />
<property name="accessible-role">combo-box</property>
<property name="action-name">power-level-selection-row.popup</property>
<accessibility>
<relation name="labelled-by">title</relation>
</accessibility>
<style>
<class name="combo" />
</style>
<property name="child">
<object class="GtkBox" id="header">
<property name="valign">center</property>
<property name="hexpand">False</property>
<style>
<class name="header"/>
</style>
<child>
<object class="GtkBox" id="title_box">
<property name="orientation">vertical</property>
<property name="valign">center</property>
<property name="hexpand">True</property>
<style>
<class name="title"/>
</style>
<child>
<object class="GtkLabel" id="title">
<property name="ellipsize">none</property>
<property name="label" bind-source="PowerLevelSelectionRow" bind-property="title" bind-flags="sync-create"/>
<property name="lines">0</property>
<property name="mnemonic-widget">PowerLevelSelectionRow</property>
<property name="wrap">True</property>
<property name="wrap-mode">word-char</property>
<property name="xalign">0</property>
<style>
<class name="title"/>
</style>
</object>
</child>
<child>
<object class="AdwBin" id="subtitle_bin">
<property name="visible" bind-source="PowerLevelSelectionRow" bind-property="use-subtitle" bind-flags="sync-create" />
</object>
</child>
</object>
</child>
<child>
<object class="GtkBox" id="suffixes">
<style>
<class name="suffixes"/>
</style>
<child>
<object class="AdwBin" id="combo_selection_bin">
<property name="visible" bind-source="PowerLevelSelectionRow" bind-property="use-subtitle" bind-flags="sync-create | invert-boolean" />
</object>
</child>
<child>
<object class="GtkBox" id="arrow_box">
<property name="visible" bind-source="PowerLevelSelectionRow" bind-property="read-only" bind-flags="sync-create | invert-boolean" />
<property name="valign">center</property>
<child>
<object class="LoadingBin" id="loading_bin">
<property name="child">
<object class="GtkImage">
<property name="icon_name">pan-down-symbolic</property>
<property name="accessible-role">presentation</property>
<style>
<class name="dropdown-arrow" />
</style>
</object>
</property>
</object>
</child>
<child>
<object class="PowerLevelSelectionPopover" id="popover">
<signal name="notify::visible" handler="popover_visible" swapped="true" />
<signal name="notify::selected-power-level" handler="power_level_changed" swapped="true" />
<property name="permissions" bind-source="PowerLevelSelectionRow" bind-property="permissions" bind-flags="sync-create"/>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</property>
</template>
<object class="GtkBox" id="selected_box">
<property name="accessible-role">group</property>
<property name="spacing">12</property>
<property name="margin-end">6</property>
<child>
<object class="GtkLabel" id="selected_level_label" />
</child>
<child>
<object class="GtkMenuButton" id="creator_info_button">
<property name="icon-name">info-symbolic</property>
<property name="tooltip-text" translatable="yes">More Information</property>
<property name="valign">center</property>
<style>
<class name="flat"/>
</style>
<property name="popover">
<object class="GtkPopover">
<property name="child">
<object class="GtkLabel">
<property name="halign">center</property>
<property name="margin-bottom">6</property>
<property name="margin-top">6</property>
<property name="margin-start">6</property>
<property name="margin-end">6</property>
<property name="max-width-chars">50</property>
<property name="valign">center</property>
<property name="wrap">True</property>
<property name="wrap-mode">word-char</property>
<property name="label" translatable="yes">Creator is an immutable role that can be attributed to several users when creating a room. Creators always have a higher power level than any other room members, except other creators, and have the permission to do anything in the room. The only way to demote a creator is to replace the current room with another one with a different creator, by upgrading the room for example.</property>
</object>
</property>
</object>
</property>
</object>
</child>
<child>
<object class="RoleBadge" id="selected_role_badge">
<property name="valign">center</property>
</object>
</child>
</object>
</interface>

24
src/components/rows/button_count_row.blp

@ -0,0 +1,24 @@
using Gtk 4.0;
using Adw 1;
template $ButtonCountRow: Adw.ActionRow {
activatable: true;
selectable: false;
accessible-role: button;
[suffix]
Gtk.Label count_label {
valign: center;
halign: center;
accessible-role: presentation;
}
[suffix]
Gtk.Image {
visible: bind template.activatable;
valign: center;
halign: center;
icon-name: "go-next-symbolic";
accessible-role: presentation;
}
}

24
src/components/rows/button_count_row.ui

@ -1,24 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="ButtonCountRow" parent="AdwActionRow">
<property name="activatable">True</property>
<property name="selectable">False</property>
<property name="accessible-role">button</property>
<child type="suffix">
<object class="GtkLabel" id="count_label">
<property name="valign">center</property>
<property name="halign">center</property>
<property name="accessible-role">presentation</property>
</object>
</child>
<child type="suffix">
<object class="GtkImage">
<property name="visible" bind-source="ButtonCountRow" bind-property="activatable" bind-flags="sync-create" />
<property name="valign">center</property>
<property name="halign">center</property>
<property name="icon-name">go-next-symbolic</property>
<property name="accessible-role">presentation</property>
</object>
</child>
</template>
</interface>

14
src/components/rows/check_loading_row.blp

@ -0,0 +1,14 @@
using Gtk 4.0;
using Adw 1;
template $CheckLoadingRow: Adw.ActionRow {
selectable: false;
activatable-widget: check;
[prefix]
$LoadingBin bin {
child: Gtk.CheckButton check {
valign: center;
};
}
}

16
src/components/rows/check_loading_row.ui

@ -1,16 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="CheckLoadingRow" parent="AdwActionRow">
<property name="selectable">False</property>
<property name="activatable-widget">check</property>
<child type="prefix">
<object class="LoadingBin" id="bin">
<property name="child">
<object class="GtkCheckButton" id="check">
<property name="valign">center</property>
</object>
</property>
</object>
</child>
</template>
</interface>

47
src/components/rows/combo_loading_row.blp

@ -0,0 +1,47 @@
using Gtk 4.0;
using Adw 1;
template $ComboLoadingRow: Adw.ActionRow {
selectable: false;
activatable: bind template.read-only inverted;
styles [
"combo",
"property",
]
Gtk.Box arrow_box {
valign: center;
$LoadingBin loading_bin {
child: Gtk.Image {
visible: bind template.read-only inverted;
icon-name: "pan-down-symbolic";
accessible-role: presentation;
styles [
"dropdown-arrow",
]
};
}
Gtk.Popover popover {
notify::visible => $popover_visible() swapped;
styles [
"menu",
]
child: Gtk.ScrolledWindow {
hscrollbar-policy: never;
max-content-height: 400;
propagate-natural-width: true;
propagate-natural-height: true;
child: Gtk.ListBox list {
row-activated => $row_activated() swapped;
};
};
}
}
}

51
src/components/rows/combo_loading_row.ui

@ -1,51 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="ComboLoadingRow" parent="AdwActionRow">
<property name="selectable">False</property>
<property name="activatable" bind-source="ComboLoadingRow" bind-property="read-only" bind-flags="sync-create | invert-boolean" />
<style>
<class name="combo"/>
<class name="property"/>
</style>
<child>
<object class="GtkBox" id="arrow_box">
<property name="valign">center</property>
<child>
<object class="LoadingBin" id="loading_bin">
<property name="child">
<object class="GtkImage">
<property name="visible" bind-source="ComboLoadingRow" bind-property="read-only" bind-flags="sync-create | invert-boolean" />
<property name="icon_name">pan-down-symbolic</property>
<property name="accessible-role">presentation</property>
<style>
<class name="dropdown-arrow"/>
</style>
</object>
</property>
</object>
</child>
<child>
<object class="GtkPopover" id="popover">
<signal name="notify::visible" handler="popover_visible" swapped="true"/>
<style>
<class name="menu"/>
</style>
<property name="child">
<object class="GtkScrolledWindow">
<property name="hscrollbar_policy">never</property>
<property name="max-content-height">400</property>
<property name="propagate-natural-width">True</property>
<property name="propagate-natural-height">True</property>
<property name="child">
<object class="GtkListBox" id="list">
<signal name="row-activated" handler="row_activated" swapped="true"/>
</object>
</property>
</object>
</property>
</object>
</child>
</object>
</child>
</template>
</interface>

24
src/components/rows/copyable_row.blp

@ -0,0 +1,24 @@
using Gtk 4.0;
using Adw 1;
template $CopyableRow: Adw.ActionRow {
selectable: false;
Adw.Bin extra_suffix_bin {}
[suffix]
Gtk.Box {
valign: center;
spacing: 6;
Gtk.Button copy_button {
icon-name: "copy-symbolic";
action-name: "copyable-row.copy";
valign: center;
styles [
"flat",
]
}
}
}

25
src/components/rows/copyable_row.ui

@ -1,25 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="CopyableRow" parent="AdwActionRow">
<property name="selectable">False</property>
<child>
<object class="AdwBin" id="extra_suffix_bin"/>
</child>
<child type="suffix">
<object class="GtkBox">
<property name="valign">center</property>
<property name="spacing">6</property>
<child>
<object class="GtkButton" id="copy_button">
<property name="icon-name">copy-symbolic</property>
<property name="action-name">copyable-row.copy</property>
<property name="valign">center</property>
<style>
<class name="flat"/>
</style>
</object>
</child>
</object>
</child>
</template>
</interface>

20
src/components/rows/entry_add_row.blp

@ -0,0 +1,20 @@
using Gtk 4.0;
using Adw 1;
template $EntryAddRow: Adw.EntryRow {
activatable: false;
selectable: false;
changed => $update_add_button() swapped;
$LoadingButton add_button {
sensitive: false;
content-icon-name: "add-symbolic";
valign: center;
halign: center;
clicked => $add() swapped;
styles [
"flat",
]
}
}

20
src/components/rows/entry_add_row.ui

@ -1,20 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="EntryAddRow" parent="AdwEntryRow">
<property name="activatable">False</property>
<property name="selectable">False</property>
<signal name="changed" handler="update_add_button" swapped="yes"/>
<child>
<object class="LoadingButton" id="add_button">
<property name="sensitive">False</property>
<property name="content-icon-name">add-symbolic</property>
<property name="valign">center</property>
<property name="halign">center</property>
<signal name="clicked" handler="add" swapped="true"/>
<style>
<class name="flat"/>
</style>
</object>
</child>
</template>
</interface>

32
src/components/rows/loading_button_row.blp

@ -0,0 +1,32 @@
using Gtk 4.0;
using Adw 1;
template $LoadingButtonRow: Adw.PreferencesRow {
activatable: true;
selectable: false;
accessible-role: button;
accessibility {
labelled-by: [
title,
];
}
styles [
"button",
]
$LoadingBin loading_bin {
child: Gtk.Label title {
styles [
"title",
]
label: bind template.title;
ellipsize: end;
mnemonic-widget: template;
xalign: 0.5;
justify: center;
};
}
}

30
src/components/rows/loading_button_row.ui

@ -1,30 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="LoadingButtonRow" parent="AdwPreferencesRow">
<property name="activatable">true</property>
<property name="selectable">false</property>
<property name="accessible-role">button</property>
<accessibility>
<relation name="labelled-by">title</relation>
</accessibility>
<style>
<class name="button" />
</style>
<child>
<object class="LoadingBin" id="loading_bin">
<property name="child">
<object class="GtkLabel" id="title">
<style>
<class name="title"/>
</style>
<property name="label" bind-source="LoadingButtonRow" bind-property="title" bind-flags="sync-create"/>
<property name="ellipsize">end</property>
<property name="mnemonic-widget">LoadingButtonRow</property>
<property name="xalign">0.5</property>
<property name="justify">center</property>
</object>
</property>
</object>
</child>
</template>
</interface>

31
src/components/rows/loading_row.blp

@ -0,0 +1,31 @@
using Gtk 4.0;
template $LoadingRow {
activatable: false;
selectable: false;
child: $LoadingBin loading_bin {
is-loading: true;
vhomogeneous: false;
child: Gtk.Box error {
orientation: vertical;
spacing: 12;
margin-top: 12;
margin-bottom: 12;
margin-start: 12;
margin-end: 12;
Gtk.Label error_label {
wrap: true;
wrap-mode: word_char;
}
Gtk.Button retry_button {
can-shrink: true;
label: _("Try Again");
halign: center;
}
};
};
}

36
src/components/rows/loading_row.ui

@ -1,36 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="LoadingRow">
<property name="activatable">False</property>
<property name="selectable">False</property>
<property name="child">
<object class="LoadingBin" id="loading_bin">
<property name="is-loading">True</property>
<property name="vhomogeneous">False</property>
<property name="child">
<object class="GtkBox" id="error">
<property name="orientation">vertical</property>
<property name="spacing">12</property>
<property name="margin-top">12</property>
<property name="margin-bottom">12</property>
<property name="margin-start">12</property>
<property name="margin-end">12</property>
<child>
<object class="GtkLabel" id="error_label">
<property name="wrap">True</property>
<property name="wrap-mode">word-char</property>
</object>
</child>
<child>
<object class="GtkButton" id="retry_button">
<property name="can-shrink">true</property>
<property name="label" translatable="yes">Try Again</property>
<property name="halign">center</property>
</object>
</child>
</object>
</property>
</object>
</property>
</template>
</interface>

19
src/components/rows/removable_row.blp

@ -0,0 +1,19 @@
using Gtk 4.0;
using Adw 1;
template $RemovableRow: Adw.ActionRow {
selectable: false;
Adw.Bin extra_suffix_bin {}
$LoadingButton remove_button {
content-icon-name: "close-symbolic";
valign: center;
halign: center;
clicked => $remove() swapped;
styles [
"flat",
]
}
}

20
src/components/rows/removable_row.ui

@ -1,20 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="RemovableRow" parent="AdwActionRow">
<property name="selectable">False</property>
<child>
<object class="AdwBin" id="extra_suffix_bin"/>
</child>
<child>
<object class="LoadingButton" id="remove_button">
<property name="content-icon-name">close-symbolic</property>
<property name="valign">center</property>
<property name="halign">center</property>
<signal name="clicked" handler="remove" swapped="true"/>
<style>
<class name="flat"/>
</style>
</object>
</child>
</template>
</interface>

103
src/components/rows/substring_entry_row.blp

@ -0,0 +1,103 @@
using Gtk 4.0;
using Adw 1;
template $SubstringEntryRow: Adw.PreferencesRow {
activatable: false;
selectable: false;
styles [
"entry",
"substring-entry-row",
]
Gtk.GestureClick {
pressed => $pressed() swapped;
}
child: Gtk.Box header {
valign: center;
styles [
"header",
]
Gtk.Box main_content {
orientation: vertical;
Gtk.Label title {
ellipsize: end;
halign: start;
xalign: 0;
label: bind template.title;
can-target: false;
styles [
"subtitle",
]
}
Gtk.Box entry_box {
spacing: 6;
Gtk.Label entry_prefix_label {
label: "#";
styles [
"dimmed",
]
}
Gtk.Text text {
enable-undo: true;
hexpand: true;
vexpand: true;
max-length: 0;
valign: baseline_fill;
accessible-role: text_box;
accessibility {
labelled-by: [
title,
];
}
activate => $add() swapped;
state-flags-changed => $text_state_flags_changed() swapped;
keynav-failed => $text_keynav_failed() swapped;
changed => $update_add_button() swapped;
}
Gtk.Image edit_icon {
valign: center;
can-target: false;
icon-name: "document-edit-symbolic";
accessible-role: presentation;
styles [
"edit-icon",
]
}
Gtk.Label entry_suffix_label {
label: ":matrix.org";
styles [
"dimmed",
]
}
}
}
$LoadingButton add_button {
sensitive: false;
content-icon-name: "add-symbolic";
valign: center;
halign: center;
clicked => $add() swapped;
styles [
"flat",
]
}
};
}

104
src/components/rows/substring_entry_row.ui

@ -1,104 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="SubstringEntryRow" parent="AdwPreferencesRow">
<property name="activatable">False</property>
<property name="selectable">False</property>
<style>
<class name="substring-entry-row"/>
</style>
<child>
<object class="GtkGestureClick">
<signal name="pressed" handler="pressed" swapped="yes"/>
</object>
</child>
<property name="child">
<object class="GtkBox" id="header">
<property name="valign">center</property>
<style>
<class name="header"/>
</style>
<child>
<object class="GtkBox" id="main_content">
<property name="orientation">vertical</property>
<child>
<object class="GtkLabel" id="title">
<property name="ellipsize">end</property>
<property name="halign">start</property>
<property name="xalign">0</property>
<property name="label" bind-source="SubstringEntryRow" bind-property="title" bind-flags="sync-create"/>
<property name="can-target">False</property>
<style>
<class name="subtitle"/>
</style>
</object>
</child>
<child>
<object class="GtkBox" id="entry_box">
<property name="spacing">6</property>
<child>
<object class="GtkLabel" id="entry_prefix_label">
<property name="label">#</property>
<style>
<class name="dimmed"/>
</style>
</object>
</child>
<child>
<object class="GtkText" id="text">
<property name="enable-undo">True</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="max-length">0</property>
<property name="valign">baseline-fill</property>
<property name="accessible-role">text-box</property>
<accessibility>
<relation name="labelled-by">title</relation>
</accessibility>
<signal name="activate" handler="add" swapped="yes"/>
<signal name="state-flags-changed" handler="text_state_flags_changed" swapped="yes"/>
<signal name="keynav-failed" handler="text_keynav_failed" swapped="yes"/>
<signal name="changed" handler="update_add_button" swapped="yes"/>
</object>
</child>
<child>
<object class="GtkImage" id="edit_icon">
<property name="valign">center</property>
<property name="can-target">False</property>
<property name="icon-name">document-edit-symbolic</property>
<property name="accessible-role">presentation</property>
<style>
<class name="edit-icon"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel" id="entry_suffix_label">
<property name="label">:matrix.org</property>
<style>
<class name="dimmed"/>
</style>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="LoadingButton" id="add_button">
<property name="sensitive">False</property>
<property name="content-icon-name">add-symbolic</property>
<property name="valign">center</property>
<property name="halign">center</property>
<signal name="clicked" handler="add" swapped="true"/>
<style>
<class name="flat"/>
</style>
</object>
</child>
</object>
</property>
<style>
<class name="entry"/>
</style>
</template>
</interface>

24
src/components/rows/switch_loading_row.blp

@ -0,0 +1,24 @@
using Gtk 4.0;
using Adw 1;
template $SwitchLoadingRow: Adw.ActionRow {
selectable: false;
activatable: bind template.read-only inverted;
activatable-widget: switch;
[suffix]
Gtk.Box {
valign: center;
spacing: 6;
Adw.Spinner spinner {
visible: false;
accessible-role: status;
}
Gtk.Switch switch {
sensitive: bind template.read-only inverted;
focusable: false;
}
}
}

26
src/components/rows/switch_loading_row.ui

@ -1,26 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="SwitchLoadingRow" parent="AdwActionRow">
<property name="selectable">False</property>
<property name="activatable" bind-source="SwitchLoadingRow" bind-property="read-only" bind-flags="sync-create | invert-boolean" />
<property name="activatable-widget">switch</property>
<child type="suffix">
<object class="GtkBox">
<property name="valign">center</property>
<property name="spacing">6</property>
<child>
<object class="AdwSpinner" id="spinner">
<property name="visible">False</property>
<property name="accessible-role">status</property>
</object>
</child>
<child>
<object class="GtkSwitch" id="switch">
<property name="sensitive" bind-source="SwitchLoadingRow" bind-property="read-only" bind-flags="sync-create | invert-boolean" />
<property name="focusable">False</property>
</object>
</child>
</object>
</child>
</template>
</interface>

233
src/components/user_page.blp

@ -0,0 +1,233 @@
using Gtk 4.0;
using Adw 1;
template $UserPage: Adw.NavigationPage {
child: Adw.ToolbarView {
[top]
Adw.HeaderBar {
show-title: false;
}
content: Gtk.ScrolledWindow scrolled_window {
hscrollbar-policy: never;
propagate-natural-height: true;
vexpand: true;
child: Adw.Clamp {
maximum-size: 444;
child: Gtk.Box box {
orientation: vertical;
$Avatar avatar {
size: 128;
accessible-role: presentation;
}
Gtk.Box {
orientation: vertical;
spacing: 6;
Gtk.Label {
wrap: true;
wrap-mode: word_char;
justify: center;
label: bind template.user as <$User>.display-name;
styles [
"title-1",
]
}
Gtk.CenterBox {
[center]
Gtk.Label user_id {
ellipsize: end;
justify: center;
label: bind template.user as <$User>.user-id-string;
styles [
"dimmed",
]
}
[end]
Gtk.Button {
icon-name: "copy-symbolic";
tooltip-text: _("Copy Matrix User ID");
valign: center;
hexpand: true;
halign: start;
margin-start: 6;
clicked => $copy_user_id() swapped;
styles [
"flat",
]
}
}
}
Gtk.ListBox direct_chat_box {
visible: false;
styles [
"boxed-list",
]
accessible-role: group;
$LoadingButtonRow direct_chat_button {
is-loading: true;
activated => $open_direct_chat() swapped;
}
}
Gtk.Box room_box {
visible: false;
orientation: vertical;
spacing: 12;
Gtk.Label room_title {
ellipsize: end;
xalign: 0.0;
styles [
"heading",
"h4",
]
}
Gtk.ListBox {
styles [
"boxed-list-separate",
]
Adw.ActionRow membership_row {
selectable: false;
title: _("Role");
accessibility {
described-by: [
membership_label,
];
}
Gtk.Label membership_label {
ellipsize: end;
}
}
$PowerLevelSelectionRow power_level_row {
/* Translators: value used to assign room member roles */
title: _("Power Level");
selected-power-level-changed => $set_power_level() swapped;
}
$LoadingButtonRow invite_button {
title: _("Invite");
activated => $invite_user() swapped;
}
$LoadingButtonRow kick_button {
styles [
"destructive-action",
]
activated => $kick_user() swapped;
}
$LoadingButtonRow ban_button {
styles [
"destructive-action",
]
title: _("Ban");
activated => $ban_user() swapped;
}
$LoadingButtonRow unban_button {
title: _("Unban");
activated => $unban_user() swapped;
}
$LoadingButtonRow remove_messages_button {
styles [
"destructive-action",
]
title: _("Remove Messages");
activated => $remove_messages() swapped;
}
}
}
Gtk.Box {
orientation: vertical;
spacing: 12;
Gtk.Label {
label: _("Security");
ellipsize: end;
xalign: 0.0;
styles [
"heading",
"h4",
]
}
Gtk.ListBox {
styles [
"boxed-list",
]
Adw.ActionRow verified_row {
selectable: false;
Gtk.Stack verified_stack {
transition-type: crossfade;
valign: center;
Gtk.StackPage {
name: "button";
child: $LoadingButton verify_button {
sensitive: false;
content-label: _("Verify");
clicked => $verify_user() swapped;
};
}
Gtk.StackPage {
name: "icon";
child: Gtk.Image {
icon-name: "verified-symbolic";
accessible-role: presentation;
halign: end;
margin-end: 6;
styles [
"success",
]
};
}
}
}
Adw.ActionRow ignored_row {
selectable: false;
$LoadingButton ignored_button {
valign: center;
clicked => $toggle_ignored() swapped;
}
}
}
}
};
};
};
};
}

264
src/components/user_page.ui

@ -1,264 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="UserPage" parent="AdwNavigationPage">
<property name="child">
<object class="AdwToolbarView">
<child type="top">
<object class="AdwHeaderBar">
<property name="show-title">False</property>
</object>
</child>
<property name="content">
<object class="GtkScrolledWindow" id="scrolled_window">
<property name="hscrollbar-policy">never</property>
<property name="propagate-natural-height">True</property>
<property name="vexpand">True</property>
<property name="child">
<object class="AdwClamp">
<property name="maximum-size">444</property>
<property name="child">
<object class="GtkBox" id="box">
<property name="orientation">vertical</property>
<child>
<object class="Avatar" id="avatar">
<property name="size">128</property>
<property name="accessible-role">presentation</property>
</object>
</child>
<child>
<object class="GtkBox">
<property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel">
<property name="wrap">true</property>
<property name="wrap-mode">word-char</property>
<property name="justify">center</property>
<binding name="label">
<lookup name="display-name">
<lookup name="user">UserPage</lookup>
</lookup>
</binding>
<style>
<class name="title-1"/>
</style>
</object>
</child>
<child>
<object class="GtkCenterBox">
<child type="center">
<object class="GtkLabel" id="user_id">
<property name="ellipsize">end</property>
<property name="justify">center</property>
<binding name="label">
<lookup name="user-id-string">
<lookup name="user">UserPage</lookup>
</lookup>
</binding>
<style>
<class name="dimmed"/>
</style>
</object>
</child>
<child type="end">
<object class="GtkButton">
<property name="icon-name">copy-symbolic</property>
<property name="tooltip-text" translatable="yes">Copy Matrix User ID</property>
<property name="valign">center</property>
<property name="hexpand">True</property>
<property name="halign">start</property>
<property name="margin-start">6</property>
<signal name="clicked" handler="copy_user_id" swapped="yes"/>
<style>
<class name="flat"/>
</style>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkListBox" id="direct_chat_box">
<property name="visible">false</property>
<style>
<class name="boxed-list" />
</style>
<property name="accessible-role">group</property>
<child>
<object class="LoadingButtonRow" id="direct_chat_button">
<property name="is-loading">true</property>
<signal name="activated" handler="open_direct_chat" swapped="yes" />
</object>
</child>
</object>
</child>
<child>
<object class="GtkBox" id="room_box">
<property name="visible">False</property>
<property name="orientation">vertical</property>
<property name="spacing">12</property>
<child>
<object class="GtkLabel" id="room_title">
<property name="ellipsize">end</property>
<property name="xalign">0.0</property>
<style>
<class name="heading"/>
<class name="h4"/>
</style>
</object>
</child>
<child>
<object class="GtkListBox">
<style>
<class name="boxed-list-separate"/>
</style>
<child>
<object class="AdwActionRow" id="membership_row">
<property name="selectable">False</property>
<property name="title" translatable="yes">Role</property>
<accessibility>
<relation name="described-by">membership_label</relation>
</accessibility>
<child>
<object class="GtkLabel" id="membership_label">
<property name="ellipsize">end</property>
</object>
</child>
</object>
</child>
<child>
<object class="PowerLevelSelectionRow" id="power_level_row">
<property name="title" translatable="yes" comments="Translators: value used to assign room member roles">Power Level</property>
<signal name="selected-power-level-changed" handler="set_power_level" swapped="yes" />
</object>
</child>
<child>
<object class="LoadingButtonRow" id="invite_button">
<!-- Translators: In this string, 'Invite' is a verb. -->
<property name="title" translatable="yes">Invite</property>
<signal name="activated" handler="invite_user" swapped="yes"/>
</object>
</child>
<child>
<object class="LoadingButtonRow" id="kick_button">
<style>
<class name="destructive-action"/>
</style>
<signal name="activated" handler="kick_user" swapped="yes"/>
</object>
</child>
<child>
<object class="LoadingButtonRow" id="ban_button">
<style>
<class name="destructive-action"/>
</style>
<!-- Translators: As in, 'Ban room member'. -->
<property name="title" translatable="yes">Ban</property>
<signal name="activated" handler="ban_user" swapped="yes"/>
</object>
</child>
<child>
<object class="LoadingButtonRow" id="unban_button">
<!-- Translators: As in, 'Unan room member'. -->
<property name="title" translatable="yes">Unban</property>
<signal name="activated" handler="unban_user" swapped="yes"/>
</object>
</child>
<child>
<object class="LoadingButtonRow" id="remove_messages_button">
<style>
<class name="destructive-action"/>
</style>
<property name="title" translatable="yes">Remove Messages</property>
<signal name="activated" handler="remove_messages" swapped="yes"/>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkBox">
<property name="orientation">vertical</property>
<property name="spacing">12</property>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">Security</property>
<property name="ellipsize">end</property>
<property name="xalign">0.0</property>
<style>
<class name="heading"/>
<class name="h4"/>
</style>
</object>
</child>
<child>
<object class="GtkListBox">
<style>
<class name="boxed-list"/>
</style>
<child>
<object class="AdwActionRow" id="verified_row">
<property name="selectable">False</property>
<child>
<object class="GtkStack" id="verified_stack">
<property name="transition-type">crossfade</property>
<property name="valign">center</property>
<child>
<object class="GtkStackPage">
<property name="name">button</property>
<property name="child">
<object class="LoadingButton" id="verify_button">
<property name="sensitive">False</property>
<property name="content-label" translatable="yes">Verify</property>
<signal name="clicked" handler="verify_user" swapped="yes" />
</object>
</property>
</object>
</child>
<child>
<object class="GtkStackPage">
<property name="name">icon</property>
<property name="child">
<object class="GtkImage">
<property name="icon-name">verified-symbolic</property>
<property name="accessible-role">presentation</property>
<property name="halign">end</property>
<property name="margin-end">6</property>
<style>
<class name="success"/>
</style>
</object>
</property>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="AdwActionRow" id="ignored_row">
<property name="selectable">False</property>
<child>
<object class="LoadingButton" id="ignored_button">
<property name="valign">center</property>
<signal name="clicked" handler="toggle_ignored" swapped="yes"/>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</property>
</object>
</property>
</object>
</property>
</object>
</property>
</template>
</interface>

35
src/ui-resources.gresource.xml

@ -1,41 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/org/gnome/Fractal/ui/">
<file compressed="true" preprocess="xml-stripblanks">components/action_button.ui</file>
<file compressed="true" preprocess="xml-stripblanks">components/avatar/editable.ui</file>
<file compressed="true" preprocess="xml-stripblanks">components/avatar/mod.ui</file>
<file compressed="true" preprocess="xml-stripblanks">components/camera/qrcode_scanner.ui</file>
<file compressed="true" preprocess="xml-stripblanks">components/context_menu_bin.ui</file>
<file compressed="true" preprocess="xml-stripblanks">components/crypto/identity_setup_view.ui</file>
<file compressed="true" preprocess="xml-stripblanks">components/crypto/recovery_setup_view.ui</file>
<file compressed="true" preprocess="xml-stripblanks">components/dialogs/auth/in_browser_page.ui</file>
<file compressed="true" preprocess="xml-stripblanks">components/dialogs/auth/mod.ui</file>
<file compressed="true" preprocess="xml-stripblanks">components/dialogs/auth/password_page.ui</file>
<file compressed="true" preprocess="xml-stripblanks">components/dialogs/room_preview.ui</file>
<file compressed="true" preprocess="xml-stripblanks">components/dialogs/toastable.ui</file>
<file compressed="true" preprocess="xml-stripblanks">components/dialogs/user_profile.ui</file>
<file compressed="true" preprocess="xml-stripblanks">components/loading/bin.ui</file>
<file compressed="true" preprocess="xml-stripblanks">components/media/audio_player.ui</file>
<file compressed="true" preprocess="xml-stripblanks">components/media/content_viewer.ui</file>
<file compressed="true" preprocess="xml-stripblanks">components/media/location_viewer.ui</file>
<file compressed="true" preprocess="xml-stripblanks">components/media/video_player.ui</file>
<file compressed="true" preprocess="xml-stripblanks">components/pill/mod.ui</file>
<file compressed="true" preprocess="xml-stripblanks">components/pill/search_entry.ui</file>
<file compressed="true" preprocess="xml-stripblanks">components/pill/source_row.ui</file>
<file compressed="true" preprocess="xml-stripblanks">components/power_level_selection/combo_box.ui</file>
<file compressed="true" preprocess="xml-stripblanks">components/power_level_selection/popover.ui</file>
<file compressed="true" preprocess="xml-stripblanks">components/power_level_selection/row.ui</file>
<file compressed="true" preprocess="xml-stripblanks">components/rows/button_count_row.ui</file>
<file compressed="true" preprocess="xml-stripblanks">components/rows/check_loading_row.ui</file>
<file compressed="true" preprocess="xml-stripblanks">components/rows/combo_loading_row.ui</file>
<file compressed="true" preprocess="xml-stripblanks">components/rows/copyable_row.ui</file>
<file compressed="true" preprocess="xml-stripblanks">components/rows/entry_add_row.ui</file>
<file compressed="true" preprocess="xml-stripblanks">components/rows/loading_button_row.ui</file>
<file compressed="true" preprocess="xml-stripblanks">components/rows/loading_row.ui</file>
<file compressed="true" preprocess="xml-stripblanks">components/rows/removable_row.ui</file>
<file compressed="true" preprocess="xml-stripblanks">components/rows/substring_entry_row.ui</file>
<file compressed="true" preprocess="xml-stripblanks">components/rows/switch_loading_row.ui</file>
<file compressed="true" preprocess="xml-stripblanks">components/user_page.ui</file>
<file compressed="true" preprocess="xml-stripblanks">identity_verification_view/accept_request_page.ui</file>
<file compressed="true" preprocess="xml-stripblanks">identity_verification_view/cancelled_page.ui</file>
<file compressed="true" preprocess="xml-stripblanks">identity_verification_view/choose_method_page.ui</file>

2
src/window.blp

@ -95,7 +95,7 @@ template $Window: Adw.ApplicationWindow {
condition ("max-width: 600sp")
setters {
template.compact: "True";
template.compact: true;
}
}
}

Loading…
Cancel
Save