accountcreationwizard.cpp 40.8 KB
Newer Older
aviau's avatar
aviau committed
1
/*
Sébastien Blin's avatar
Sébastien Blin committed
2
 *  Copyright (C) 2016-2020 Savoir-faire Linux Inc.
aviau's avatar
aviau committed
3
 *  Author: Alexandre Viau <alexandre.viau@savoirfairelinux.com>
4
 *  Author: Hugo Lefeuvre <hugo.lefeuvre@savoirfairelinux.com>
aviau's avatar
aviau committed
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
 *
 *  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 3 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, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.
 */

// GTK+ related
#include <glib/gi18n.h>
#include <gtk/gtk.h>

// LRC
26
#include "api/newaccountmodel.h"
aviau's avatar
aviau committed
27

28
// Jami Client
aviau's avatar
aviau committed
29 30 31
#include "utils/models.h"
#include "avatarmanipulation.h"
#include "accountcreationwizard.h"
32
#include "usernameregistrationbox.h"
33
#include "utils/files.h"
aviau's avatar
aviau committed
34 35 36

struct _AccountCreationWizard
{
37
    GtkScrolledWindow parent;
aviau's avatar
aviau committed
38 39 40 41
};

struct _AccountCreationWizardClass
{
42
    GtkScrolledWindowClass parent_class;
aviau's avatar
aviau committed
43 44 45 46
};

typedef struct _AccountCreationWizardPrivate AccountCreationWizardPrivate;

47 48 49 50 51 52 53
enum class Mode {
    ADD_LOCAL,
    IMPORT_FROM_DEVICE,
    IMPORT_FROM_BACKUP,
    CONNECT_TO_MANAGER
};

aviau's avatar
aviau committed
54 55
struct _AccountCreationWizardPrivate
{
56 57 58 59 60 61
    AccountInfoPointer const *accountInfo_ = nullptr;
    gchar* accountId;
    gchar* username;
    gchar* password;
    gchar* avatar;

aviau's avatar
aviau committed
62
    GtkWidget *stack_account_creation;
63 64
    gboolean username_available;

aviau's avatar
aviau committed
65 66 67 68
    /* choose_account_type_vbox */
    GtkWidget *choose_account_type_vbox;
    GtkWidget *choose_account_type_ring_logo;
    GtkWidget *button_new_account;
69 70
    GtkWidget *button_import_from_device;
    GtkWidget *button_import_from_backup;
71
    GtkWidget *button_show_advanced;
72
    GtkWidget *button_connect_account_manager;
73
    GtkWidget *button_new_sip_account;
aviau's avatar
aviau committed
74

75 76
    /* existing account */
    GtkWidget *existing_account;
77 78 79 80 81 82 83
    GtkWidget *existing_account_label;
    GtkWidget *row_archive;
    GtkWidget *row_pin;
    GtkWidget *button_pin_info;
    GtkWidget *row_pin_label;
    GtkWidget *button_import_from_next;
    GtkWidget *button_import_from_previous;
aviau's avatar
aviau committed
84
    GtkWidget *entry_existing_account_pin;
85
    GtkWidget *entry_existing_account_archive;
aviau's avatar
aviau committed
86 87 88 89 90
    GtkWidget *entry_existing_account_password;
    GtkWidget *retrieving_account;

    /* account creation */
    GtkWidget *account_creation;
91
    GtkWidget *entry_username;
aviau's avatar
aviau committed
92 93
    GtkWidget *entry_password;
    GtkWidget *entry_password_confirm;
94
    GtkWidget *label_password_error;
aviau's avatar
aviau committed
95 96 97 98
    GtkWidget *button_account_creation_next;
    GtkWidget *button_account_creation_previous;
    GtkWidget *box_avatarselection;
    GtkWidget *avatar_manipulation;
99
    GtkWidget *box_username_entry;
100
    GtkWidget *switch_register;
101
    GtkWidget *username_registration_box;
102
    GtkWidget *entry_display_name;
aviau's avatar
aviau committed
103 104 105 106

    /* generating_account_spinner */
    GtkWidget *vbox_generating_account_spinner;

107 108 109
    /* registering_username_spinner */
    GtkWidget *vbox_registering_username_spinner;

110 111 112 113 114 115 116 117
    /* backup */
    GtkWidget *info_backup;
    GtkWidget *button_never_show_again;
    GtkWidget *button_export_account;
    GtkWidget *button_skip_backup;
    GtkWidget *button_backup_info;
    GtkWidget *row_backup_label;

aviau's avatar
aviau committed
118 119
    /* error_view */
    GtkWidget *error_view;
120
    GtkWidget *label_error_view;
aviau's avatar
aviau committed
121 122
    GtkWidget *button_error_view_ok;

123 124 125 126 127 128 129 130
    /* connect to account_manager */
    GtkWidget *connect_to_account_manager;
    GtkWidget *entry_account_manager_username;
    GtkWidget *entry_account_manager_password;
    GtkWidget *entry_account_manager_uri;
    GtkWidget *button_account_manager_connect_previous;
    GtkWidget *button_account_manager_connect_next;

131
    lrc::api::AVModel* avModel_;
132 133 134
    lrc::api::NewAccountModel* accountModel_;

    Mode mode;
135

136
    GSettings *settings;
aviau's avatar
aviau committed
137 138
};

139
G_DEFINE_TYPE_WITH_PRIVATE(AccountCreationWizard, account_creation_wizard, GTK_TYPE_SCROLLED_WINDOW);
aviau's avatar
aviau committed
140 141 142 143 144

