Skip to content

Commit

Permalink
restore panel state between different invocations
Browse files Browse the repository at this point in the history
  • Loading branch information
mhammond committed Dec 6, 2011
1 parent 08f48dd commit e1421a7
Show file tree
Hide file tree
Showing 7 changed files with 240 additions and 56 deletions.
50 changes: 31 additions & 19 deletions data/ui/share/index.js
Expand Up @@ -47,7 +47,6 @@ function (require, $, object, fn,
AddAccount, less, osTheme, mediator) {

var accountPanels = {},
accountPanelsRestoreState = {},
SHARE_DONE = 0,
SHARE_START = 1,
SHARE_ERROR = 2,
Expand All @@ -56,7 +55,7 @@ function (require, $, object, fn,
statusSharing: true,
statusShared: true
},
options, sendData, tabButtonsDom,
activity, sendData, tabButtonsDom,
servicePanelsDom,
owaservices = [], // A list of OWA service objects
owaservicesbyid = {}; // A map version of the above
Expand Down Expand Up @@ -128,8 +127,8 @@ function (require, $, object, fn,

function showStatusShared() {
var svcRec = owaservicesbyid[sendData.appid],
siteName = options.siteName,
url = options.url || "",
siteName = activity.data.siteName,
url = activity.data.url || "",
doubleSlashIndex = url.indexOf("//") + 2;
$('#statusShared').empty().append(jig('#sharedTemplate', {
domain: siteName || url.slice(doubleSlashIndex, url.indexOf("/", doubleSlashIndex)),
Expand Down Expand Up @@ -300,7 +299,7 @@ function (require, $, object, fn,
tabButtonsDom = $('.widgets-TabButton');
servicePanelsDom = $('.servicePanel');

mediator.checkBase64Preview(options);
mediator.checkBase64Preview(activity.data);

//If no matching accounts match the last selection clear it.
if (lastSelectionMatch < 0 && lastSelection) {
Expand Down Expand Up @@ -337,18 +336,19 @@ function (require, $, object, fn,
/// XXX - need the OWA icon helper!!
var icon = thisSvc.getIconForSize(48); // XXX - what size should really be used???
// Add a tab button for the service.
tabsDom.append(new TabButton({
var tabButton = new TabButton({
target: tabId,
type: appid,
title: thisSvc.app.manifest.name,
serviceIcon: icon
}, tabFragment));
}, tabFragment);
tabButton.node.setAttribute("appid", appid);
tabsDom.append(tabButton);

// Get the contructor function for the panel.
accountPanel = new ServicePanel({
options: options,
owaservice: thisSvc,
savedState: accountPanelsRestoreState[appid]
activity: activity,
owaservice: thisSvc
}, fragment);

accountPanel.node.setAttribute("id", tabId);
Expand All @@ -357,7 +357,6 @@ function (require, $, object, fn,
}
});
finishCreate();
accountPanelsRestoreState = {};
}

// Set up initialization work for the first share state passing.
Expand Down Expand Up @@ -499,7 +498,6 @@ function (require, $, object, fn,
$("#tabContent").empty();
for (var appid in accountPanels) {
var panel = accountPanels[appid];
accountPanelsRestoreState[appid] = panel.getRestoreState();
panel.destroy();
}
accountPanels = {};
Expand All @@ -510,6 +508,7 @@ function (require, $, object, fn,
// since the this call could happen before AccountPanels are ready, which
// also listen for base64Preview.
function onBase64Preview(img) {
var options = activity.data;
if (options) {
var preview = options.previews && options.previews[0];
if (preview && preview.http_url == img.url) {
Expand All @@ -523,9 +522,9 @@ function (require, $, object, fn,

// tell OWA we are ready...
window.navigator.mozActivities.mediation.ready(
function configureServices(activity, services) {
function configureServices(_activity, services) {
_deleteOldServices();
options = activity.data;
activity = _activity;
owaservices = services;
onFirstShareState();
displayAccounts();
Expand Down Expand Up @@ -553,11 +552,24 @@ function (require, $, object, fn,
}.bind(svc));
}
},
function updateActivity(activity) {
options = activity.data;
// force a refresh of the options....
dispatch.pub('optionsChanged', options);
mediator.checkBase64Preview(options);
function updateActivity(_activity) {
activity = _activity;
// reselect whatever app was in use.
if (activity.mediatorState && activity.mediatorState.selectedApp) {
$('#tabs').find('[appid="' + activity.mediatorState.selectedApp + '"]').click();
}
// force a refresh of the activity data....
dispatch.pub('activityChanged', activity);
mediator.checkBase64Preview(activity.data);
},
function fetchState() {
var appstate = {};
for (var appid in accountPanels) {
var panel = accountPanels[appid];
appstate[appid] = panel.getRestoreState();
}
var selectedApp = $('.servicePanel').not('.hidden').attr('appid');
return {apps: appstate, selectedApp: selectedApp};
}
);
});
60 changes: 39 additions & 21 deletions data/ui/share/scripts/widgets/AccountPanel.js
Expand Up @@ -71,10 +71,10 @@ function (object, Widget, $, template,
onCreate: function (onAsynCreateDone) {
var profile = this.owaservice.user;

this.hadFocusRequest = false;
this.profile = profile;
this.parameters = this.owaservice.parameters;
this.svc = this.parameters; // just for the jig template...
this.options = this.activity.data; // just for the jig template...

//Set up the photo property
this.photo = profile.photos && profile.photos[0] && profile.photos[0].value;
Expand All @@ -92,16 +92,13 @@ function (object, Widget, $, template,
mediator.on('base64Preview', this.base64PreviewSub);

//Listen for options changes and update the account.
this.optionsChangedSub = dispatch.sub('optionsChanged', fn.bind(this, function (options) {
this.options = options;
this.optionsChanged();
}));
this.activityChangedSub = dispatch.sub('activityChanged', this.activityChanged.bind(this));
},

destroy: function () {
mediator.removeListener('base64Preview', this.base64PreviewSub);
dispatch.unsub(this.sendCompleteSub);
dispatch.unsub(this.optionsChangedSub);
dispatch.unsub(this.activityChangedSub);
if (this.select) {
this.select.dom.unbind('change', this.selectChangeFunc);
delete this.selectChangeFunc;
Expand Down Expand Up @@ -137,6 +134,29 @@ function (object, Widget, $, template,
}
},

activityChanged: function(activity) {
var appid = this.owaservice.app.origin;
var opts = activity.data;
var savedState = activity.mediatorState && activity.mediatorState.apps ?
activity.mediatorState.apps[appid] : null;

this.hadFocusRequest = false;
this.doneFirstRender = false;
if (savedState) {
this.doneFirstRender = savedState.doneFirstRender;
this.hadFocusRequest = savedState.hadFocusRequest;

// Mix in any saved UI data from the last time we were invoked.
var tomixin =['to', 'subject', 'message', 'shareType', 'description', 'title'];
for each (var prop in tomixin) {
opts[prop] = savedState.ui[prop];
}
}
this.activity = activity;
this.options = opts;
this.renderData();
},

onRender: function () {
// Note an exception in _onRender will cause the widget creation
// process to hang and never return - so catch and log exceptions.
Expand All @@ -156,18 +176,7 @@ function (object, Widget, $, template,
this.toDom = $('[name="to"]', this.node);
this.shareButtonNode = $('button.share', this.node)[0];

//Mix in any saved data for the new URL if it was in storage.
if (this.savedState) {
//Create a temp object so we do not mess with pristine options.
opts = object.create(opts, [{
to: this.savedState.to,
subject: this.savedState.subject,
message: this.savedState.message,
shareType: this.savedState.shareType
}]);
}

this.optionsChanged();
this.activityChanged(this.activity);

var shareTypes = this.parameters.shareTypes;
if (shareTypes.length > 1) {
Expand Down Expand Up @@ -216,7 +225,7 @@ function (object, Widget, $, template,

},

optionsChanged: function() {
renderData: function() {
var root = $(this.node),
opts = this.options,
formLink = opts.url,
Expand All @@ -233,6 +242,7 @@ function (object, Widget, $, template,
if (this.parameters.features) {
if (this.parameters.features.title) {
root.find('[name="title"]').val(opts.title);
root.find('[name="subject"]').val(opts.subject);
} else if (this.parameters.features.subjectLabel) {
if (opts.subject) {
root.find('[name="subject"]').val(opts.subject);
Expand All @@ -248,7 +258,7 @@ function (object, Widget, $, template,
this.toDom.val(opts.to);
var message = opts.message || '';
var constraints = this.parameters.constraints || {};
if (constraints.editableURLInMessage) {
if (!this.doneFirstRender && constraints.editableURLInMessage) {
// so we need some URL in the message itself - if the service doesn't
// do its own shortening we prefer a short url if we already have one.
var url;
Expand All @@ -264,6 +274,10 @@ function (object, Widget, $, template,
}
}
root.find('[name="message"]').val(message);
if (this.counter) {
this.counter.checkCount();
}
this.doneFirstRender = true;
},

validate: function (sendData) {
Expand Down Expand Up @@ -370,7 +384,11 @@ function (object, Widget, $, template,
},

getRestoreState: function () {
return this.getFormData();
return {
doneFirstRender: this.doneFirstRender,
hadFocusRequest: this.hadFocusRequest,
ui: this.getFormData()
};
},

getFormData: function () {
Expand Down
5 changes: 2 additions & 3 deletions data/ui/share/scripts/widgets/ServicePanel.js
Expand Up @@ -136,9 +136,8 @@ function (object, Widget, $, template,
// XXX - overlay??
var PanelCtor = require('widgets/AccountPanel');
this.accountPanel = new PanelCtor({
options: this.options,
owaservice: this.owaservice,
savedState: this.savedState
activity: this.activity,
owaservice: this.owaservice
}, thisPanelDiv[0]);
}
thisPanelDiv.show();
Expand Down
22 changes: 17 additions & 5 deletions lib/panel.js
Expand Up @@ -237,12 +237,14 @@ SharePanel.prototype = {
return optBuilder.getOptions(contentargs);
},

_panelShown: function() {
onPanelShown: function() {
this.anchor.setAttribute("checked", true);
MediatorPanel.prototype.onPanelShown.apply(this);
},

_panelHidden: function() {
onPanelHidden: function() {
this.anchor.removeAttribute("checked");
MediatorPanel.prototype.onPanelHidden.apply(this);
},

attachHandlers: function() {
Expand Down Expand Up @@ -499,7 +501,7 @@ PageOptionsBuilder.prototype = {
},

getVideoSourceURLHacks: function() {
let canonical = this.getCanonicalURL(), host = this.gBrowser.currentURI.host, params, embeds, i, src, flashvars, value, url;
let canonical = this.getCanonicalURL(), host = this.currentHost, params, embeds, i, src, flashvars, value, url;

// YouTube hack to get the right source without too many parameters
if (host.indexOf("youtube.com") >= 0 && canonical.match(/v=([A-Za-z0-9._%\-]*)[&\w;=\+_\-]*/)) {
Expand Down Expand Up @@ -596,13 +598,23 @@ PageOptionsBuilder.prototype = {
// work but currently don't provide the right kind of meta data
getCanonicalURLHacks: function() {
// Google Maps Hack :( obviously this regex isn't robust
if (/^maps\.google\.[a-zA-Z]{2,5}/.test(this.gBrowser.currentURI.host)) {
return this._validURL(this.gBrowser.contentDocument.getElementById("link").getAttribute("href"));
let host = this.currentHost;
if (host && /^maps\.google\.[a-zA-Z]{2,5}/.test(host)) {
return this._validURL(this.gBrowser.contentDocument.getElementById("link").getAttribute("href"));
}

return '';
},

get currentHost() {
try {
return this.gBrowser.currentURI.host;
} catch (ex) {
// probably about:blank or similar
return '';
}
},

_validURL: function(url) {
// hacky validation of a url to make sure it at least appears valid
return validateURL(this.gBrowser.currentURI.resolve(url));
Expand Down
25 changes: 20 additions & 5 deletions tests/app_helpers.js
Expand Up @@ -75,6 +75,15 @@ exports.ensureNoTestApp = function(test, appPath, callback) {
function() {callback()}, function() {callback()});
}

function maybeInstallTestApp(test, appPath, skipInstall, callback) {
if (skipInstall) {
let options = getTestAppOptions(appPath);
callback(options.origin);
} else {
exports.installTestApp(test, appPath, callback);
}
}

// Helpers for working with our "test app".

// Install our test app, open a URL in a new tab, open the "share panel" for
Expand All @@ -86,7 +95,9 @@ exports.getMediatorWithApp = function(test, args, cb) {
let appPath = args.appPath || "apps/basic/basic.webapp";
let pageUrl = args.pageUrl || getTestUrl("page.html");
let shareArgs = args.shareArgs;
exports.installTestApp(test, appPath, function(appOrigin) {
let skipAppInstall = args.skipAppInstall;
let tabTitle = args.tabTitle;
maybeInstallTestApp(test, appPath, skipAppInstall, function(appOrigin) {
// ensure a teardown method to unregister it!
finalize(test, function(finish) {
exports.ensureNoTestApp(test, appPath, function() {
Expand All @@ -95,17 +106,20 @@ exports.getMediatorWithApp = function(test, args, cb) {
});

createTab(pageUrl, function(tab) {
if (tabTitle) {
tab.title = tabTitle;
}
// a finalizer to destroy the tab.
finalize(test, function(finish) {
removeCurrentTab(function() {
finish();
})
});

let mediator = getMediator(shareArgs);
mediator.panel.port.once("owa.mediation.ready", function() {
let mediator = getMediator(shareArgs, function(mediator) {
//// The mediator reported it is ready - now find the contentWindow for the mediator.
test.waitUntil(function() {return mediator.panelWindow && mediator.handlers[appOrigin]; }
test.waitUntil(function() {
return mediator.panelWindow && mediator.handlers[appOrigin]; }
).then(function() {
// loop over the iframes looking for or test app skipping any other
// link.send apps which may exist.
Expand All @@ -125,7 +139,8 @@ exports.getMediatorWithApp = function(test, args, cb) {
jqPanelContentWindow: cw.$,
appFrame: appFrame,
appWidget: appWidget,
jqAppWidget: jqAppWidget
jqAppWidget: jqAppWidget,
tab: tab
};
cb(result);
return;
Expand Down

0 comments on commit e1421a7

Please sign in to comment.