Bug 1303008 - refactor Fennec Finder.jsm integration to always show the correct match count results in the findbar. r=nalexander

MozReview-Commit-ID: KZIstsbHAyT

--HG--
extra : rebase_source : 24972d38daa947d62410b43d14f0da6c7662e5da
This commit is contained in:
Mike de Boer 2016-10-10 11:53:25 +02:00
Родитель 114a132b2e
Коммит 05f70d10ef
4 изменённых файлов: 128 добавлений и 77 удалений

Просмотреть файл

@ -67,7 +67,9 @@ public class FindInPageBar extends LinearLayout implements TextWatcher, View.OnC
mStatusText = (TextView) content.findViewById(R.id.find_status);
mInflated = true;
GeckoApp.getEventDispatcher().registerGeckoThreadListener(this, "TextSelection:Data");
GeckoApp.getEventDispatcher().registerGeckoThreadListener(this,
"FindInPage:MatchesCountResult",
"TextSelection:Data");
}
public void show() {
@ -110,7 +112,34 @@ public class FindInPageBar extends LinearLayout implements TextWatcher, View.OnC
if (!mInflated) {
return;
}
GeckoApp.getEventDispatcher().unregisterGeckoThreadListener(this, "TextSelection:Data");
GeckoApp.getEventDispatcher().unregisterGeckoThreadListener(this,
"FindInPage:MatchesCountResult",
"TextSelection:Data");
}
private void onMatchesCountResult(final int total, final int current, final int limit, final String searchString) {
if (total == -1) {
updateResult(Integer.toString(limit) + "+");
} else if (total > 0) {
updateResult(Integer.toString(current) + "/" + Integer.toString(total));
} else if (TextUtils.isEmpty(searchString)) {
updateResult("");
} else {
// We display 0/0, when there were no
// matches found, or if matching has been turned off by setting
// pref accessibility.typeaheadfind.matchesCountLimit to 0.
updateResult("0/0");
}
}
private void updateResult(final String statusText) {
ThreadUtils.postToUiThread(new Runnable() {
@Override
public void run() {
mStatusText.setVisibility(statusText.isEmpty() ? View.GONE : View.VISIBLE);
mStatusText.setText(statusText);
}
});
}
// TextWatcher implementation
@ -160,6 +189,14 @@ public class FindInPageBar extends LinearLayout implements TextWatcher, View.OnC
@Override
public void handleMessage(String event, JSONObject message) {
if (event.equals("FindInPage:MatchesCountResult")) {
onMatchesCountResult(message.optInt("total", 0),
message.optInt("current", 0),
message.optInt("limit", 0),
message.optString("searchString"));
return;
}
if (!event.equals("TextSelection:Data") || !REQUEST_ID.equals(message.optString("requestId"))) {
return;
}
@ -203,21 +240,8 @@ public class FindInPageBar extends LinearLayout implements TextWatcher, View.OnC
GeckoAppShell.sendRequestToGecko(new GeckoRequest(request, searchString) {
@Override
public void onResponse(NativeJSObject nativeJSObject) {
final int total = nativeJSObject.optInt("total", 0);
if (total == -1) {
final int limit = nativeJSObject.optInt("limit", 0);
updateResult(Integer.toString(limit) + "+");
} else if (total > 0) {
final int current = nativeJSObject.optInt("current", 0);
updateResult(Integer.toString(current) + "/" + Integer.toString(total));
} else if (TextUtils.isEmpty(searchString)) {
updateResult("");
} else {
// We display 0/0, when there were no
// matches found, or if matching has been turned off by setting
// pref accessibility.typeaheadfind.matchesCountLimit to 0.
updateResult("0/0");
}
// We don't care about the return value, because `onMatchesCountResult`
// does the heavy lifting.
}
@Override
@ -227,16 +251,6 @@ public class FindInPageBar extends LinearLayout implements TextWatcher, View.OnC
searchString + "]");
updateResult("");
}
private void updateResult(final String statusText) {
ThreadUtils.postToUiThread(new Runnable() {
@Override
public void run() {
mStatusText.setVisibility(statusText.isEmpty() ? View.GONE : View.VISIBLE);
mStatusText.setText(statusText);
}
});
}
});
}
}

Просмотреть файл