#define ACCOUNT_CREATION_WIZARD_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), ACCOUNT_CREATION_WIZARD_TYPE, AccountCreationWizardPrivate))

/* signals */
enum {
145 146
    ACCOUNT_CREATION_LOCK,
    ACCOUNT_CREATION_UNLOCK,
aviau's avatar
aviau committed
147 148 149 150 151 152 153 154 155
    ACCOUNT_CREATION_COMPLETED,
    LAST_SIGNAL
};

static guint account_creation_wizard_signals[LAST_SIGNAL] = { 0 };

static void
account_creation_wizard_dispose(GObject *object)
{
156 157 158
    // make sure preview is stopped and destroyed
    account_creation_wizard_show_preview(ACCOUNT_CREATION_WIZARD(object), FALSE);

159 160 161
    auto* priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(object);
    g_clear_object(&priv->settings);

aviau's avatar
aviau committed
162 163 164 165 166 167 168
    G_OBJECT_CLASS(account_creation_wizard_parent_class)->dispose(object);
}

static void
account_creation_wizard_init(AccountCreationWizard *view)
{
    gtk_widget_init_template(GTK_WIDGET(view));
169 170 171 172 173 174 175 176

    auto *priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(view);
    priv->settings = g_settings_new_full(get_settings_schema(), NULL, NULL);


    g_settings_bind(priv->settings, "never-show-backup-again",
                    priv->button_never_show_again, "active",
                    G_SETTINGS_BIND_DEFAULT);
aviau's avatar
aviau committed
177 178 179 180 181 182 183 184
}

static void
account_creation_wizard_class_init(AccountCreationWizardClass *klass)
{
    G_OBJECT_CLASS(klass)->dispose = account_creation_wizard_dispose;

    gtk_widget_class_set_template_from_resource(GTK_WIDGET_CLASS (klass),
185
                                                "/net/jami/JamiGnome/accountcreationwizard.ui");
aviau's avatar
aviau committed
186 187 188 189 190 191 192

    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, stack_account_creation);

    /* choose_account_type_vbox */
    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, choose_account_type_vbox);
    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, choose_account_type_ring_logo);
    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, button_new_account);
193 194
    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, button_import_from_device);
    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, button_import_from_backup);
195
    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, button_show_advanced);
196
    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, button_connect_account_manager);
197
    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, button_new_sip_account);
aviau's avatar
aviau committed
198

199 200
    /* existing account */
    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, existing_account);
201 202 203 204 205 206 207
    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, existing_account_label);
    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, row_archive);
    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, row_pin);
    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, button_pin_info);
    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, row_pin_label);
    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, button_import_from_next);
    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, button_import_from_previous);
aviau's avatar
aviau committed
208
    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, entry_existing_account_pin);
209
    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, entry_existing_account_archive);
aviau's avatar
aviau committed
210 211 212 213 214 215 216 217 218 219 220
    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, entry_existing_account_password);
    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, retrieving_account);

    /* account creation */
    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, account_creation);
    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, entry_password);
    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, entry_password_confirm);
    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, button_account_creation_next);
    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, button_account_creation_previous);
    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, box_avatarselection);
    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, label_password_error);
221
    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, box_username_entry);
222
    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, switch_register);
223
    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, entry_display_name);
aviau's avatar
aviau committed
224 225 226 227

    /* generating_account_spinner */
    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, vbox_generating_account_spinner);

228 229 230
    /* registering_username_spinner */
    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, vbox_registering_username_spinner);

231 232 233 234 235 236 237 238
    /* info backup */
    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, info_backup);
    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, button_never_show_again);
    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, button_export_account);
    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, row_backup_label);
    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, button_backup_info);
    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, button_skip_backup);

aviau's avatar
aviau committed
239 240
    /* error view */
    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, error_view);
241
    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, label_error_view);
aviau's avatar
aviau committed
242 243
    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, button_error_view_ok);

244 245 246 247 248 249 250 251
    /* connect to account_manager */
    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, connect_to_account_manager);
    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, entry_account_manager_username);
    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, entry_account_manager_password);
    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, entry_account_manager_uri);
    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, button_account_manager_connect_previous);
    gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountCreationWizard, button_account_manager_connect_next);

aviau's avatar
aviau committed
252 253 254 255 256 257 258 259 260 261
    /* add signals */
    account_creation_wizard_signals[ACCOUNT_CREATION_COMPLETED] = g_signal_new("account-creation-completed",
                 G_TYPE_FROM_CLASS(klass),
                 (GSignalFlags) (G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION),
                 0,
                 nullptr,
                 nullptr,
                 g_cclosure_marshal_VOID__VOID,
                 G_TYPE_NONE, 0);

262 263 264 265 266 267 268 269 270 271
    account_creation_wizard_signals[ACCOUNT_CREATION_LOCK] = g_signal_new("account-creation-lock",
                 G_TYPE_FROM_CLASS(klass),
                 (GSignalFlags) (G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION),
                 0,
                 nullptr,
                 nullptr,
                 g_cclosure_marshal_VOID__VOID,
                 G_TYPE_NONE, 0);

    account_creation_wizard_signals[ACCOUNT_CREATION_UNLOCK] = g_signal_new("account-creation-unlock",
aviau's avatar
aviau committed
272 273 274 275 276 277 278 279 280
                 G_TYPE_FROM_CLASS(klass),
                 (GSignalFlags) (G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION),
                 0,
                 nullptr,
                 nullptr,
                 g_cclosure_marshal_VOID__VOID,
                 G_TYPE_NONE, 0);
}

