Skip to content
This repository has been archived by the owner on Dec 11, 2019. It is now read-only.

Add multiple selection for about:history #4607

Merged
merged 1 commit into from
Oct 10, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions app/common/lib/platformUtil.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,11 @@ module.exports.getPlatformStyles = () => {
}

module.exports.isDarwin = () => {
return os.platform() === 'darwin'
return os.platform() === 'darwin' ||
navigator.platform === 'MacIntel'
}

module.exports.isWindows = () => {
return os.platform() === 'win32'
return os.platform() === 'win32' ||
navigator.platform === 'Win32'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for adding these checks in 😄

}
4 changes: 4 additions & 0 deletions app/extensions/brave/locales/en-US/menu.properties
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ editBookmark=Edit Bookmark…
deleteFolder=Delete Folder
deleteBookmark=Delete Bookmark
deleteHistoryEntry=Delete History Entry
deleteHistoryEntries=Delete History Entries
deleteLedgerEntry=Never include this site
stop=Stop
clone=Clone
Expand All @@ -107,10 +108,13 @@ muteTab=Mute Tab
disableTrackingProtection=Disable tracking protection
disableAdBlock=Disable ad block
openInNewTab=Open Link in New Tab
openInNewTabs=Open Links in New Tabs
openAllInTabs=Open all in tabs
openInNewPrivateTab=Open Link in New Private Tab
openInNewPrivateTabs=Open Links in New Private Tabs
openInNewWindow=Open Link in New Window
openInNewSessionTab=Open Link in New Session Tab
openInNewSessionTabs=Open Links in New Session Tabs
copyLinkAddress=Copy Link Address
copyEmailAddress=Copy Email Address
saveLinkAs=Save Link As…
Expand Down
4 changes: 4 additions & 0 deletions app/locale.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,11 @@ var rendererIdentifiers = function () {
'allowFlashAlways',
'openInNewWindow',
'openInNewSessionTab',
'openInNewSessionTabs',
'openInNewPrivateTab',
'openInNewPrivateTabs',
'openInNewTab',
'openInNewTabs',
'openAllInTabs',
'disableAdBlock',
'disableTrackingProtection',
Expand All @@ -51,6 +54,7 @@ var rendererIdentifiers = function () {
'deleteFolder',
'deleteBookmark',
'deleteHistoryEntry',
'deleteHistoryEntries',
'deleteLedgerEntry',
'editFolder',
'editBookmark',
Expand Down
15 changes: 14 additions & 1 deletion js/about/history.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,11 @@ class HistoryDay extends ImmutableComponent {
urlutils.getHostname(entry.get('location'), true)
])}
rowObjects={this.props.entries}
totalRowObjects={this.props.totalEntries}
tableID={this.props.tableID}
columnClassNames={['time', 'title', 'domain']}
addHoverClass
multiSelect
onDoubleClick={this.navigate}
contextMenuName='history'
onContextMenu={aboutActions.contextMenu} />
Expand Down Expand Up @@ -117,13 +120,23 @@ class GroupedHistoryList extends ImmutableComponent {
}
return []
}
totalEntries (local) {
const origin = this.groupEntriesByDay(local)
let result = []
origin.forEach((entry) => {
result.push(entry.entries)
})
return result
}
render () {
const defaultLanguage = this.props.languageCodes.find((lang) => lang.includes(navigator.language)) || 'en-US'
const userLanguage = getSetting(settings.LANGUAGE, this.props.settings)
let index = 0
return <list className='historyList'>
{
this.groupEntriesByDay(userLanguage || defaultLanguage).map((groupedEntry) =>
<HistoryDay date={groupedEntry.date} entries={groupedEntry.entries} />)
<HistoryDay date={groupedEntry.date} entries={groupedEntry.entries}
totalEntries={this.totalEntries(userLanguage || defaultLanguage)} tableID={index++} />)
}
</list>
}
Expand Down
83 changes: 80 additions & 3 deletions js/components/sortableTable.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const React = require('react')
const ImmutableComponent = require('./immutableComponent')
const tableSort = require('tablesort')
const cx = require('../lib/classSet')
const eventUtil = require('../lib/eventUtil')

tableSort.extend('number', (item) => {
return typeof item === 'number'
Expand All @@ -16,9 +17,82 @@ tableSort.extend('number', (item) => {
})

class SortableTable extends ImmutableComponent {
constructor () {
super()
this.onClick = this.onClick.bind(this)
this.onContextMenu = this.onContextMenu.bind(this)
}
componentDidMount (event) {
return tableSort(this.table)
}
onClick (e) {
const targetElement = e.target.parentNode

if (eventUtil.isForSecondaryAction(e)) {
if (targetElement.className.includes(' selected')) {
targetElement.className = targetElement.className.replace(' selected', '')
} else {
targetElement.className += ' ' + 'selected'
}
} else if (e.shiftKey) {
const selected = document.querySelectorAll('.selected')
const targetID = targetElement.id
const tableEntries = targetElement.parentNode.childNodes
selected.forEach((entry) => {
if (entry.id === targetID) {
if (entry.rowIndex < targetElement.rowIndex) {
for (let i = entry.rowIndex - 1; i < targetElement.rowIndex; ++i) {
if (!tableEntries[i].className.includes(' selected')) {
tableEntries[i].className += ' ' + 'selected'
}
}
} else if (entry.rowIndex > targetElement.rowIndex) {
for (let i = targetElement.rowIndex - 1; i < entry.rowIndex; ++i) {
if (!tableEntries[i].className.includes(' selected')) {
tableEntries[i].className += ' ' + 'selected'
}
}
}
}
})
} else {
let sameTarget = false
const selected = document.querySelectorAll('.selected')
selected.forEach((entry) => {
entry.className = entry.className.replace(' selected', '')
if (entry === targetElement) {
sameTarget = true
}
})
if (!sameTarget) {
targetElement.className += ' ' + 'selected'
}
}
}
onContextMenu (e) {
const selected = document.querySelectorAll('.selected')
let handlerInputs = []
selected.forEach((entry) => {
entry.className = entry.className.replace(' selected', '')
const tableID = entry.id
const index = entry.rowIndex - 1
const handlerInput = this.props.totalRowObjects
? (typeof this.props.totalRowObjects[parseInt(tableID)][index].toJS === 'function'
? this.props.totalRowObjects[parseInt(tableID)][index].toJS()
: this.props.totalRowObjects[parseInt(tableID)][index])
: null
if (handlerInput) {
handlerInputs.push(handlerInput)
}
})
if (handlerInputs.length && this.hasContextMenu) {
if (handlerInputs.length === 1) {
this.props.onContextMenu(handlerInputs[0], this.props.contextMenuName, e)
} else {
this.props.onContextMenu(handlerInputs, this.props.contextMenuName, e)
}
}
}
get hasClickHandler () {
return typeof this.props.onClick === 'function'
}
Expand Down Expand Up @@ -105,9 +179,12 @@ class SortableTable extends ImmutableComponent {
return row.length
? <tr {...rowAttributes}
data-context-menu-disable={rowAttributes.onContextMenu ? true : undefined}
className={this.hasRowClassNames ? this.props.rowClassNames[i] + ' ' + rowAttributes.className
: rowAttributes.className}>{entry}</tr>
: null
id={this.props.tableID}
className={this.hasRowClassNames
? this.props.rowClassNames[i] + ' ' + rowAttributes.className
: rowAttributes.className} onClick={this.props.multiSelect ? this.onClick : undefined}
onContextMenu={this.props.multiSelect ? this.onContextMenu : undefined}>{entry}</tr>
: null
})
}
</tbody>
Expand Down
135 changes: 105 additions & 30 deletions js/contextMenus.js
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ function downloadsToolbarTemplateInit (downloadId, downloadItem) {

function siteDetailTemplateInit (siteDetail, activeFrame) {
let isHistoryEntry = false
let isHistoryEntries = false
let isFolder = false
let isRootFolder = false
let deleteLabel
Expand All @@ -228,21 +229,43 @@ function siteDetailTemplateInit (siteDetail, activeFrame) {
isRootFolder = siteDetail.get('folderId') === 0
deleteLabel = 'deleteFolder'
deleteTag = siteTags.BOOKMARK_FOLDER
} else {
} else if (siteUtil.isHistoryEntry(siteDetail)) {
isHistoryEntry = true
deleteLabel = 'deleteHistoryEntry'
} else if (Immutable.List.isList(siteDetail)) {
isHistoryEntries = true
siteDetail.forEach((site) => {
if (!siteUtil.isHistoryEntry(site)) {
isHistoryEntries = false
}
})
deleteLabel = 'deleteHistoryEntries'
}

const template = []

if (!isFolder) {
const location = siteDetail.get('location')
if (!Immutable.List.isList(siteDetail)) {
const location = siteDetail.get('location')

template.push(openInNewTabMenuItem(location, undefined, siteDetail.get('partitionNumber')),
openInNewPrivateTabMenuItem(location),
openInNewSessionTabMenuItem(location),
copyAddressMenuItem('copyLinkAddress', location),
CommonMenu.separatorMenuItem)
template.push(openInNewTabMenuItem(location, undefined, siteDetail.get('partitionNumber')),
openInNewPrivateTabMenuItem(location),
openInNewSessionTabMenuItem(location),
copyAddressMenuItem('copyLinkAddress', location),
CommonMenu.separatorMenuItem)
} else {
let locations = []
let partitionNumbers = []
siteDetail.forEach((site) => {
locations.push(site.get('location'))
partitionNumbers.push(site.get('partitionNumber'))
})

template.push(openInNewTabMenuItem(locations, undefined, partitionNumbers),
openInNewPrivateTabMenuItem(locations),
openInNewSessionTabMenuItem(locations),
CommonMenu.separatorMenuItem)
}
} else {
template.push(openAllInNewTabsMenuItem(appStoreRenderer.state.get('sites'), siteDetail),
CommonMenu.separatorMenuItem)
Expand All @@ -251,7 +274,7 @@ function siteDetailTemplateInit (siteDetail, activeFrame) {
if (!isRootFolder) {
// History can be deleted but not edited
// Picking this menu item pops up the AddEditBookmark modal
if (!isHistoryEntry) {
if (!isHistoryEntry && !isHistoryEntries) {
template.push(
{
label: locale.translation(isFolder ? 'editFolder' : 'editBookmark'),
Expand All @@ -263,11 +286,17 @@ function siteDetailTemplateInit (siteDetail, activeFrame) {
template.push(
{
label: locale.translation(deleteLabel),
click: () => appActions.removeSite(siteDetail, deleteTag)
click: () => {
if (Immutable.List.isList(siteDetail)) {
siteDetail.forEach((site) => appActions.removeSite(site, deleteTag))
} else {
appActions.removeSite(siteDetail, deleteTag)
}
}
})
}

if (!isHistoryEntry) {
if (!isHistoryEntry && !isHistoryEntries) {
if (template[template.length - 1] !== CommonMenu.separatorMenuItem) {
template.push(CommonMenu.separatorMenuItem)
}
Expand Down Expand Up @@ -656,10 +685,26 @@ function hamburgerTemplateInit (location, e) {

const openInNewTabMenuItem = (location, isPrivate, partitionNumber, parentFrameKey) => {
let openInForeground = getSetting(settings.SWITCH_TO_NEW_TABS) === true
return {
label: locale.translation('openInNewTab'),
click: () => {
windowActions.newFrame({ location, isPrivate, partitionNumber, parentFrameKey }, openInForeground)
if (Array.isArray(location) && Array.isArray(partitionNumber)) {
return {
label: locale.translation('openInNewTabs'),
click: () => {
for (let i = 0; i < location.length; ++i) {
windowActions.newFrame(
{ location: location[i],
isPrivate,
partitionNumber: partitionNumber[i],
parentFrameKey },
openInForeground)
}
}
}
} else {
return {
label: locale.translation('openInNewTab'),
click: () => {
windowActions.newFrame({ location, isPrivate, partitionNumber, parentFrameKey }, openInForeground)
}
}
}
}
Expand All @@ -675,14 +720,29 @@ const openAllInNewTabsMenuItem = (allSites, folderDetail) => {

const openInNewPrivateTabMenuItem = (location, parentFrameKey) => {
let openInForeground = getSetting(settings.SWITCH_TO_NEW_TABS) === true
return {
label: locale.translation('openInNewPrivateTab'),
click: () => {
windowActions.newFrame({
location,
isPrivate: true,
parentFrameKey
}, openInForeground)
if (Array.isArray(location)) {
return {
label: locale.translation('openInNewPrivateTabs'),
click: () => {
for (let i = 0; i < location.length; ++i) {
windowActions.newFrame({
location: location[i],
isPrivate: true,
parentFrameKey
}, openInForeground)
}
}
}
} else {
return {
label: locale.translation('openInNewPrivateTab'),
click: () => {
windowActions.newFrame({
location,
isPrivate: true,
parentFrameKey
}, openInForeground)
}
}
}
}
Expand All @@ -698,14 +758,29 @@ const openInNewWindowMenuItem = (location, isPrivate, partitionNumber) => {

const openInNewSessionTabMenuItem = (location, parentFrameKey) => {
let openInForeground = getSetting(settings.SWITCH_TO_NEW_TABS) === true
return {
label: locale.translation('openInNewSessionTab'),
click: (item, focusedWindow) => {
windowActions.newFrame({
location,
isPartitioned: true,
parentFrameKey
}, openInForeground)
if (Array.isArray(location)) {
return {
label: locale.translation('openInNewSessionTabs'),
click: (item, focusedWindow) => {
for (let i = 0; i < location.length; ++i) {
windowActions.newFrame({
location: location[i],
isPartitioned: true,
parentFrameKey
}, openInForeground)
}
}
}
} else {
return {
label: locale.translation('openInNewSessionTab'),
click: (item, focusedWindow) => {
windowActions.newFrame({
location,
isPartitioned: true,
parentFrameKey
}, openInForeground)
}
}
}
}
Expand Down
Loading