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

Splits sites object in the app state #10136

Merged
merged 7 commits into from
Aug 4, 2017
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
111 changes: 57 additions & 54 deletions app/browser/api/topSites.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,39 +7,36 @@
const Immutable = require('immutable')
const appActions = require('../../../js/actions/appActions')
const debounce = require('../../../js/lib/debounce')
const siteUtil = require('../../../js/state/siteUtil')
const historyState = require('../../common/state/historyState')
const bookmarkLocationCache = require('../../common/cache/bookmarkLocationCache')
const newTabData = require('../../../js/data/newTabData')
const {isSourceAboutUrl} = require('../../../js/lib/appUrlUtil')
const aboutNewTabMaxEntries = 100
let appStore

let minCountOfTopSites
let minAccessOfTopSites

const compareSites = (site1, site2) => {
if (!site1 || !site2) return false
return site1.get('location') === site2.get('location') &&
site1.get('partitionNumber') === site2.get('partitionNumber')
}
const staticData = Immutable.fromJS(newTabData.topSites)

const pinnedTopSites = (state) => {
return (state.getIn(['about', 'newtab', 'pinnedTopSites']) || Immutable.List()).setSize(18)
return state.getIn(['about', 'newtab', 'pinnedTopSites'], Immutable.List())
}

const ignoredTopSites = (state) => {
return state.getIn(['about', 'newtab', 'ignoredTopSites']) || Immutable.List()
return state.getIn(['about', 'newtab', 'ignoredTopSites'], Immutable.List())
}