281 282
void
account_creation_show_error_view(AccountCreationWizard *view, const std::string& id)
aviau's avatar
aviau committed
283
{
284 285 286 287 288 289 290 291 292 293 294 295 296
    auto* priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(view);
    if (priv->accountId && id == priv->accountId) {
        switch (priv->mode) {
            case Mode::ADD_LOCAL:
                gtk_label_set_text(GTK_LABEL(priv->label_error_view),
                    _("An error occured during the account creation."));
                break;
            case Mode::IMPORT_FROM_DEVICE:
                gtk_label_set_text(GTK_LABEL(priv->label_error_view),
                    _("Cannot retrieve any account, please verify your PIN and your password."));
                break;
            case Mode::IMPORT_FROM_BACKUP:
                gtk_label_set_text(GTK_LABEL(priv->label_error_view),
297
                    _("Cannot retrieve any account, please verify your archive and your password."));
298 299 300 301 302 303
                break;
            case Mode::CONNECT_TO_MANAGER:
                gtk_label_set_text(GTK_LABEL(priv->label_error_view),
                    _("Cannot connect to provided account manager. Please check your credentials."));
                break;
        }
304
        gtk_stack_set_visible_child(GTK_STACK(priv->stack_account_creation), priv->error_view);
305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324
    }
}

static gboolean
connect_to_manager(AccountCreationWizard *view, gchar* username, gchar* password, gchar* managerUri)
{
    g_return_val_if_fail(IS_ACCOUNT_CREATION_WIZARD(view), G_SOURCE_REMOVE);
    auto* priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(view);
    g_signal_emit(G_OBJECT(view), account_creation_wizard_signals[ACCOUNT_CREATION_LOCK], 0);

    std::string accountId = lrc::api::NewAccountModel::connectToAccountManager(
                                   username? username : "",
                                   password? password : "",
                                   managerUri? managerUri : "");
    priv->accountId = g_strdup(accountId.c_str());
    // NOTE: NewAccountModel::accountAdded will be triggered here and will call account_creation_wizard_account_added

    g_object_ref(view);  // ref so its not destroyed too early

    return G_SOURCE_REMOVE;
aviau's avatar
aviau committed
325 326 327
}

static gboolean
328
create_account(AccountCreationWizard *view,
329 330
                    gchar *display_name,
                    gchar *username,
aviau's avatar
aviau committed
331
                    gchar *password,
332 333
                    gchar *pin,
                    gchar *archivePath)
aviau's avatar
aviau committed
334 335
{
    g_return_val_if_fail(IS_ACCOUNT_CREATION_WIZARD(view), G_SOURCE_REMOVE);
336 337 338
    auto* priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(view);

    g_signal_emit(G_OBJECT(view), account_creation_wizard_signals[ACCOUNT_CREATION_LOCK], 0);
aviau's avatar
aviau committed
339

340 341 342 343 344 345 346 347 348 349 350
    priv->username = g_strdup(username);
    priv->password = g_strdup(password);
    std::string accountId = lrc::api::NewAccountModel::createNewAccount(
                                   lrc::api::profile::Type::RING,
                                   display_name? display_name : "",
                                   archivePath? archivePath : "",
                                   password? password : "",
                                   pin? pin : "");
    priv->accountId = g_strdup(accountId.c_str());
    priv->avatar = g_strdup(avatar_manipulation_get_temporary(AVATAR_MANIPULATION(priv->avatar_manipulation)));
    // NOTE: NewAccountModel::accountAdded will be triggered here and will call account_creation_wizard_account_added
351

352
    g_object_ref(view);  // ref so its not destroyed too early
aviau's avatar
aviau committed
353

354 355
    return G_SOURCE_REMOVE;
}
aviau's avatar
aviau committed
356

357
void
358
account_creation_wizard_account_added(AccountCreationWizard *view, const std::string& id)
359 360
{
    g_return_if_fail(IS_ACCOUNT_CREATION_WIZARD(view));
361 362
    auto* priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(view);
    if (id != priv->accountId) {
363 364
        // Not for this account. Abort
        return;
aviau's avatar
aviau committed
365
    }
366 367
    // Register username
    if (priv->username) {
368
        priv->accountModel_->registerName(priv->accountId, priv->password, priv->username);
369
    }
370 371 372
    // Set avatar if any.
    if (priv->avatar) {
        try {
373
            priv->accountModel_->setAvatar(priv->accountId, priv->avatar);
374 375
        } catch (std::out_of_range&) {
            g_warning("Can't set avatar for unknown account");
aviau's avatar
aviau committed
376
        }
377
    }
aviau's avatar
aviau committed
378

379 380 381 382 383 384 385 386
    if (!g_settings_get_boolean(priv->settings, "never-show-backup-again") && priv->mode == Mode::ADD_LOCAL) {
        gtk_button_set_label(GTK_BUTTON(priv->button_export_account), _("Export account"));
        gtk_widget_show_all(priv->info_backup);
        gtk_stack_set_visible_child(GTK_STACK(priv->stack_account_creation), priv->info_backup);
    } else {
        g_signal_emit(G_OBJECT(view), account_creation_wizard_signals[ACCOUNT_CREATION_COMPLETED], 0);
    }

387
    g_object_unref(view);
aviau's avatar
aviau committed
388 389 390
}

