Commit a5a3953e authored by Julian Sparber's avatar Julian Sparber

contact-editor: improve UX/UI for unlinking contacts

This moves the unlink feature to the editor. The unlink dialog was
removed.

This imporves the UX as well as the UI for performing unlink of
personas. This also adds the possibility to undo the unlink and to
cancel the complete operation like before only for the contact
infromation.
parent c9392682
......@@ -11,7 +11,6 @@
<file compressed="true" preprocess="xml-stripblanks">ui/contacts-crop-cheese-dialog.ui</file>
<file compressed="true" preprocess="xml-stripblanks">ui/contacts-in-app-notification.ui</file>
<file compressed="true" preprocess="xml-stripblanks">ui/contacts-link-suggestion-grid.ui</file>
<file compressed="true" preprocess="xml-stripblanks">ui/contacts-linked-personas-dialog.ui</file>
<file compressed="true" preprocess="xml-stripblanks">ui/contacts-list-pane.ui</file>
<file compressed="true" preprocess="xml-stripblanks">ui/contacts-setup-window.ui</file>
<file compressed="true" preprocess="xml-stripblanks">ui/contacts-window.ui</file>
......
......@@ -84,12 +84,6 @@
</child>
</object>
</child>
<child>
<object class="GtkButton" id="linked_button">
<property name="visible">True</property>
<property name="label" translatable="yes">Linked Accounts</property>
</object>
</child>
<child>
<object class="GtkButton" id="remove_button">
<property name="visible">True</property>
......
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk+" version="3.22"/>
<template class="ContactsLinkedPersonasDialog" parent="GtkDialog">
<property name="visible">True</property>
<property name="modal">True</property>
<property name="default_width">600</property>
<property name="default_height">400</property>
<child type="titlebar">
<object class="GtkHeaderBar">
<property name="visible">True</property>
<property name="subtitle" translatable="yes">Linked Accounts</property>
</object>
</child>
<child internal-child="vbox">
<object class="GtkBox">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkGrid">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<property name="column_spacing">8</property>
<property name="row_spacing">12</property>
<child>
<object class="GtkScrolledWindow">
<property name="visible">True</property>
<property name="hscrollbar_policy">never</property>
<property name="vscrollbar_policy">automatic</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkListBox" id="linked_accounts_view">
<property name="visible">True</property>
<property name="selection_mode">none</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="halign">center</property>
<property name="label" translatable="yes">You can link contacts by selecting them from the contacts list</property>
</object>
</child>
</object>
</child>
</object>
</child>
</template>
</interface>
......@@ -242,9 +242,6 @@ public class Contacts.ContactEditor : ContactForm {
[GtkChild]
private MenuButton add_detail_button;
[GtkChild]
public Button linked_button;
[GtkChild]
public Button remove_button;
......@@ -262,6 +259,7 @@ public class Contacts.ContactEditor : ContactForm {
HashMap<int, RowData?> rows;
}
private ArrayList<Persona> unlink_personas;
/* the key of the hash_map is the uid of the persona */
private HashMap<string, HashMap<string, Field?>> writable_personas;
......@@ -280,6 +278,7 @@ public class Contacts.ContactEditor : ContactForm {
}
construct {
this.unlink_personas = new ArrayList<Persona> ();
this.writable_personas = new HashMap<string, HashMap<string, Field?>> ();
this.container_grid.size_allocate.connect(on_container_grid_size_allocate);
......@@ -315,10 +314,8 @@ public class Contacts.ContactEditor : ContactForm {
if (contact != null) {
this.remove_button.sensitive = contact.can_remove_personas ();
this.linked_button.sensitive = contact.individual.personas.size > 1;
} else {
this.remove_button.hide ();
this.linked_button.hide ();
}
/* Set the initial remove_button content based on the width */
......@@ -349,6 +346,24 @@ public class Contacts.ContactEditor : ContactForm {
foreach (var p in personas) {
if (!is_first_persona) {
this.container_grid.attach (create_persona_store_label (p), 0, i, 2);
var unlink_button = new Button.with_label(_("unlink"));
unlink_button.set_halign (Align.END);
/* Keep the state of the button */
var unlink = true;
unlink_button.clicked.connect(() => {
if (unlink) {
unlink_button.set_label(_("link"));
unlink = false;
unlink_personas.add (p);
} else {
unlink_button.set_label(_("unlink"));
unlink = true;
unlink_personas.remove (p);
}
});
this.container_grid.attach (unlink_button, 1, i, 2);
last_store_position = ++i;
}
......@@ -1006,6 +1021,10 @@ public class Contacts.ContactEditor : ContactForm {
return props_set;
}
public ArrayList<Persona> get_unlink_personas () {
return unlink_personas;
}
public void add_new_row_for_property (Persona? p, string prop_name, string? type = null) {
/* Somehow, I need to ensure that p is the main/default/first persona */
Persona persona = null;
......
......@@ -153,7 +153,7 @@ public class Contacts.ContactPane : Stack {
remove_contact_editor ();
this.editor = new ContactEditor (this.contact, this.store, this.edit_contact_actions);
this.editor.linked_button.clicked.connect (linked_accounts);
this.editor.remove_button.clicked.connect (delete_contact);
/* enable/disable actions*/
......@@ -190,16 +190,6 @@ public class Contacts.ContactPane : Stack {
}
}
private void linked_accounts () {
var dialog = new LinkedPersonasDialog (this.parent_window, this.store, contact);
if (dialog.run () == ResponseType.CLOSE && dialog.any_unlinked) {
/* update edited contact if any_unlinked */
stop_editing ();
start_editing ();
}
dialog.destroy ();
}
void delete_contact () {
if (contact != null) {
contact.hidden = true;
......@@ -244,6 +234,13 @@ public class Contacts.ContactPane : Stack {
}
}
/* unlink personas */
foreach (var persona in this.editor.get_unlink_personas()) {
unlink_persona.begin (store, contact, persona, (obj, result) => {
unlink_persona.end (result);
});
}
if (this.editor.name_changed ()) {
var v = this.editor.get_full_name_value ();
try {
......
/*
* Copyright (C) 2011 Alexander Larsson <alexl@redhat.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
using Gtk;
using Folks;
[GtkTemplate (ui = "/org/gnome/Contacts/ui/contacts-linked-personas-dialog.ui")]
public class Contacts.LinkedPersonasDialog : Dialog {
private const int AVATAR_SIZE = 54;
[GtkChild]
private ListBox linked_accounts_view;
private Contact contact;
public bool any_unlinked = false;
public LinkedPersonasDialog (Window main_win, Store store, Contact contact) {
Object (
use_header_bar: 1,
transient_for: main_win,
title: contact.individual.display_name
);
this.contact = contact;
this.linked_accounts_view.set_header_func (add_separator);
// loading personas for display
var personas = contact.get_personas_for_display ();
bool is_first = true;
foreach (var p in personas) {
if (is_first) {
is_first = false;
continue;
}
var row_grid = new Grid ();
var image_frame = new Avatar (AVATAR_SIZE, contact);
image_frame.set_hexpand (false);
image_frame.margin = 6;
image_frame.margin_end = 12;
row_grid.attach (image_frame, 0, 0, 1, 2);
var display_name = new Label ("");
display_name.set_halign (Align.START);
display_name.set_valign (Align.END);
display_name.set_hexpand (true);
display_name.set_markup (Markup.printf_escaped ("<span font='bold'>%s</span>", p.display_id));
row_grid.attach (display_name, 1, 0, 1, 1);
var store_name = new Label (Contact.format_persona_store_name_for_contact (p));
store_name.set_halign (Align.START);
store_name.set_valign (Align.START);
store_name.set_hexpand (true);
store_name.get_style_context ().add_class ("dim-label");
row_grid.attach (store_name, 1, 1, 1, 1);
var button = new Button.with_label (_("Unlink"));
button.margin_end = 6;
button.set_valign (Align.CENTER);
button.get_child ().margin = 1;
row_grid.attach (button, 2, 0, 1, 2);
/* signal */
button.clicked.connect (() => {
unlink_persona.begin (store, contact, p, (obj, result) => {
unlink_persona.end (result);
row_grid.destroy ();
this.any_unlinked = true;
/* TODO: Support undo */
/* TODO: Ensure we don't get suggestion for this linkage again */
});
});
row_grid.show_all ();
this.linked_accounts_view.add (row_grid);
}
}
}
......@@ -87,7 +87,6 @@ contacts_vala_sources = files(
'contacts-crop-cheese-dialog.vala',
'contacts-in-app-notification.vala',
'contacts-link-suggestion-grid.vala',
'contacts-linked-personas-dialog.vala',
'contacts-linking.vala',
'contacts-list-pane.vala',
'contacts-max-width-bin.vala',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment