Bug 1581555 - Allow dynamic location switching in the Touch Bar. r=spohl,mikedeboer

Differential Revision: https://phabricator.services.mozilla.com/D58463

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Harry Twyford 2020-01-06 18:03:21 +00:00
parent 03c717bd41
commit 30f020b398
2 changed files with 36 additions and 19 deletions

View File

@ -237,6 +237,11 @@ const kBuiltInInputs = {
},
};
// We create a new flat object to cache strings. Since gBuiltInInputs is a
// tree, caching/retrieval of localized strings would otherwise require tree
// traversal.
var localizedStrings = {};
const kHelperObservers = new Set([
"bookmark-icon-updated",
"reader-mode-available",
@ -303,8 +308,6 @@ class TouchBarHelper {
// icons) are loaded. We keep track of which inputs haven't updated and
// run an update on them after the first location change.
this._inputsNotUpdated = new Set(Object.keys(kBuiltInInputs));
// This is a temporary workaround until bug 1596723 is resolved.
this._inputsNotUpdated.delete("SearchPopover");
return layoutItems;
}
@ -351,8 +354,8 @@ class TouchBarHelper {
// Skip localization if there is already a cached localized title or if
// no title is needed.
if (
kBuiltInInputs[inputName].hasOwnProperty("localTitle") ||
!kBuiltInInputs[inputName].hasOwnProperty("title")
!inputData.hasOwnProperty("title") ||
localizedStrings[inputData.title]
) {
return item;
}
@ -360,7 +363,7 @@ class TouchBarHelper {
// Async l10n fills in the localized input labels after the initial load.
this._l10n.formatValue(item.key).then(result => {
item.title = result;
kBuiltInInputs[inputName].localTitle = result; // Cache result.
localizedStrings[inputData.title] = result; // Cache result.
// Checking TouchBarHelper.window since this callback can fire after all windows are closed.
if (TouchBarHelper.window) {
if (this._inputsNotUpdated) {
@ -475,12 +478,16 @@ class TouchBarHelper {
);
break;
case "intl:app-locales-changed":
// On locale change, refresh all inputs after loading new localTitle.
this._searchPopover = null;
for (let input in kBuiltInInputs) {
delete input.localTitle;
}
this._updateTouchBarInputs(...kBuiltInInputs.keys());
localizedStrings = {};
// This event can fire before this._l10n updates to switch languages,
// so all the new translations are in the old language. To avoid this,
// we need to reinitialize this._l10n.
this._l10n = new Localization(["browser/touchbar/touchbar.ftl"]);
helperProto._l10n = this._l10n;
this._updateTouchBarInputs(...Object.keys(kBuiltInInputs));
break;
case "quit-application":
this.destructor();
@ -523,7 +530,7 @@ helperProto._l10n = new Localization(["browser/touchbar/touchbar.ftl"]);
class TouchBarInput {
constructor(input) {
this._key = input.key || input.title;
this._title = input.hasOwnProperty("localTitle") ? input.localTitle : "";
this._title = localizedStrings[this._key] || "";
this._image = input.image;
this._type = input.type;
this._callback = input.callback;
@ -544,7 +551,7 @@ class TouchBarInput {
initializedChild.type = input.type + "-" + initializedChild.type;
this._children.push(initializedChild);
// Skip l10n for inputs without a title or those already localized.
if (childData.title && childData.title != "") {
if (childData.title && !localizedStrings[childData.title]) {
toLocalize.push(initializedChild);
}
}
@ -606,9 +613,14 @@ class TouchBarInput {
/**
* Apply Fluent l10n to child inputs.
* @param {Array} children An array of initialized TouchBarInputs.
* @param {Array} children
* An array of initialized TouchBarInputs.
*/
async _localizeChildren(children) {
if (!children || !children.length) {
return;
}
let titles = await helperProto._l10n.formatValues(
children.map(child => ({ id: child.key }))
);
@ -617,7 +629,9 @@ class TouchBarInput {
// results in titles match up with the inputs to be localized.
children.forEach(function(child, index) {
child.title = titles[index];
localizedStrings[child.key] = child.title;
});
gTouchBarUpdater.updateTouchBarInputs(TouchBarHelper.baseWindow, children);
}
}

View File

@ -217,15 +217,12 @@ static const uint32_t kInputIconSize = 16;
NSTouchBarItem* item = [self itemForIdentifier:[aInput nativeIdentifier]];
// Update our canonical copy of the input.
[self replaceMappedLayoutItem:aInput];
// If we can't immediately find item, there are three possibilities:
// * It is a button in a ScrollView, which can't be found with itemForIdentifier; or
// * It is contained within a popover; or
// * It is a button in a ScrollView, or
// * It is contained within a popover, or
// * It simply does not exist.
// We check for each possibility here.
if (!item) {
if (!self.mappedLayoutItems[[aInput nativeIdentifier]]) {
if ([self maybeUpdateScrollViewChild:aInput]) {
return true;
}
@ -235,6 +232,9 @@ static const uint32_t kInputIconSize = 16;
return false;
}
// Update our canonical copy of the input.
[self replaceMappedLayoutItem:aInput];
if ([aInput baseType] == TouchBarInputBaseType::kButton) {
[(NSCustomTouchBarItem*)item setCustomizationLabel:[aInput title]];
[self updateButton:(NSCustomTouchBarItem*)item withIdentifier:[aInput nativeIdentifier]];
@ -247,6 +247,9 @@ static const uint32_t kInputIconSize = 16;
} else if ([aInput baseType] == TouchBarInputBaseType::kPopover) {
[(NSPopoverTouchBarItem*)item setCustomizationLabel:[aInput title]];
[self updatePopover:(NSPopoverTouchBarItem*)item withIdentifier:[aInput nativeIdentifier]];
for (TouchBarInput* child in [aInput children]) {
[(nsTouchBar*)[(NSPopoverTouchBarItem*)item popoverTouchBar] updateItem:child];
}
} else if ([aInput baseType] == TouchBarInputBaseType::kLabel) {
[self updateLabel:(NSTextField*)item.view withIdentifier:[aInput nativeIdentifier]];
}