static gboolean
391
create_new_account(AccountCreationWizard *win)
aviau's avatar
aviau committed
392 393
{
    g_return_val_if_fail(IS_ACCOUNT_CREATION_WIZARD(win), G_SOURCE_REMOVE);
394
    auto* priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(win);
aviau's avatar
aviau committed
395

396 397 398 399 400 401 402
    /* Tuleap: #1441
     * if the user did not validate the avatar area selection, we still take that as the image
     * for their avatar; otherwise many users end up with no avatar by default
     * TODO: improve avatar creation process to not need this fix
     */
    avatar_manipulation_wizard_completed(AVATAR_MANIPULATION(priv->avatar_manipulation));

403 404
    gchar *display_name = g_strdup(gtk_entry_get_text(GTK_ENTRY(priv->entry_display_name)));
    gchar *username = g_strdup(gtk_entry_get_text(GTK_ENTRY(priv->entry_username)));
aviau's avatar
aviau committed
405 406 407 408
    gchar *password = g_strdup(gtk_entry_get_text(GTK_ENTRY(priv->entry_password)));
    gtk_entry_set_text(GTK_ENTRY(priv->entry_password), "");
    gtk_entry_set_text(GTK_ENTRY(priv->entry_password_confirm), "");

409
    auto status = create_account(win, display_name, username, password, nullptr, nullptr);
aviau's avatar
aviau committed
410

411 412 413 414
    // Now that we've use the preview to generate the avatar, we can safely close it. Don't
    // assume owner will do it for us, this might not always be the case
    account_creation_wizard_show_preview(win, FALSE);

415
    g_free(display_name);
aviau's avatar
aviau committed
416
    g_free(password);
417
    g_free(username);
aviau's avatar
aviau committed
418 419 420 421

    return status;
}

422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440
static gboolean
connect_to_account_manager(AccountCreationWizard *win)
{
    g_return_val_if_fail(IS_ACCOUNT_CREATION_WIZARD(win), G_SOURCE_REMOVE);
    auto* priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(win);

    gchar *username = g_strdup(gtk_entry_get_text(GTK_ENTRY(priv->entry_account_manager_username)));
    gchar *password = g_strdup(gtk_entry_get_text(GTK_ENTRY(priv->entry_account_manager_password)));
    gchar *managerUri = g_strdup(gtk_entry_get_text(GTK_ENTRY(priv->entry_account_manager_uri)));

    auto status = connect_to_manager(win, username, password, managerUri);

    g_free(username);
    g_free(password);
    g_free(managerUri);

    return status;
}

aviau's avatar
aviau committed
441 442 443 444
static gboolean
create_existing_ring_account(AccountCreationWizard *win)
{
    g_return_val_if_fail(IS_ACCOUNT_CREATION_WIZARD(win), G_SOURCE_REMOVE);
445
    auto* priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(win);
aviau's avatar
aviau committed
446 447 448 449

    gchar *password = g_strdup(gtk_entry_get_text(GTK_ENTRY(priv->entry_existing_account_password)));
    gtk_entry_set_text(GTK_ENTRY(priv->entry_existing_account_password), "");

450 451
    gchar *pin = g_strdup(gtk_entry_get_text(GTK_ENTRY(priv->entry_existing_account_pin)));
    if (pin and strlen(pin) > 0) {
452 453
        gtk_entry_set_text(GTK_ENTRY(priv->entry_existing_account_pin), "");
    }
aviau's avatar
aviau committed
454

455 456
    gchar *archive = g_strdup(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(priv->entry_existing_account_archive)));
    if (archive) {
457 458 459
        gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(priv->entry_existing_account_archive), nullptr);
    }

460
    auto status = create_account(win, NULL, NULL, password, pin, archive);
aviau's avatar
aviau committed
461

462
    g_free(archive);
aviau's avatar
aviau committed
463 464 465 466 467 468 469 470 471
    g_free(password);
    g_free(pin);

    return status;
}

static void
show_generating_account_spinner(AccountCreationWizard *view)
{
472
    auto* priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(view);
aviau's avatar
aviau committed
473 474 475 476 477 478
    gtk_stack_set_visible_child(GTK_STACK(priv->stack_account_creation), priv->vbox_generating_account_spinner);
}

static void
account_creation_next_clicked(G_GNUC_UNUSED GtkButton *button, AccountCreationWizard *win)
{
479
    auto* priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(win);
aviau's avatar
aviau committed
480 481 482 483 484 485 486

    /* Check for correct password */
    const gchar *password = gtk_entry_get_text(GTK_ENTRY(priv->entry_password));
    const gchar *password_confirm = gtk_entry_get_text(GTK_ENTRY(priv->entry_password_confirm));

    if (g_strcmp0(password, password_confirm) != 0)
    {
487
        gtk_label_set_text(GTK_LABEL(priv->label_password_error), _("Passwords don't match"));
aviau's avatar
aviau committed
488 489 490 491 492 493 494 495 496
        return;
    }

    show_generating_account_spinner(win);

    /* now create account after a short timeout so that the the save doesn't
     * happen freeze the client before the widget changes happen;
     * the timeout function should then display the next step in account creation
     */
497 498 499 500 501 502 503 504 505 506 507 508 509
    g_timeout_add_full(G_PRIORITY_DEFAULT, 300, (GSourceFunc)create_new_account, win, NULL);
}

static void
connect_account_manager_next_clicked(G_GNUC_UNUSED GtkButton *button, AccountCreationWizard *win)
{
    show_generating_account_spinner(win);

    /* now create account after a short timeout so that the the save doesn't
     * happen freeze the client before the widget changes happen;
     * the timeout function should then display the next step in account creation
     */
    g_timeout_add_full(G_PRIORITY_DEFAULT, 300, (GSourceFunc)connect_to_account_manager, win, NULL);
aviau's avatar
aviau committed
510 511 512 513 514
}

static void
show_retrieving_account(AccountCreationWizard *win)
{
515
    auto* priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(win);
aviau's avatar
aviau committed
516 517 518 519
    gtk_stack_set_visible_child(GTK_STACK(priv->stack_account_creation), priv->retrieving_account);
}

