mirror of
https://github.com/TakeV-Lambda/dino.git
synced 2024-11-21 22:44:23 +00:00
Calls: Use GtkHeaderBar for each participant
This commit is contained in:
parent
be751a5dda
commit
0f5f57888e
4 changed files with 95 additions and 110 deletions
|
@ -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,31 +333,39 @@ 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 .call-header-bar button image {
|
||||
color: alpha(white, 0.7);
|
||||
}
|
||||
|
||||
.dino-call-window .call-header-bar button:hover image {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.dino-call-window .participant-title-button {
|
||||
.dino-call-window .participant-header-bar button {
|
||||
background: none;
|
||||
border: 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.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 .participant-header-bar button image {
|
||||
color: alpha(white, 0.7);
|
||||
-gtk-icon-shadow: none;
|
||||
}
|
||||
|
||||
.dino-call-window .participant-header-bar button:hover image {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.dino-call-window .call-bottom-bar {
|
||||
background: linear-gradient(rgba(0,0,0,0), rgba(0,0,0,0.3));
|
||||
border: 0;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
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());
|
||||
|
||||
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);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue