/* -*- Mode: JS2; indent-tabs-mode: nil; js2-basic-offset: 4 -*- */
/* vim: set et ts=4 sw=4: */
/*
* Copyright (c) 2014 Damián Nohales
*
* GNOME Maps 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.
*
* GNOME Maps 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 GNOME Maps; if not, see .
*
* Author: Damián Nohales
*/
const Gio = imports.gi.Gio;
const Gtk = imports.gi.Gtk;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const AccountListBox = imports.accountListBox;
const Application = imports.application;
const CheckIn = imports.checkIn;
const SocialPlaceListBox = imports.socialPlaceListBox;
const SocialPlaceMatcher = imports.socialPlaceMatcher;
const Response = {
SUCCESS: 0,
CANCELLED: 1,
FAILURE_NO_PLACES: 2,
FAILURE_GET_PLACES: 3,
FAILURE_ACCOUNT_DISABLED: 4,
FAILURE_CHECKIN_DISABLED: 5
};
const CheckInDialog = new Lang.Class({
Name: 'CheckInDialog',
Extends: Gtk.Dialog,
Template: 'resource:///org/gnome/Maps/ui/check-in-dialog.ui',
InternalChildren: [ 'cancelButton',
'okButton',
'stack',
'accountFrame',
'placeScrolledWindow',
'placeNotFoundInfoBar',
'placeNotFoundLabel',
'messageInfoLabel',
'messageInfoAccountImage',
'messageTextView',
'facebookOptionsGrid',
'facebookOptionsPrivacyComboBox',
'foursquareOptionsGrid',
'foursquareOptionsPrivacyComboBox',
'foursquareOptionsBroadcastFacebookCheckButton',
'foursquareOptionsBroadcastTwitterCheckButton' ],
_init: function(params) {
this._place = params.place;
delete params.place;
this._matchPlace = params.matchPlace;
delete params.matchPlace;
// This is a construct-only property and cannot be set by GtkBuilder
params.use_header_bar = true;
this.parent(params);
this._account = null;
this._checkIn = new CheckIn.CheckIn();
this.error = null;
this._cancellable = new Gio.Cancellable();
this._cancellable.connect((function() {
this.response(Response.CANCELLED);
}).bind(this));
this.connect('delete-event', (function() {
this._cancellable.cancel();
}).bind(this));
Application.checkInManager.connect('accounts-refreshed', this._onAccountRefreshed.bind(this));
this._initHeaderBar();
this._initWidgets();
},
_initHeaderBar: function() {
this._cancelButton.connect('clicked', (function() {
this._cancellable.cancel();
}).bind(this));
this._okButton.connect('clicked', (function() {
this._startCheckInStep();
}).bind(this));
},
_initWidgets: function() {
// Limitations in Gjs means we can't do this in UI files yet
this._accountListBox = new AccountListBox.AccountListBox({ visible: true });
this._accountFrame.add(this._accountListBox);
this._placeListBox = new SocialPlaceListBox.SocialPlaceListBox({ visible: true });
this._placeScrolledWindow.add(this._placeListBox);
Application.settings.bind('checkin-facebook-privacy',
this._facebookOptionsPrivacyComboBox,
'active_id', Gio.SettingsBindFlags.DEFAULT);
Application.settings.bind('checkin-foursquare-privacy',
this._foursquareOptionsPrivacyComboBox,
'active_id', Gio.SettingsBindFlags.DEFAULT);
Application.settings.bind('checkin-foursquare-broadcast-facebook',
this._foursquareOptionsBroadcastFacebookCheckButton,
'active', Gio.SettingsBindFlags.DEFAULT);
Application.settings.bind('checkin-foursquare-broadcast-twitter',
this._foursquareOptionsBroadcastTwitterCheckButton,
'active', Gio.SettingsBindFlags.DEFAULT);
this._accountListBox.connect('account-selected', (function(list, account) {
this._account = account;
this._startPlaceStep();
}).bind(this));
this._placeListBox.connect('place-selected', (function(list, place) {
this._checkIn.place = place;
this._startMessageStep();
}).bind(this));
},
vfunc_show: function() {
this._startup();
this.parent();
},
_startup: function() {
let accounts = Application.checkInManager.accounts;
if (accounts.length > 1)
this._startAccountStep();
else if (accounts.length === 1) {
this._account = Application.checkInManager.accounts[0];
this._startPlaceStep();
} else {
Mainloop.idle_add((function() {
this.response(Response.FAILURE_CHECKIN_DISABLED);
}).bind(this));
}
},
_onAccountRefreshed: function() {
let accounts = Application.checkInManager.accounts;
if (!Application.checkInManager.hasCheckIn)
this.response(Response.FAILURE_CHECKIN_DISABLED);
else if (this._account) {
for (let i in accounts) {
let account = accounts[i];
if (this._account.get_account().id === accounts[i].get_account().id)
return;
}
this.response(Response.FAILURE_ACCOUNT_DISABLED);
}
},
_startAccountStep: function() {
this.set_title(_("Select an account"));
this._stack.set_visible_child_name('account');
},
_startPlaceStep: function() {
this.set_title(_("Loading"));
this._stack.set_visible_child_name('loading');
Application.checkInManager.findPlaces(this._account,
this._place.location.latitude,
this._place.location.longitude,
100,
this._onFindPlacesFinished.bind(this),
this._cancellable);
},
_onFindPlacesFinished: function(account, places, error) {
if (!error) {
if (places.length === 0) {
this.response(Response.FAILURE_NO_PLACES);
return;
}
let matches = SocialPlaceMatcher.match(this._place, places);
if (matches.exactMatches.length === 1 && this._matchPlace) {
this._checkIn.place = matches.exactMatches[0];
this._startMessageStep();
} else {
this.set_title(_("Select a place"));
this._placeListBox.matches = matches;
if (this._matchPlace) {
if (this._account.get_account().provider_type === 'facebook')
this._placeNotFoundLabel.label = _("Maps cannot find the place to check in to with Facebook. Please select one from this list.");
else if (this._account.get_account().provider_type === 'foursquare')
this._placeNotFoundLabel.label = _("Maps cannot find the place to check in to with Foursquare. Please select one from this list.");
} else
this._placeNotFoundInfoBar.hide();
this._stack.set_visible_child_name('place');
}
} else {
this.error = error;
this.response(Response.FAILURE_GET_PLACES);
}
},
_startMessageStep: function() {
/* Translators: %s is the name of the place to check in.
*/
this.set_title(_("Check in to %s").format(this._checkIn.place.name));
this._stack.set_visible_child_name('message');
this._messageTextView.grab_focus();
this._okButton.show();
let account = this._account.get_account();
/* Translators: %s is the name of the place to check in.
*/
let labelMessageInfo = _("Write an optional message to check in to %s.");
this._messageInfoLabel.label = labelMessageInfo.format('%s'.format(this._checkIn.place.link,
this._checkIn.place.name));
this._messageInfoAccountImage.gicon = Gio.Icon.new_for_string(account.provider_icon);
let optionsGrids = { 'facebook': this._facebookOptionsGrid,
'foursquare': this._foursquareOptionsGrid };
for (let provider in optionsGrids)
if (provider === account.provider_type)
optionsGrids[provider].show();
else
optionsGrids[provider].hide();
},
_startCheckInStep: function() {
this.set_title(_("Loading"));
this._stack.set_visible_child_name('loading');
this._okButton.hide();
let message = this._messageTextView.buffer.text;
let privacy;
if (this._account.get_account().provider_type === 'facebook')
privacy = this._facebookOptionsPrivacyComboBox.active_id;
else if (this._account.get_account().provider_type === 'foursquare')
privacy = this._foursquareOptionsPrivacyComboBox.active_id;
let broadcastFacebook = this._foursquareOptionsBroadcastFacebookCheckButton.active;
let broadcastTwitter = this._foursquareOptionsBroadcastTwitterCheckButton.active;
this._checkIn.message = message;
this._checkIn.privacy = privacy;
this._checkIn.broadcastFacebook = broadcastFacebook;
this._checkIn.broadcastTwitter = broadcastTwitter;
Application.checkInManager.performCheckIn(this._account,
this._checkIn,
this._onPerformCheckInFinished.bind(this),
this._cancellable);
},
_onPerformCheckInFinished: function (account, data, error) {
if (!error)
this.response(Response.SUCCESS);
else {
let messageDialog = new Gtk.MessageDialog({ transient_for: this,
destroy_with_parent: true,
message_type: Gtk.MessageType.ERROR,
buttons: Gtk.ButtonsType.OK,
modal: true,
text: _("An error has occurred"),
secondary_text: error.message });
messageDialog.run();
messageDialog.destroy();
this._startMessageStep();
}
}
});