static void
520
existing_account_next_clicked(AccountCreationWizard *win)
aviau's avatar
aviau committed
521 522 523 524 525 526 527 528 529 530 531 532 533
{
    show_retrieving_account(win);

    /* now create account after a short timeout so that the the save doesn't
     * happen freeze the client before the widget changes happen;
     * the timeout function should then display the next step in account creation
     */
    g_timeout_add_full(G_PRIORITY_DEFAULT, 300, (GSourceFunc)create_existing_ring_account, win, NULL);
}

static void
show_choose_account_type(AccountCreationWizard *view)
{
534
    auto* priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(view);
535 536 537 538 539

    /* Make sure other stack elements are hidden, otherwise their width will prevent
       the window to be correctly resized at this stage. */
    gtk_widget_hide(priv->account_creation);
    gtk_widget_hide(priv->existing_account);
540
    gtk_widget_hide(priv->connect_to_account_manager);
541

aviau's avatar
aviau committed
542 543 544
    gtk_stack_set_visible_child(GTK_STACK(priv->stack_account_creation), priv->choose_account_type_vbox);
}

545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571
static void
show_pin_label(AccountCreationWizard *view)
{
    auto* priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(view);
    gtk_widget_set_visible(priv->row_pin_label, !gtk_widget_is_visible(priv->row_pin_label));
}

static void
show_backup_label(AccountCreationWizard *view)
{
    auto* priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(view);
    gtk_widget_set_visible(priv->row_backup_label, !gtk_widget_is_visible(priv->row_backup_label));
}

static void
error_ok_clicked(AccountCreationWizard *view)
{
    g_signal_emit(G_OBJECT(view), account_creation_wizard_signals[ACCOUNT_CREATION_UNLOCK], 0);
    show_choose_account_type(view);
}

static void
skip_backup_clicked(AccountCreationWizard *view)
{
    g_signal_emit(G_OBJECT(view), account_creation_wizard_signals[ACCOUNT_CREATION_COMPLETED], 0);
}

aviau's avatar
aviau committed
572
static void
573
account_creation_previous_clicked(G_GNUC_UNUSED GtkButton *button, AccountCreationWizard *view)
574
{
575 576 577
    // make sure to stop preview before going back to choose account type
    account_creation_wizard_show_preview(view, FALSE);
    show_choose_account_type(view);
aviau's avatar
aviau committed
578 579 580
}

static void
581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606
connect_account_manager_previous_clicked(G_GNUC_UNUSED GtkButton *button, AccountCreationWizard *view)
{
    show_choose_account_type(view);
}

static void
show_import_from_device(AccountCreationWizard *view)
{
    auto* priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(view);

    gtk_label_set_text(GTK_LABEL(priv->existing_account_label), _("Import from device"));
    gtk_entry_set_text(GTK_ENTRY(priv->entry_existing_account_pin), "");
    gtk_entry_set_text(GTK_ENTRY(priv->entry_existing_account_password), "");
    gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(priv->entry_existing_account_archive), nullptr);

    gtk_widget_show_all(priv->existing_account);
    gtk_widget_hide(priv->row_archive);
    gtk_widget_hide(priv->row_pin_label);
    gtk_widget_hide(priv->row_backup_label);

    gtk_stack_set_visible_child(GTK_STACK(priv->stack_account_creation), priv->existing_account);
    priv->mode = Mode::IMPORT_FROM_DEVICE;
}

static void
show_import_from_backup(AccountCreationWizard *view)
aviau's avatar
aviau committed
607
{
608 609 610 611 612 613 614 615 616 617 618
    auto* priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(view);

    gtk_label_set_text(GTK_LABEL(priv->existing_account_label), _("Import from backup"));
    gtk_entry_set_text(GTK_ENTRY(priv->entry_existing_account_pin), "");
    gtk_entry_set_text(GTK_ENTRY(priv->entry_existing_account_password), "");
    gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(priv->entry_existing_account_archive), nullptr);

    gtk_widget_show_all(priv->existing_account);
    gtk_widget_hide(priv->row_pin);
    gtk_widget_hide(priv->row_pin_label);
    gtk_widget_hide(priv->row_backup_label);
619

620
    gtk_stack_set_visible_child(GTK_STACK(priv->stack_account_creation), priv->existing_account);
621
    priv->mode = Mode::IMPORT_FROM_BACKUP;
aviau's avatar
aviau committed
622 623 624
}

static void
625
show_connect_account_manager(AccountCreationWizard *view)
aviau's avatar
aviau committed
626
{
627 628 629 630 631
    auto* priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(view);

    gtk_widget_show(priv->connect_to_account_manager);
    gtk_stack_set_visible_child(GTK_STACK(priv->stack_account_creation), priv->connect_to_account_manager);
    priv->mode = Mode::CONNECT_TO_MANAGER;
aviau's avatar
aviau committed
632 633
}

634 635 636
static void
show_advanced(G_GNUC_UNUSED GtkButton *button, AccountCreationWizard *view)
{
637 638
    auto* priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(view);
    gtk_widget_set_visible(GTK_WIDGET(priv->button_connect_account_manager), !gtk_widget_is_visible(GTK_WIDGET(priv->button_connect_account_manager)));
639 640 641 642 643 644 645 646 647 648 649
    gtk_widget_set_visible(GTK_WIDGET(priv->button_new_sip_account), !gtk_widget_is_visible(GTK_WIDGET(priv->button_new_sip_account)));
}