@ -9,7 +9,8 @@ var FindHelper = {
_initialViewport: null,
_viewportChanged: false,
_result: null,
_limit: 0,
// Start of nsIObserver implementation.
observe: function(aMessage, aTopic, aData) {
switch(aTopic) {
@ -31,34 +32,25 @@ var FindHelper = {
}
},
/**
* When the FindInPageBar opens/ becomes visible, it's time to:
* 1. Add listeners for other message types sent from the FindInPageBar
* 2. initialize the Finder instance, if necessary.
*/
_findOpened: function() {
try {
this._limit = Services.prefs.getIntPref("accessibility.typeaheadfind.matchesCountLimit");
} catch (e) {
// Pref not available, assume 0, no match counting.
this._limit = 0;
}
Messaging.addListener((data) => {
this.doFind(data);
return this._getMatchesCountResult(data);
}, "FindInPage:Find");
Messaging.addListener((data) => {
this.findAgain(data, false);
return this._getMatchesCountResult(data);
}, "FindInPage:Next");
Messaging.addListener((data) => {
this.findAgain(data, true);
return this._getMatchesCountResult(data);
}, "FindInPage:Prev");
Messaging.addListener(data => this.doFind(data), "FindInPage:Find");
Messaging.addListener(data => this.findAgain(data, false), "FindInPage:Next");
Messaging.addListener(data => this.findAgain(data, true), "FindInPage:Prev");
// Initialize the finder component for the current page by performing a fake find.
this._init();
this._finder.requestMatchesCount("", 1);
this._finder.requestMatchesCount("");
},
/**
* Fetch the Finder instance from the active tabs' browser and start tracking
* the active viewport.
*/
_init: function() {
// If there's no find in progress, start one.
if (this._finder) {
@ -78,6 +70,10 @@ var FindHelper = {
this._viewportChanged = false;
},
/**
* Detach from the Finder instance (so stop listening for messages) and stop
* tracking the active viewport.
*/
_uninit: function() {
// If there's no find in progress, there's nothing to clean up.
if (!this._finder) {
@ -92,6 +88,9 @@ var FindHelper = {
this._viewportChanged = false;
},
/**
* When the FindInPageBar closes, it's time to stop listening for its messages.
*/
_findClosed: function() {
Messaging.removeListener("FindInPage:Find");
Messaging.removeListener("FindInPage:Next");
@ -99,47 +98,86 @@ var FindHelper = {
},
/**
* Request, wait for, and return the current matchesCount results for a string.
* Start an asynchronous find-in-page operation, using the current Finder
* instance and request to count the amount of matches.
* If no Finder instance is currently active, we'll lazily initialize it here.
*
* @param {String} searchString Word to search for in the current document
* @return {Object} Echo of the current find action
*/
_getMatchesCountResult: function(findString) {
// Count matches up to any provided limit.
if (this._limit <= 0) {
return { total: 0, current: 0, limit: 0 };
}
// Sync call to Finder, results available immediately.
this._finder.requestMatchesCount(findString, this._limit);
return this._result;
},
/**
* Pass along the count results to FindInPageBar for display.
*/
onMatchesCountResult: function(result) {
this._result = result;
this._result.limit = this._limit;
},
doFind: function(searchString) {
if (!this._finder) {
this._init();
}
this._finder.fastFind(searchString, false);
return { searchString, findBackwards: false };
},
/**
* Restart the same find-in-page operation as before via `doFind()`. If we
* haven't called `doFind()`, we simply kick off a regular find.
*
* @param {String} searchString Word to search for in the current document
* @param {Boolean} findBackwards Direction to search in
* @return {Object} Echo of the current find action
*/
findAgain: function(searchString, findBackwards) {
// This always happens if the user taps next/previous after re-opening the
// search bar, and not only forces _init() but also an initial fastFind(STRING)
// before any findAgain(DIRECTION).
if (!this._finder) {
this.doFind(searchString);
return;
return this.doFind(searchString);
}
this._finder.findAgain(findBackwards, false, false);
return { searchString, findBackwards };
},
// Start of Finder.jsm listener implementation.
/**
* Pass along the count results to FindInPageBar for display. The result that
* is sent to the FindInPageBar is augmented with the current find-in-page count
* limit.
*
* @param {Object} result Result coming from the Finder instance that contains
* the following properties:
* - {Number} total The total amount of matches found
* - {Number} current The index of current found range
* in the document
*/
onMatchesCountResult: function(result) {
this._result = result;
Messaging.sendRequest(Object.assign({
type: "FindInPage:MatchesCountResult"
}, this._result));
},
/**
* When a find-in-page action finishes, this method is invoked. This is mainly
* used at the moment to detect if the current viewport has changed, which might
* be indicated by not finding a string in the current page.
*
* @param {Object} aData A dictionary, representing the find result, which
* contains the following properties:
* - {String} searchString Word that was searched for
* in the current document
* - {Number} result One of the following
* Ci.nsITypeAheadFind.* result
* indicators: FIND_FOUND,
* FIND_NOTFOUND, FIND_WRAPPED,
* FIND_PENDING
* - {Boolean} findBackwards Whether the search direction
* was backwards
* - {Boolean} findAgain Whether the previous search
* was repeated
* - {Boolean} drawOutline Whether we may (re-)draw the
* outline of a hyperlink
* - {Boolean} linksOnly Whether links-only mode was
* active
*/
onFindResult: function(aData) {
if (aData.result == Ci.nsITypeAheadFind.FIND_NOTFOUND) {
if (this._viewportChanged) {

Просмотреть файл

@ -374,8 +374,6 @@
prefsvc.getIntPref("accessibility.typeaheadfind.timeout");
this._flashFindBar =
prefsvc.getIntPref("accessibility.typeaheadfind.flashBar");
this._matchesCountLimit =
prefsvc.getIntPref("accessibility.typeaheadfind.matchesCountLimit");
this._useModalHighlight = prefsvc.getBoolPref("findbar.modalHighlight");
prefsvc.addObserver("accessibility.typeaheadfind",
@ -1309,9 +1307,9 @@
if (aResult.total !== 0) {
if (aResult.total == -1) {
this._foundMatches.value = this.pluralForm.get(
this._matchesCountLimit,
aResult.limit,
this.strBundle.GetStringFromName("FoundMatchesCountLimit")
).replace("#1", this._matchesCountLimit);
).replace("#1", aResult.limit);
} else {
this._foundMatches.value = this.pluralForm.get(
aResult.total,

Просмотреть файл

@ -394,7 +394,8 @@ Finder.prototype = {
_notifyMatchesCount: function(result = this._currentMatchesCountResult) {
// The `_currentFound` property is only used for internal bookkeeping.
delete result._currentFound;
if (result.total == this.matchesCountLimit)
result.limit = this.matchesCountLimit;
if (result.total == result.limit)
result.total = -1;
for (let l of this._listeners) {