const isPinned = (state, siteProps) => {
return pinnedTopSites(state).filter((site) => compareSites(site, siteProps)).size > 0
const isPinned = (state, siteKey) => {
return pinnedTopSites(state).find(site => site.get('key') === siteKey)
}

const isIgnored = (state, siteProps) => {
return ignoredTopSites(state).filter((site) => compareSites(site, siteProps)).size > 0
const isIgnored = (state, siteKey) => {
return ignoredTopSites(state).includes(siteKey)
}

const sortCountDescending = (left, right) => {
const leftCount = left.get('count') || 0
const rightCount = right.get('count') || 0
const leftCount = left.get('count', 0)
const rightCount = right.get('count', 0)
if (leftCount < rightCount) {
return 1
}
Expand Down Expand Up @@ -74,35 +71,44 @@ const removeDuplicateDomains = (list) => {
})
}

const calculateTopSites = (clearCache) => {
const calculateTopSites = (clearCache, withoutDebounce = false) => {
if (clearCache) {
clearTopSiteCacheData()
}
startCalculatingTopSiteData()
if (withoutDebounce) {
getTopSiteData()
} else {
debouncedGetTopSiteData()
}
}

/**
* TopSites are defined by users for the new tab page. Pinned sites are attached to their positions
* in the grid, and the non pinned indexes are populated with newly accessed sites
*/
const startCalculatingTopSiteData = debounce(() => {
const getTopSiteData = () => {
if (!appStore) {
appStore = require('../../../js/stores/appStore')
}
const state = appStore.getState()
// remove folders; sort by visit count; enforce a max limit
const sites = (state.get('sites') ? state.get('sites').toList() : new Immutable.List())
.filter((site) => !siteUtil.isFolder(site) &&
!siteUtil.isImportedBookmark(site) &&
!isSourceAboutUrl(site.get('location')) &&
let sites = historyState.getSites(state)
.filter((site, key) => !isSourceAboutUrl(site.get('location')) &&
!isPinned(state, key) &&
!isIgnored(state, key) &&
(minCountOfTopSites === undefined || (site.get('count') || 0) >= minCountOfTopSites) &&
(minAccessOfTopSites === undefined || (site.get('lastAccessedTime') || 0) >= minAccessOfTopSites))
(minAccessOfTopSites === undefined || (site.get('lastAccessedTime') || 0) >= minAccessOfTopSites)
)
.sort(sortCountDescending)
.slice(0, aboutNewTabMaxEntries)
.map((site, key) => {
const bookmarkKey = bookmarkLocationCache.getCacheKey(state, site.get('location'))

site = site.set('bookmarked', bookmarkKey.get(0, false))
site = site.set('key', key)
return site
})
.toList()

for (let i = 0; i < sites.size; i++) {
const count = sites.getIn([i, 'count']) || 0
const access = sites.getIn([i, 'lastAccessedTime']) || 0
const count = sites.getIn([i, 'count'], 0)
const access = sites.getIn([i, 'lastAccessedTime'], 0)
if (minCountOfTopSites === undefined || count < minCountOfTopSites) {
minCountOfTopSites = count
}
Expand All @@ -111,33 +117,30 @@ const startCalculatingTopSiteData = debounce(() => {
}
}

// Filter out pinned and ignored sites
let unpinnedSites = sites.filter((site) => !(isPinned(state, site) || isIgnored(state, site)))
unpinnedSites = removeDuplicateDomains(unpinnedSites)

// Merge the pinned and unpinned lists together
// Pinned items have priority because the position is important
let gridSites = pinnedTopSites(state).map((pinnedSite) => {
// Fetch latest siteDetail objects from appState.sites using location/partition
if (pinnedSite) {
const matches = sites.filter((site) => compareSites(site, pinnedSite))
if (matches.size > 0) return matches.first()
}
// Default to unpinned items
const firstSite = unpinnedSites.first()
unpinnedSites = unpinnedSites.shift()
return firstSite
})

// Include up to [aboutNewTabMaxEntries] entries so that folks
// can ignore sites and have new items fill those empty spaces
if (unpinnedSites.size > 0) {
gridSites = gridSites.concat(unpinnedSites)
// remove duplicate domains
// we only keep uniques host names
sites = removeDuplicateDomains(sites)

if (sites.size < 18) {
const preDefined = staticData
.filter((site) => {
return !isPinned(state, site.get('key')) && !isIgnored(state, site.get('key'))
})
.map(site => {
const bookmarkKey = bookmarkLocationCache.getCacheKey(state, site.get('location'))
return site.set('bookmarked', bookmarkKey.get(0, false))
})
sites = sites.concat(preDefined)
}

const finalData = gridSites.filter((site) => site != null)
appActions.topSiteDataAvailable(finalData)
}, 5 * 1000)
appActions.topSiteDataAvailable(sites)
}

/**
* TopSites are defined by users for the new tab page. Pinned sites are attached to their positions
* in the grid, and the non pinned indexes are populated with newly accessed sites
*/
const debouncedGetTopSiteData = debounce(() => getTopSiteData(), 5 * 1000)

const clearTopSiteCacheData = () => {
minCountOfTopSites = undefined
Expand Down
49 changes: 26 additions & 23 deletions app/browser/bookmarksExporter.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,23 @@ const electron = require('electron')
const dialog = electron.dialog
const app = electron.app
const BrowserWindow = electron.BrowserWindow
const getSetting = require('../../js/settings').getSetting

// State
const bookmarksState = require('../common/state/bookmarksState')

// Constants
const settings = require('../../js/constants/settings')
const siteTags = require('../../js/constants/siteTags')
const siteUtil = require('../../js/state/siteUtil')
const isWindows = process.platform === 'win32'

// Utils
const {getSetting} = require('../../js/settings')
const platformUtil = require('../common/lib/platformUtil')
const bookmarkFoldersUtil = require('../common/lib/bookmarkFoldersUtil')
const bookmarkUtil = require('../common/lib/bookmarkUtil')

const indentLength = 2
const indentType = ' '

function showDialog (sites) {
const showDialog = (state) => {
const focusedWindow = BrowserWindow.getFocusedWindow()
const fileName = moment().format('DD_MM_YYYY') + '.html'
const defaultPath = path.join(getSetting(settings.DEFAULT_DOWNLOAD_SAVE_PATH) || app.getPath('downloads'), fileName)
Expand All @@ -34,44 +42,39 @@ function showDialog (sites) {
}]
}, (fileName) => {
if (fileName) {
personal = createBookmarkArray(sites)
other = createBookmarkArray(sites, -1, false)
personal = createBookmarkArray(state)
other = createBookmarkArray(state, -1, false)
fs.writeFileSync(fileName, createBookmarkHTML(personal, other))
}
})
}

function createBookmarkArray (sites, parentFolderId, first = true, depth = 1) {
const filteredBookmarks = parentFolderId
? sites.filter((site) => site.get('parentFolderId') === parentFolderId)
: sites.filter((site) => !site.get('parentFolderId'))
const createBookmarkArray = (state, parentFolderId = 0, first = true, depth = 1) => {
const bookmarks = bookmarksState.getBookmarksWithFolders(state, parentFolderId)
let payload = []
let title
let indentFirst = indentType.repeat(depth * indentLength)
let indentNext = (!first) ? indentFirst : indentType.repeat((depth + 1) * indentLength)

if (first) payload.push(`${indentFirst}<DL><p>`)

filteredBookmarks.forEach((site) => {
if (site.get('tags').includes(siteTags.BOOKMARK) && site.get('location')) {
title = site.get('customTitle') || site.get('title') || site.get('location')
for (let site of bookmarks) {
if (bookmarkUtil.isBookmark(site) && site.get('location')) {
title = site.get('title', site.get('location'))
payload.push(`${indentNext}<DT><A HREF="${site.get('location')}">${title}</A>`)
} else if (siteUtil.isFolder(site)) {
const folderId = site.get('folderId')

title = site.get('customTitle') || site.get('title')
payload.push(`${indentNext}<DT><H3>${title}</H3>`)
payload = payload.concat(createBookmarkArray(sites, folderId, true, (depth + 1)))
} else if (bookmarkFoldersUtil.isFolder(site)) {
payload.push(`${indentNext}<DT><H3>${site.get('title')}</H3>`)
payload = payload.concat(createBookmarkArray(state, site.get('folderId'), true, (depth + 1)))
}
})
}

if (first) payload.push(`${indentFirst}</DL><p>`)

return payload
}

function createBookmarkHTML (personal, other) {
const breakTag = (isWindows) ? '\r\n' : '\n'
const createBookmarkHTML = (personal, other) => {
const breakTag = (platformUtil.isWindows()) ? '\r\n' : '\n'
const title = 'Bookmarks'

return `<!DOCTYPE NETSCAPE-Bookmark-file-1>
Expand Down
43 changes: 9 additions & 34 deletions app/browser/menu.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ const appConstants = require('../../js/constants/appConstants')
const windowConstants = require('../../js/constants/windowConstants')
const messages = require('../../js/constants/messages')
const settings = require('../../js/constants/settings')
const siteTags = require('../../js/constants/siteTags')

// State
const {getByTabId} = require('../common/state/tabState')
Expand All @@ -35,8 +34,8 @@ const frameStateUtil = require('../../js/state/frameStateUtil')
const menuUtil = require('../common/lib/menuUtil')
const {getSetting} = require('../../js/settings')
const locale = require('../locale')
const {isLocationBookmarked} = require('../../js/state/siteUtil')
const platformUtil = require('../common/lib/platformUtil')
const bookmarkUtil = require('../common/lib/bookmarkUtil')
const isDarwin = platformUtil.isDarwin()
const isLinux = platformUtil.isLinux()
const isWindows = platformUtil.isWindows()
Expand Down Expand Up @@ -376,7 +375,7 @@ const updateRecentlyClosedMenuItems = (state) => {
}

const isCurrentLocationBookmarked = (state) => {
return isLocationBookmarked(state, currentLocation)
return bookmarkUtil.isLocationBookmarked(state, currentLocation)
}

const createBookmarksSubmenu = (state) => {
Expand Down Expand Up @@ -406,7 +405,7 @@ const createBookmarksSubmenu = (state) => {
CommonMenu.exportBookmarksMenuItem()
]

const bookmarks = menuUtil.createBookmarkTemplateItems(state.get('sites'))
const bookmarks = menuUtil.createBookmarkTemplateItems(state)
if (bookmarks.length > 0) {
submenu.push(CommonMenu.separatorMenuItem)
submenu = submenu.concat(bookmarks)
Expand Down Expand Up @@ -693,38 +692,14 @@ const doAction = (state, action) => {
}
break
}
case appConstants.APP_APPLY_SITE_RECORDS:
if (action.records && action.records.find((record) => record.objectData === 'bookmark')) {
createMenu(state)
}
break
case appConstants.APP_ADD_SITE:
case appConstants.APP_ADD_BOOKMARK:
case appConstants.APP_EDIT_BOOKMARK:
{
if (action.tag === siteTags.BOOKMARK || action.tag === siteTags.BOOKMARK_FOLDER) {
createMenu(state)
} else if (action.siteDetail && action.siteDetail.constructor === Immutable.List && action.tag === undefined) {
let shouldRebuild = false
action.siteDetail.forEach((site) => {
const tag = site.getIn(['tags', 0])
if (tag === siteTags.BOOKMARK || tag === siteTags.BOOKMARK_FOLDER) {
shouldRebuild = true
}
})
if (shouldRebuild) {
createMenu(state)
}
}
break
}
case appConstants.APP_REMOVE_SITE:
{
if (action.tag === siteTags.BOOKMARK || action.tag === siteTags.BOOKMARK_FOLDER) {
createMenu(state)
}
break
}
case appConstants.APP_REMOVE_BOOKMARK:
case appConstants.APP_ADD_BOOKMARK_FOLDER:
case appConstants.APP_EDIT_BOOKMARK_FOLDER:
case appConstants.APP_REMOVE_BOOKMARK_FOLDER:
createMenu(state)
break
case appConstants.APP_ON_CLEAR_BROWSING_DATA:
{
const defaults = state.get('clearBrowsingDataDefaults')
Expand Down
2 changes: 1 addition & 1 deletion app/browser/reducers/autoplayReducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const {makeImmutable} = require('../../common/state/immutableUtil')
const {ipcMain, webContents} = require('electron')
const siteSettings = require('../../../js/state/siteSettings')
const appActions = require('../../../js/actions/appActions')
const {getOrigin} = require('../../../js/state/siteUtil')
const {getOrigin} = require('../../../js/lib/urlutil')
const locale = require('../../locale')
const messages = require('../../../js/constants/messages')

Expand Down
Loading