static void
create_new_sip_account(G_GNUC_UNUSED GtkButton *button, AccountCreationWizard *view)
{
    lrc::api::NewAccountModel::createNewAccount(lrc::api::profile::Type::SIP, "SIP");
    g_signal_emit(G_OBJECT(view), account_creation_wizard_signals[ACCOUNT_CREATION_COMPLETED], 0);
    g_object_unref(view);
}

aviau's avatar
aviau committed
650 651 652
static void
entries_existing_account_changed(G_GNUC_UNUSED GtkEntry *entry, AccountCreationWizard *view)
{
653
    auto* priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(view);
aviau's avatar
aviau committed
654 655

    const gchar *pin = gtk_entry_get_text(GTK_ENTRY(priv->entry_existing_account_pin));
656
    gchar *archive_path = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(priv->entry_existing_account_archive));
657 658 659

    bool hasPin = pin and strlen(pin) > 0;
    bool hasArchive = archive_path and strlen(archive_path) > 0;
aviau's avatar
aviau committed
660

661
    gtk_widget_set_sensitive(
662 663 664 665 666 667 668 669
        priv->entry_existing_account_pin,
        (not hasArchive)
    );
    gtk_widget_set_sensitive(
        priv->entry_existing_account_archive,
        (not hasPin)
    );
    gtk_widget_set_sensitive(
670
        priv->button_import_from_next,
671
        (hasArchive || hasPin)
672
    );
673 674

    g_free(archive_path);
aviau's avatar
aviau committed
675 676 677
}

static void
678
entries_new_account_changed(AccountCreationWizard *view)
aviau's avatar
aviau committed
679
{
680
    auto* priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(view);
aviau's avatar
aviau committed
681

682
    const gchar *username = gtk_entry_get_text(GTK_ENTRY(priv->entry_username));
683
    const gboolean sign_up_blockchain = gtk_switch_get_active(GTK_SWITCH(priv->switch_register));
684 685

    if (
686 687
            (sign_up_blockchain && strlen(username) > 0 && priv->username_available) || // we are signing up, username is set and avaialble
            !sign_up_blockchain // We are not signing up
688
        )
aviau's avatar
aviau committed
689 690 691 692 693 694 695 696 697
    {
        gtk_widget_set_sensitive(priv->button_account_creation_next, TRUE);
    }
    else
    {
        gtk_widget_set_sensitive(priv->button_account_creation_next, FALSE);
    }
}

698 699 700 701 702 703 704 705 706 707 708 709
static void
entries_connect_account_manager_changed(AccountCreationWizard *view)
{
    auto* priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(view);

    const std::string username = gtk_entry_get_text(GTK_ENTRY(priv->entry_account_manager_username));
    const std::string managerUri = gtk_entry_get_text(GTK_ENTRY(priv->entry_account_manager_uri));
    const std::string password = gtk_entry_get_text(GTK_ENTRY(priv->entry_account_manager_password));

    gtk_widget_set_sensitive(priv->button_account_manager_connect_next, (!username.empty() && !managerUri.empty() && !password.empty()));
}

aviau's avatar
aviau committed
710
static void
711
sign_up_blockchain_switched(GtkSwitch* switch_btn, GParamSpec*, AccountCreationWizard *view)
712
{
713
    auto* priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(view);
714
    gboolean sign_up_blockchain = gtk_switch_get_active(switch_btn);
715 716 717 718 719 720

    username_registration_box_set_use_blockchain(
        USERNAME_REGISTRATION_BOX(priv->username_registration_box),
        sign_up_blockchain
    );

721 722 723 724 725 726 727
    gtk_widget_set_sensitive(priv->entry_username, sign_up_blockchain);

    if (!sign_up_blockchain)
    {
        gtk_entry_set_text(GTK_ENTRY(priv->entry_username), "");
    }

728 729
    /* Unchecking blockchain signup when there is an empty username should
     * result in activating the next button.
730
     */
731 732 733 734 735 736
    entries_new_account_changed(view);
}

static void
username_availability_changed(AccountCreationWizard *view, gboolean username_available)
{
737
    auto* priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(view);
738 739 740 741
    priv->username_available = username_available;
    entries_new_account_changed(view);
}

