Commit 9f234866 authored by calamity's avatar calamity Committed by Commit bot

[MD History] Add search for synced devices.

This CL implements a simple search that matches the functionality of the
original history page.

This CL also fixes a bug related to window separators in the synced view
that could cause excess window separators to appear.

BUG=610934
CQ_INCLUDE_TRYBOTS=tryserver.chromium.linux:closure_compilation

Review-Url: https://codereview.chromium.org/2022003002
Cr-Commit-Position: refs/heads/master@{#398252}
parent 7b3867c7
......@@ -67,7 +67,8 @@
</template>
<template is="dom-if" if="[[syncedTabsSelected_(selectedPage_)]]">
<history-synced-device-manager id="history-synced-device-manager"
session-list="[[queryState_.sessionList]]">
session-list="[[queryState_.sessionList]]"
searched-term=[[queryState_.info.term]]>
</history-synced-device-manager>
</template>
</iron-pages>
......
......@@ -69,6 +69,8 @@ cr.define('md_history', function() {
* occurrences of the search term in bold.
* @private
*/
// TODO(calamity): Pull this bolding behavior into a separate element for
// synced device search.
setSearchedTextToBold_: function() {
var i = 0;
var titleElem = this.$.title;
......
......@@ -93,9 +93,9 @@
[[tab.title]]
</a>
</div>
<template is="dom-if" if="[[tab.needsWindowSeparator]]">
<div id="window-separator"></div>
</template>
<div id="window-separator"
hidden$="[[!isWindowSeparatorIndex_(index, separatorIndexes)]]">
</div>
</template>
<div class="item-container">
<p on-tap="openAllTabs_" id="open-tabs">$i18n{openAll}</p>
......
......@@ -7,16 +7,10 @@ Polymer({
properties: {
// Name of the synced device.
device: {
type: String,
value: ''
},
device: {type: String, value: ''},
// When the device information was last updated.
lastUpdateTime: {
type: String,
value: ''
},
lastUpdateTime: {type: String, value: ''},
/**
* The list of tabs open for this device.
......@@ -28,11 +22,16 @@ Polymer({
observer: 'updateIcons_'
},
/**
* The indexes where a window separator should be shown. The use of a
* separate array here is necessary for window separators to appear
* correctly in search. See http://crrev.com/2022003002 for more details.
* @type {!Array<number>}
*/
separatorIndexes: Array,
// Whether the card is open.
cardOpen_: {
type: Boolean,
value: true
},
cardOpen_: {type: Boolean, value: true},
},
/**
......@@ -68,5 +67,10 @@ Polymer({
cr.icon.getFaviconImageSet(this.tabs[i].url);
}
});
},
/** @private */
isWindowSeparatorIndex_: function(index, separatorIndexes) {
return this.separatorIndexes.indexOf(index) != -1;
}
});
......@@ -18,7 +18,8 @@
<template is="dom-repeat" items="[[syncedDevices_]]" as="syncedDevice">
<history-synced-device-card device="[[syncedDevice.device]]"
last-update-time="[[syncedDevice.lastUpdateTime]]"
tabs="[[syncedDevice.tabs]]">
tabs="[[syncedDevice.tabs]]"
separator-indexes="[[syncedDevice.separatorIndexes]]">
</history-synced-device-card>
</template>
</template>
......
......@@ -5,6 +5,7 @@
/**
* @typedef {{device: string,
* lastUpdateTime: string,
* separatorIndexes: !Array<number>,
* timestamp: number,
* tabs: !Array<!ForeignSessionTab>,
* tag: string}}
......@@ -20,7 +21,12 @@ Polymer({
*/
sessionList: {
type: Array,
observer: 'setSyncedHistory',
observer: 'updateSyncedDevices'
},
searchedTerm: {
type: String,
observer: 'searchTermChanged'
},
/**
......@@ -39,20 +45,39 @@ Polymer({
*/
createInternalDevice_: function(session) {
var tabs = [];
for (var j = 0; j < session.windows.length; j++) {
var newTabs = session.windows[j].tabs;
var separatorIndexes = [];
for (var i = 0; i < session.windows.length; i++) {
var newTabs = session.windows[i].tabs;
if (newTabs.length == 0)
continue;
tabs = tabs.concat(newTabs);
tabs[tabs.length - 1].needsWindowSeparator = true;
if (!this.searchedTerm) {
// Add all the tabs if there is no search term.
tabs = tabs.concat(newTabs);
separatorIndexes.push(tabs.length - 1);
} else {
var searchText = this.searchedTerm.toLowerCase();
var windowAdded = false;
for (var j = 0; j < newTabs.length; j++) {
var tab = newTabs[j];
if (tab.title.toLowerCase().indexOf(searchText) != -1) {
tabs.push(tab);
windowAdded = true;
}
}
if (windowAdded)
separatorIndexes.push(tabs.length - 1);
}
}
return {
device: session.name,
lastUpdateTime: '' + session.modifiedTime,
separatorIndexes: separatorIndexes,
timestamp: session.timestamp,
tabs: tabs,
tag: session.tag
tag: session.tag,
};
},
......@@ -62,9 +87,9 @@ Polymer({
* avoid doing extra work in this case. The logic could be more intelligent
* about updating individual tabs rather than replacing whole sessions, but
* this approach seems to have acceptable performance.
* @param {!Array<!ForeignSession>} sessionList
* @param {?Array<!ForeignSession>} sessionList
*/
setSyncedHistory: function(sessionList) {
updateSyncedDevices: function(sessionList) {
if (!sessionList)
return;
......@@ -83,5 +108,10 @@ Polymer({
for (var i = updateCount; i < sessionList.length; i++) {
this.push('syncedDevices_', this.createInternalDevice_(sessionList[i]));
}
},
searchTermChanged: function(searchedTerm) {
this.syncedDevices_ = [];
this.updateSyncedDevices(this.sessionList);
}
});
......@@ -31,6 +31,16 @@ cr.define('md_history.history_synced_tabs_test', function() {
var app;
var element;
var numWindowSeparators = function(card) {
return Polymer.dom(card.root).
querySelectorAll(':not([hidden])#window-separator').length;
};
var getCards = function() {
return Polymer.dom(element.root).
querySelectorAll('history-synced-device-card');
}
suiteSetup(function() {
app = $('history-app');
// Not rendered until selected.
......@@ -65,7 +75,7 @@ cr.define('md_history.history_synced_tabs_test', function() {
[createWindow(['http://www.google.com', 'http://example.com'])]
),
createSession(
'Nexus 5',
'Nexus 6',
[
createWindow(['http://test.com']),
createWindow(['http://www.gmail.com', 'http://badssl.com'])
......@@ -75,19 +85,12 @@ cr.define('md_history.history_synced_tabs_test', function() {
setForeignSessions(sessionList, true);
return flush().then(function() {
var cards = Polymer.dom(element.root)
.querySelectorAll('history-synced-device-card');
var cards = getCards();
assertEquals(2, cards.length);
// Ensure separators between windows are added appropriately.
assertEquals(
1, Polymer.dom(cards[0].root)
.querySelectorAll('#window-separator')
.length);
assertEquals(
2, Polymer.dom(cards[1].root)
.querySelectorAll('#window-separator')
.length);
assertEquals(1, numWindowSeparators(cards[0]));
assertEquals(2, numWindowSeparators(cards[1]));
});
});
......@@ -114,15 +117,11 @@ cr.define('md_history.history_synced_tabs_test', function() {
return flush();
}).then(function() {
// There should only be two cards.
var cards = Polymer.dom(element.root)
.querySelectorAll('history-synced-device-card');
var cards = getCards();
assertEquals(2, cards.length);
// There are now 2 windows in the first device.
assertEquals(
2, Polymer.dom(cards[0].root)
.querySelectorAll('#window-separator')
.length);
assertEquals(2, numWindowSeparators(cards[0]));
// Check that the actual link changes.
assertEquals(
......@@ -133,8 +132,50 @@ cr.define('md_history.history_synced_tabs_test', function() {
});
});
test('two cards, multiple windows, search', function() {
var sessionList = [
createSession(
'Nexus 5',
[createWindow(['http://www.google.com', 'http://example.com'])]
),
createSession(
'Nexus 6',
[
createWindow(['http://www.gmail.com', 'http://badssl.com']),
createWindow(['http://test.com']),
createWindow(['http://www.gmail.com', 'http://bagssl.com'])
]
),
];
setForeignSessions(sessionList, true);
return flush().then(function() {
var cards = getCards();
assertEquals(2, cards.length);
// Ensure separators between windows are added appropriately.
assertEquals(1, numWindowSeparators(cards[0]));
assertEquals(3, numWindowSeparators(cards[1]));
element.searchedTerm = 'g';
return flush();
}).then(function() {
var cards = getCards();
assertEquals(1, numWindowSeparators(cards[0]));
assertEquals(1, cards[0].tabs.length);
assertEquals('http://www.google.com', cards[0].tabs[0].title);
assertEquals(2, numWindowSeparators(cards[1]));
assertEquals(3, cards[1].tabs.length);
assertEquals('http://www.gmail.com', cards[1].tabs[0].title);
assertEquals('http://www.gmail.com', cards[1].tabs[1].title);
assertEquals('http://bagssl.com', cards[1].tabs[2].title);
});
});
teardown(function() {
element.syncedDevices = [];
element.searchedTerm = '';
});
});
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment