aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarvin W <git@larma.de>2022-02-12 12:54:48 +0100
committerMarvin W <git@larma.de>2022-02-12 14:36:25 +0100
commit0f5f57888e2e237549b1bc7002770ec102ff0e6b (patch)
tree7e95ea3bc079804b13e6cddbec32710242b6ef3b
parentbe751a5dda6e4b4612276d278f59f9f96ed0298c (diff)
downloaddino-0f5f57888e2e237549b1bc7002770ec102ff0e6b.tar.gz
dino-0f5f57888e2e237549b1bc7002770ec102ff0e6b.zip
Calls: Use GtkHeaderBar for each participant
-rw-r--r--main/data/theme.css42
-rw-r--r--main/src/ui/call_window/call_window.vala17
-rw-r--r--main/src/ui/call_window/call_window_controller.vala41
-rw-r--r--main/src/ui/call_window/participant_widget.vala99
4 files changed, 92 insertions, 107 deletions
diff --git a/main/data/theme.css b/main/data/theme.css
index b8def4e1..2451f5d9 100644
--- a/main/data/theme.css
+++ b/main/data/theme.css
@@ -256,6 +256,10 @@ box.dino-input-error label.input-status-highlight-once {
/* Call window */
+.dino-call-window decoration {
+ border-radius: 0;
+}
+
.dino-call-window .titlebar {
min-height: 0;
}
@@ -264,12 +268,6 @@ box.dino-input-error label.input-status-highlight-once {
box-shadow: none;
}
-.dino-call-window .titlebutton.close:hover {
- background: rgba(255,255,255,0.15);
- border-color: rgba(255,255,255,0);
- box-shadow: none;
-}
-
.dino-call-window button.call-button {
outline: 0;
border-radius: 1000px;
@@ -335,29 +333,37 @@ box.dino-input-error label.input-status-highlight-once {
background: rgba(20,20,20,0.5);
}
-.dino-call-window .call-header-bar {
+.dino-call-window .participant-header-bar {
+ background: none;
+ border: none;
+ border-radius: 0;
+ color: #ededec;
+ text-shadow: 0 0 2px black;
+}
+
+.dino-call-window .call-header-background {
background: linear-gradient(rgba(0,0,0,0.4), rgba(0,0,0,0));
border: 0;
border-radius: 0;
}
-.dino-call-window .call-header-bar {
- color: #ededec;
+.dino-call-window .participant-header-bar button {
+ background: none;
}
-.dino-call-window .call-header-bar button image {
- color: alpha(white, 0.7);
+.dino-call-window .participant-header-bar button:hover {
+ background: rgba(255,255,255,0.15);
+ border-color: rgba(255,255,255,0);
+ box-shadow: none;
}
-.dino-call-window .call-header-bar button:hover image {
- color: white;
+.dino-call-window .participant-header-bar button image {
+ color: alpha(white, 0.7);
+ -gtk-icon-shadow: none;
}
-.dino-call-window .participant-title-button {
- background: none;
- border: 0;
- border-radius: 0;
- box-shadow: none;
+.dino-call-window .participant-header-bar button:hover image {
+ color: white;
}
.dino-call-window .call-bottom-bar {
diff --git a/main/src/ui/call_window/call_window.vala b/main/src/ui/call_window/call_window.vala
index cf9ca0e6..ab969597 100644
--- a/main/src/ui/call_window/call_window.vala
+++ b/main/src/ui/call_window/call_window.vala
@@ -15,11 +15,9 @@ namespace Dino.Ui {
public Grid grid = new Grid() { visible=true };
public CallBottomBar bottom_bar = new CallBottomBar() { visible=true };
public Revealer bottom_bar_revealer = new Revealer() { valign=Align.END, transition_type=RevealerTransitionType.CROSSFADE, transition_duration=200, visible=true };
- public HeaderBar header_bar = new HeaderBar() { valign=Align.START, halign=Align.END, show_close_button=true, visible=true };
- public Revealer header_bar_revealer = new Revealer() { halign=Align.END, valign=Align.START, transition_type=RevealerTransitionType.CROSSFADE, transition_duration=200, visible=true };
+ public HeaderBar header_bar = new HeaderBar() { valign=Align.START, halign=Align.END, show_close_button=true, visible=true, opacity=0.0 };
+ public Revealer header_bar_revealer = new Revealer() { halign=Align.END, valign=Align.START, transition_type=RevealerTransitionType.SLIDE_LEFT, transition_duration=200, visible=true, reveal_child=false };
public Box own_video_box = new Box(Orientation.HORIZONTAL, 0) { halign=Align.END, valign=Align.END, visible=true };
- public Revealer invite_button_revealer = new Revealer() { margin_top=50, margin_right=30, halign=Align.END, valign=Align.START, transition_type=RevealerTransitionType.CROSSFADE, transition_duration=200 };
- public Button invite_button = new Button.from_icon_name("dino-account-plus") { relief=ReliefStyle.NONE, visible=true };
private Widget? own_video = null;
private HashMap<string, ParticipantWidget> participant_widgets = new HashMap<string, ParticipantWidget>();
private ArrayList<string> participants = new ArrayList<string>();
@@ -32,12 +30,11 @@ namespace Dino.Ui {
public bool controls_active { get; set; default=true; }
construct {
- Util.force_css(header_bar, "* { background: none; border: 0; border-radius: 0; }");
header_bar.get_style_context().add_class("call-header-bar");
+ header_bar.custom_title = new Box(Orientation.VERTICAL, 0);
+ header_bar.spacing = 0;
header_bar_revealer.add(header_bar);
bottom_bar_revealer.add(bottom_bar);
- invite_button.get_style_context().add_class("black-element");
- invite_button_revealer.add(invite_button);
own_video_box.get_style_context().add_class("own-video");
this.get_style_context().add_class("dino-call-window");
@@ -46,7 +43,6 @@ namespace Dino.Ui {
overlay.add_overlay(own_video_box);
overlay.add_overlay(bottom_bar_revealer);
overlay.add_overlay(header_bar_revealer);
- overlay.add_overlay(invite_button_revealer);
overlay.get_child_position.connect(on_get_child_position);
add(overlay);
@@ -54,8 +50,6 @@ namespace Dino.Ui {
public CallWindow() {
this.bind_property("controls-active", bottom_bar_revealer, "reveal-child", BindingFlags.SYNC_CREATE);
- this.bind_property("controls-active", header_bar_revealer, "reveal-child", BindingFlags.SYNC_CREATE);
- this.bind_property("controls-active", invite_button_revealer, "reveal-child", BindingFlags.SYNC_CREATE);
this.motion_notify_event.connect(reveal_control_elements);
this.enter_notify_event.connect(reveal_control_elements);
@@ -125,8 +119,7 @@ namespace Dino.Ui {
participant_widgets[participants[0]].margin_bottom = margin_bottom;
participant_widgets[participants[0]].margin_start = margin_left;
- participant_widgets[participants[0]].on_lowest_row_changed(margin_bottom == 0);
- participant_widgets[participants[0]].on_highest_row_changed(margin_top == 0);
+ participant_widgets[participants[0]].on_row_changed(margin_top == 0, margin_bottom == 0, margin_left == 0, margin_right == 0);
return;
}
diff --git a/main/src/ui/call_window/call_window_controller.vala b/main/src/ui/call_window/call_window_controller.vala
index e482e3aa..445f88ea 100644
--- a/main/src/ui/call_window/call_window_controller.vala
+++ b/main/src/ui/call_window/call_window_controller.vala
@@ -16,12 +16,12 @@ public class Dino.Ui.CallWindowController : Object {
private HashMap<string, Plugins.VideoCallWidget> participant_videos = new HashMap<string, Plugins.VideoCallWidget>();
private HashMap<string, ParticipantWidget> participant_widgets = new HashMap<string, ParticipantWidget>();
private HashMap<string, PeerState> peer_states = new HashMap<string, PeerState>();
+ private HashMap<string, ulong> invite_handler_ids = new HashMap<string, ulong>();
private int window_height = -1;
private int window_width = -1;
private bool window_size_changed = false;
private ulong[] call_window_handler_ids = new ulong[0];
private ulong[] bottom_bar_handler_ids = new ulong[0];
- private ulong[] invite_handler_ids = new ulong[0];
public CallWindowController(CallWindow call_window, CallState call_state, StreamInteractor stream_interactor) {
this.call_window = call_window;
@@ -93,18 +93,6 @@ public class Dino.Ui.CallWindowController : Object {
call_window_handler_ids += call_window.realize.connect(() => {
capture_window_size();
});
- invite_handler_ids += call_window.invite_button.clicked.connect(() => {
- Gee.List<Account> acc_list = new ArrayList<Account>(Account.equals_func);
- acc_list.add(call.account);
- SelectContactDialog add_chat_dialog = new SelectContactDialog(stream_interactor, acc_list);
- add_chat_dialog.set_transient_for((Window) call_window.get_toplevel());
- add_chat_dialog.title = _("Invite to Call");
- add_chat_dialog.ok_button.label = _("Invite");
- add_chat_dialog.selected.connect((account, jid) => {
- call_state.invite_to_call.begin(jid);
- });
- add_chat_dialog.present();
- });
calls.conference_info_received.connect((call, conference_info) => {
if (!this.call.equals(call)) return;
@@ -129,6 +117,19 @@ public class Dino.Ui.CallWindowController : Object {
update_own_video();
}
+ private void invite_button_clicked() {
+ Gee.List<Account> acc_list = new ArrayList<Account>(Account.equals_func);
+ acc_list.add(call.account);
+ SelectContactDialog add_chat_dialog = new SelectContactDialog(stream_interactor, acc_list);
+ add_chat_dialog.set_transient_for((Window) call_window.get_toplevel());
+ add_chat_dialog.title = _("Invite to Call");
+ add_chat_dialog.ok_button.label = _("Invite");
+ add_chat_dialog.selected.connect((account, jid) => {
+ call_state.invite_to_call.begin(jid);
+ });
+ add_chat_dialog.present();
+ }
+
private void connect_peer_signals(PeerState peer_state) {
string peer_id = peer_state.internal_id;
Jid peer_jid = peer_state.jid;
@@ -149,7 +150,7 @@ public class Dino.Ui.CallWindowController : Object {
call_state.can_convert_into_groupcall.begin((_, res) => {
bool can_convert = call_state.can_convert_into_groupcall.end(res);
- call_window.invite_button_revealer.visible = can_convert;
+ participant_widgets.values.@foreach((widget) => widget.may_show_invite_button = true);
});
call_plugin.devices_changed.connect((media, incoming) => {
@@ -160,7 +161,7 @@ public class Dino.Ui.CallWindowController : Object {
update_audio_device_choices();
update_video_device_choices();
} else if (participant_widgets.size >= 1) {
- call_window.invite_button_revealer.visible = true;
+ participant_widgets.values.@foreach((widget) => widget.may_show_invite_button = true);
}
});
peer_state.counterpart_sends_video_updated.connect((mute) => {
@@ -215,7 +216,8 @@ public class Dino.Ui.CallWindowController : Object {
string participant_name = conversation != null ? Util.get_conversation_display_name(stream_interactor, conversation) : jid.bare_jid.to_string();
ParticipantWidget participant_widget = new ParticipantWidget(participant_name);
- participant_widget.menu_button.clicked.connect((event) => {
+ participant_widget.may_show_invite_button = !participant_widgets.is_empty;
+ participant_widget.debug_information_clicked.connect(() => {
var conn_details_window = new CallConnectionDetailsWindow() { title=participant_name, visible=true };
conn_details_window.update_content(peer_states[participant_id].get_info());
uint timeout_handle_id = Timeout.add_seconds(1, () => {
@@ -227,6 +229,7 @@ public class Dino.Ui.CallWindowController : Object {
conn_details_window.present();
this.call_window.destroy.connect(() => conn_details_window.close() );
});
+ invite_handler_ids[participant_id] += participant_widget.invite_button_clicked.connect(() => invite_button_clicked());
participant_widgets[participant_id] = participant_widget;
call_window.add_participant(participant_id, participant_widget);
@@ -256,7 +259,9 @@ public class Dino.Ui.CallWindowController : Object {
if (peer_states.has_key(participant_id)) debug(@"[%s] Call window controller | Remove participant: %s", call.account.bare_jid.to_string(), peer_states[participant_id].jid.to_string());
participant_videos.unset(participant_id);
+ participant_widgets[participant_id].disconnect(invite_handler_ids[participant_id]);
participant_widgets.unset(participant_id);
+ invite_handler_ids.unset(participant_id);
peer_states.unset(participant_id);
call_window.remove_participant(participant_id);
}
@@ -337,9 +342,9 @@ public class Dino.Ui.CallWindowController : Object {
public override void dispose() {
foreach (ulong handler_id in call_window_handler_ids) call_window.disconnect(handler_id);
foreach (ulong handler_id in bottom_bar_handler_ids) call_window.bottom_bar.disconnect(handler_id);
- foreach (ulong handler_id in invite_handler_ids) call_window.invite_button.disconnect(handler_id);
+ participant_widgets.keys.@foreach((peer_id) => { remove_participant(peer_id); return true; });
- call_window_handler_ids = bottom_bar_handler_ids = invite_handler_ids = new ulong[0];
+ call_window_handler_ids = bottom_bar_handler_ids = new ulong[0];
base.dispose();
}
diff --git a/main/src/ui/call_window/participant_widget.vala b/main/src/ui/call_window/participant_widget.vala
index cbf8df2d..0d8d25b4 100644
--- a/main/src/ui/call_window/participant_widget.vala
+++ b/main/src/ui/call_window/participant_widget.vala
@@ -9,63 +9,57 @@ namespace Dino.Ui {
public class ParticipantWidget : Gtk.Overlay {
public Widget main_widget;
- public Box outer_box = new Box(Orientation.HORIZONTAL, 0) { valign=Align.START, visible=true };
+ public HeaderBar header_bar = new HeaderBar() { valign=Align.START, visible=true };
public Box inner_box = new Box(Orientation.HORIZONTAL, 0) { margin_start=5, margin_top=5, hexpand=true, visible=true };
public Box title_box = new Box(Orientation.VERTICAL, 0) { valign=Align.CENTER, hexpand=true, visible=true };
public CallEncryptionButton encryption_button = new CallEncryptionButton() { opacity=0, relief=ReliefStyle.NONE, height_request=30, width_request=30, margin_end=5, visible=true };
- public Label status_label = new Label("") { ellipsize=EllipsizeMode.MIDDLE };
- public Label name_label = new Label("") { ellipsize=EllipsizeMode.MIDDLE, visible=true };
- public Button menu_button = new Button.from_icon_name("view-more-horizontal-symbolic") { relief=ReliefStyle.NONE, visible=true };
+ public MenuButton menu_button = new MenuButton() { relief=ReliefStyle.NONE, visible=true, image=new Image.from_icon_name("open-menu-symbolic", IconSize.MENU) };
+ public Button invite_button = new Button.from_icon_name("dino-account-plus") { relief=ReliefStyle.NONE, visible=true };
public bool shows_video = false;
public string? participant_name;
bool is_highest_row = false;
- bool is_lowest_row = false;
public bool controls_active { get; set; }
+ public bool may_show_invite_button { get; set; }
+
+ public signal void debug_information_clicked();
+ public signal void invite_button_clicked();
public ParticipantWidget(string participant_name) {
this.participant_name = participant_name;
- name_label.label = participant_name;
-
- name_label.attributes = new AttrList();
- name_label.attributes.filter((attr) => attr.equal(attr_weight_new(Weight.BOLD)));
-
- name_label.attributes = new AttrList();
- name_label.attributes.filter((attr) => attr.equal(attr_scale_new(0.9)));
- status_label.get_style_context().add_class("dim-label");
-
- Util.force_css(outer_box, "* { color: white; text-shadow: 1px 1px black; }");
- menu_button.get_style_context().add_class("participant-title-button");
- encryption_button.get_style_context().add_class("participant-title-button");
-
- title_box.add(name_label);
- title_box.add(status_label);
-
- outer_box.add(inner_box);
-
- inner_box.add(menu_button);
- inner_box.add(encryption_button);
- inner_box.add(title_box);
- inner_box.add(new Button.from_icon_name("go-up-symbolic") { opacity=0, visible=true });
- inner_box.add(new Button.from_icon_name("go-up-symbolic") { opacity=0, visible=true });
-
- this.add_overlay(outer_box);
+ header_bar.title = participant_name;
+ header_bar.get_style_context().add_class("participant-header-bar");
+ header_bar.pack_start(invite_button);
+ header_bar.pack_start(encryption_button);
+ header_bar.pack_end(menu_button);
+ PopoverMenu menu = new PopoverMenu();
+ Box box = new Box(Orientation.VERTICAL, 0) { margin=10, visible=true };
+ ModelButton debug_information_button = new ModelButton() { text=_("Debug information"), visible=true };
+ debug_information_button.clicked.connect(() => debug_information_clicked());
+ box.add(debug_information_button);
+ menu.add(box);
+ menu_button.popover = menu;
+ invite_button.clicked.connect(() => invite_button_clicked());
+
+ this.add_overlay(header_bar);
this.notify["controls-active"].connect(reveal_or_hide_controls);
}
- public void on_show_names_changed(bool show) {
- name_label.visible = show;
- reveal_or_hide_controls();
- }
-
- public void on_highest_row_changed(bool is_highest) {
+ public void on_row_changed(bool is_highest, bool is_lowest, bool is_start, bool is_end) {
is_highest_row = is_highest;
- reveal_or_hide_controls();
- }
-
- public void on_lowest_row_changed(bool is_lowest) {
- is_lowest_row = is_lowest;
+ header_bar.show_close_button = is_highest_row;
+ invite_button.visible = may_show_invite_button && is_highest_row && is_start;
+ if (is_highest_row) {
+ header_bar.get_style_context().add_class("call-header-background");
+ Gtk.Settings? gtk_settings = Gtk.Settings.get_default();
+ if (gtk_settings != null) {
+ string[] buttons = gtk_settings.gtk_decoration_layout.split(":");
+ header_bar.decoration_layout = (is_start ? buttons[0] : "") + ":" + (is_end && buttons.length == 2 ? buttons[1] : "");
+ }
+ } else {
+ header_bar.get_style_context().remove_class("call-header-background");
+ }
reveal_or_hide_controls();
}
@@ -98,32 +92,19 @@ namespace Dino.Ui {
}
public void set_status(string state) {
- status_label.visible = true;
-
if (state == "requested") {
- status_label.label = _("Calling…");
+ header_bar.subtitle = _("Calling…");
} else if (state == "ringing") {
- status_label.label = _("Ringing…");
+ header_bar.subtitle = _("Ringing…");
} else if (state == "establishing") {
- status_label.label = _("Connecting…");
+ header_bar.subtitle = _("Connecting…");
} else {
- status_label.visible = false;
+ header_bar.subtitle = "";
}
}
private void reveal_or_hide_controls() {
- if (controls_active && name_label.visible) {
- title_box.opacity = 1;
- menu_button.opacity = 1;
- } else {
- title_box.opacity = 0;
- menu_button.opacity = 0;
- }
- if (is_highest_row && controls_active) {
- outer_box.get_style_context().add_class("call-header-bar");
- } else {
- outer_box.get_style_context().remove_class("call-header-bar");
- }
+ header_bar.opacity = controls_active ? 1.0 : 0.0;
}
}
} \ No newline at end of file