742
// Export file
743
static void
744
choose_export_file(AccountCreationWizard *view)
aviau's avatar
aviau committed
745 746
{
    g_return_if_fail(IS_ACCOUNT_CREATION_WIZARD(view));
747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820
    auto* priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(view);
    // Get preferred path
    GtkWidget* dialog;
    GtkFileChooserAction action = GTK_FILE_CHOOSER_ACTION_SAVE;
    gint res;
    gchar* filename = nullptr;

    dialog = gtk_file_chooser_dialog_new(_("Save File"),
                                         GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(view))),
                                         action,
                                         _("_Cancel"),
                                         GTK_RESPONSE_CANCEL,
                                         _("_Save"),
                                         GTK_RESPONSE_ACCEPT,
                                         nullptr);

    const auto& accountInfo = priv->accountModel_->getAccountInfo(priv->accountId);
    std::string alias = accountInfo.profileInfo.alias;
    std::string uri = alias.empty()? "export.gz" : alias + ".gz";
    gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), uri.c_str());
    res = gtk_dialog_run(GTK_DIALOG(dialog));

    if (res == GTK_RESPONSE_ACCEPT) {
        auto chooser = GTK_FILE_CHOOSER(dialog);
        filename = gtk_file_chooser_get_filename(chooser);
    }
    gtk_widget_destroy(dialog);

    if (!filename) return;

    std::string password = {};
    auto prop = priv->accountModel_->getAccountConfig(priv->accountId);
    if (prop.archiveHasPassword) {
        auto* top_window = GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(view)));
        auto* password_dialog = gtk_message_dialog_new(top_window,
            GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_OK_CANCEL,
            _("You need to enter your password to export the full archive."));
        gtk_window_set_title(GTK_WINDOW(password_dialog), _("Enter password to export archive"));
        gtk_dialog_set_default_response(GTK_DIALOG(password_dialog), GTK_RESPONSE_OK);

        auto* message_area = gtk_message_dialog_get_message_area(GTK_MESSAGE_DIALOG(password_dialog));
        auto* password_entry = gtk_entry_new();
        gtk_entry_set_visibility(GTK_ENTRY(password_entry), false);
        gtk_entry_set_invisible_char(GTK_ENTRY(password_entry), '*');
        gtk_box_pack_start(GTK_BOX(message_area), password_entry, true, true, 0);
        gtk_widget_show_all(password_dialog);

        auto res = gtk_dialog_run(GTK_DIALOG(password_dialog));
        if (res == GTK_RESPONSE_OK) {
            password = gtk_entry_get_text(GTK_ENTRY(password_entry));
        } else {
            gtk_widget_destroy(password_dialog);
            return;
        }

        gtk_widget_destroy(password_dialog);
    }

    // export account
    auto success = priv->accountModel_->exportToFile(priv->accountId, filename, password);
    std::string label = success? _("Account exported!") : _("Export account failure.");
    gtk_button_set_label(GTK_BUTTON(priv->button_export_account), label.c_str());
    g_free(filename);

    if (success) {
        g_signal_emit(G_OBJECT(view), account_creation_wizard_signals[ACCOUNT_CREATION_COMPLETED], 0);
    }
}

static void
build_creation_wizard_view(AccountCreationWizard *view)
{
    g_return_if_fail(IS_ACCOUNT_CREATION_WIZARD(view));
    auto* priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(view);
aviau's avatar
aviau committed
821 822 823

    /* set ring logo */
    GError *error = NULL;
824
    GdkPixbuf* logo_ring = gdk_pixbuf_new_from_resource_at_scale("/net/jami/JamiGnome/jami-logo-blue",
aviau's avatar
aviau committed
825 826 827 828 829 830 831
                                                                  -1, 50, TRUE, &error);
    if (logo_ring == NULL) {
        g_debug("Could not load logo: %s", error->message);
        g_clear_error(&error);
    } else
        gtk_image_set_from_pixbuf(GTK_IMAGE(priv->choose_account_type_ring_logo), logo_ring);

832
    /* create the username_registration_box */
833
    priv->username_registration_box = username_registration_box_new_empty(false);
834
    gtk_box_pack_end(GTK_BOX(priv->box_username_entry), GTK_WIDGET(priv->username_registration_box), false, false, 0);
835
    gtk_widget_show(priv->username_registration_box);
836
    priv->entry_username = GTK_WIDGET(
837 838 839 840
        username_registration_box_get_entry(
            USERNAME_REGISTRATION_BOX(priv->username_registration_box)
        )
    );
aviau's avatar
aviau committed
841 842 843 844 845 846 847 848 849

    /* use the real name / username of the logged in user as the default */
    const char* real_name = g_get_real_name();
    const char* user_name = g_get_user_name();
    g_debug("real_name = %s",real_name);
    g_debug("user_name = %s",user_name);

    /* check first if the real name was determined */
    if (g_strcmp0 (real_name,"Unknown") != 0)
850
        gtk_entry_set_text(GTK_ENTRY(priv->entry_display_name), real_name);
aviau's avatar
aviau committed
851
    else
852 853
        gtk_entry_set_text(GTK_ENTRY(priv->entry_display_name), user_name);

aviau's avatar
aviau committed
854
    /* choose_account_type signals */
855
    g_signal_connect_swapped(priv->button_new_account, "clicked", G_CALLBACK(account_creation_wizard_show_preview), view);
856 857
    g_signal_connect_swapped(priv->button_import_from_device, "clicked", G_CALLBACK(show_import_from_device), view);
    g_signal_connect_swapped(priv->button_import_from_backup, "clicked", G_CALLBACK(show_import_from_backup), view);
858
    g_signal_connect(priv->button_show_advanced, "clicked", G_CALLBACK(show_advanced), view);
859
    g_signal_connect_swapped(priv->button_connect_account_manager, "clicked", G_CALLBACK(show_connect_account_manager), view);
860
    g_signal_connect(priv->button_new_sip_account, "clicked", G_CALLBACK(create_new_sip_account), view);
aviau's avatar
aviau committed
861 862

    /* account_creation signals */
863
    g_signal_connect_swapped(priv->entry_username, "changed", G_CALLBACK(entries_new_account_changed), view);
aviau's avatar
aviau committed
864
    g_signal_connect(priv->button_account_creation_next, "clicked", G_CALLBACK(account_creation_next_clicked), view);
865
    g_signal_connect(priv->button_account_creation_previous, "clicked", G_CALLBACK(account_creation_previous_clicked), view);
866 867
    g_signal_connect_swapped(priv->entry_password, "changed", G_CALLBACK(entries_new_account_changed), view);
    g_signal_connect_swapped(priv->entry_password_confirm, "changed", G_CALLBACK(entries_new_account_changed), view);
868
    g_signal_connect_swapped(priv->entry_display_name, "changed", G_CALLBACK(entries_new_account_changed), view);
869
    g_signal_connect(priv->switch_register, "notify::active", G_CALLBACK(sign_up_blockchain_switched), view);
870
    g_signal_connect_swapped(priv->username_registration_box, "username-availability-changed", G_CALLBACK(username_availability_changed), view);
aviau's avatar
aviau committed
871

872
    /* existing_account signals */
873 874 875
    g_signal_connect_swapped(priv->button_import_from_previous, "clicked", G_CALLBACK(show_choose_account_type), view);
    g_signal_connect_swapped(priv->button_pin_info, "clicked", G_CALLBACK(show_pin_label), view);
    g_signal_connect_swapped(priv->button_import_from_next, "clicked", G_CALLBACK(existing_account_next_clicked), view);
aviau's avatar
aviau committed
876
    g_signal_connect(priv->entry_existing_account_pin, "changed", G_CALLBACK(entries_existing_account_changed), view);
877
    g_signal_connect(priv->entry_existing_account_archive, "file-set", G_CALLBACK(entries_existing_account_changed), view);
aviau's avatar
aviau committed
878 879
    g_signal_connect(priv->entry_existing_account_password, "changed", G_CALLBACK(entries_existing_account_changed), view);

880 881 882 883 884
    /* Backup */
    g_signal_connect_swapped(priv->button_export_account, "clicked", G_CALLBACK(choose_export_file), view);
    g_signal_connect_swapped(priv->button_skip_backup, "clicked", G_CALLBACK(skip_backup_clicked), view);
    g_signal_connect_swapped(priv->button_backup_info, "clicked", G_CALLBACK(show_backup_label), view);

aviau's avatar
aviau committed
885
    /* error_view signals */
886
    g_signal_connect_swapped(priv->button_error_view_ok, "clicked", G_CALLBACK(error_ok_clicked), view);
887

888 889 890 891 892 893 894

    /* Connect to account_manager */
    g_signal_connect_swapped(priv->entry_account_manager_username, "changed", G_CALLBACK(entries_connect_account_manager_changed), view);
    g_signal_connect_swapped(priv->entry_account_manager_password, "changed", G_CALLBACK(entries_connect_account_manager_changed), view);
    g_signal_connect_swapped(priv->entry_account_manager_uri, "changed", G_CALLBACK(entries_connect_account_manager_changed), view);
    g_signal_connect(priv->button_account_manager_connect_previous, "clicked", G_CALLBACK(connect_account_manager_previous_clicked), view);
    g_signal_connect(priv->button_account_manager_connect_next, "clicked", G_CALLBACK(connect_account_manager_next_clicked), view);
aviau's avatar
aviau committed
895 896

    show_choose_account_type(view);
897

898 899
    gtk_button_set_relief(GTK_BUTTON(priv->button_show_advanced), GTK_RELIEF_NONE);

900 901 902
    auto provider = gtk_css_provider_new();
    gtk_css_provider_load_from_data(provider,
        ".black { color: grey; font-size: 0.8em; }\
903 904
        .transparent-button { margin-left: 10px; border: 0; background-color: rgba(0,0,0,0); margin-right: 0; padding-right: 0;}\
        .infos-button { margin: 0; border: 0; background-color: rgba(0,0,0,0); padding: 0; box-shadow: 0;}",
905 906 907 908 909
        -1, nullptr
    );
    gtk_style_context_add_provider_for_screen(gdk_display_get_default_screen(gdk_display_get_default()),
                                              GTK_STYLE_PROVIDER(provider),
                                              GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
aviau's avatar
aviau committed
910 911 912
}

GtkWidget *
913
account_creation_wizard_new(lrc::api::AVModel& avModel, lrc::api::NewAccountModel& accountModel)
aviau's avatar
aviau committed
914 915 916
{
    gpointer view = g_object_new(ACCOUNT_CREATION_WIZARD_TYPE, NULL);

917 918
    auto* priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(view);
    priv->avModel_ = &avModel;
919
    priv->accountModel_ = &accountModel;
920

921
    build_creation_wizard_view(ACCOUNT_CREATION_WIZARD(view));
aviau's avatar
aviau committed
922 923
    return (GtkWidget *)view;
}
924 925 926 927

void
account_creation_wizard_show_preview(AccountCreationWizard *win, gboolean show_preview)
{
928
    auto* priv = ACCOUNT_CREATION_WIZARD_GET_PRIVATE(win);
929

930 931 932 933 934 935
    if (priv->account_creation) {
        if (show_preview)
            gtk_widget_show(priv->account_creation);
        else
            gtk_widget_hide(priv->account_creation);
    }
936
    priv->mode = Mode::ADD_LOCAL;
937 938

    /* Similarily to general settings view, we construct and destroy the avatar manipulation widget
939 940 941
       each time the profile is made visible / hidden. While not the most elegant solution, this
       allows us to run the preview if and only if it is displayed, and always stop it when hidden. */
    if (show_preview && !priv->avatar_manipulation) {
942
        priv->avatar_manipulation = avatar_manipulation_new_from_wizard(priv->avModel_);
943 944 945 946 947 948 949 950 951
        gtk_box_pack_start(GTK_BOX(priv->box_avatarselection), priv->avatar_manipulation, true, true, 0);
        gtk_stack_set_visible_child(GTK_STACK(priv->stack_account_creation), priv->account_creation);
    } else if (priv->avatar_manipulation) {
        /* make sure the AvatarManipulation widget is destroyed so the VideoWidget inside of it is too;
         * NOTE: destorying its parent (box_avatarselection) first will cause a mystery 'BadDrawable'
         * crash due to X error */
        gtk_container_remove(GTK_CONTAINER(priv->box_avatarselection), priv->avatar_manipulation);
        priv->avatar_manipulation = nullptr;
    }
952
}