mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-08-21 03:43:16 +09:00
97 lines
4.4 KiB
Swift
97 lines
4.4 KiB
Swift
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
import Foundation
|
|
import Deferred
|
|
import Shared
|
|
|
|
public let ActivityStreamTopSiteCacheSize: Int32 = 16
|
|
|
|
private let log = Logger.browserLogger
|
|
|
|
protocol DataObserver {
|
|
var profile: Profile { get }
|
|
weak var delegate: DataObserverDelegate? { get set }
|
|
|
|
func refreshIfNeeded(forceHighlights highlights: Bool, forceTopSites topSites: Bool)
|
|
}
|
|
|
|
protocol DataObserverDelegate: class {
|
|
func didInvalidateDataSources(refresh forced: Bool, highlightsRefreshed: Bool, topSitesRefreshed: Bool)
|
|
func willInvalidateDataSources(forceHighlights highlights: Bool, forceTopSites topSites: Bool)
|
|
}
|
|
|
|
// Make these delegate methods optional by providing default implementations
|
|
extension DataObserverDelegate {
|
|
func didInvalidateDataSources(refresh forced: Bool, highlightsRefreshed: Bool, topSitesRefreshed: Bool) {}
|
|
func willInvalidateDataSources(forceHighlights highlights: Bool, forceTopSites topSites: Bool) {}
|
|
}
|
|
|
|
open class PanelDataObservers {
|
|
var activityStream: DataObserver
|
|
|
|
init(profile: Profile) {
|
|
self.activityStream = ActivityStreamDataObserver(profile: profile)
|
|
}
|
|
}
|
|
|
|
class ActivityStreamDataObserver: DataObserver {
|
|
let profile: Profile
|
|
weak var delegate: DataObserverDelegate?
|
|
private var invalidationTime = OneMinuteInMilliseconds * 15
|
|
|
|
fileprivate let events = [NotificationFirefoxAccountChanged, NotificationProfileDidFinishSyncing, NotificationPrivateDataClearedHistory]
|
|
|
|
init(profile: Profile) {
|
|
self.profile = profile
|
|
self.profile.history.setTopSitesCacheSize(ActivityStreamTopSiteCacheSize)
|
|
events.forEach { NotificationCenter.default.addObserver(self, selector: #selector(self.notificationReceived(_:)), name: $0, object: nil) }
|
|
}
|
|
|
|
/*
|
|
refreshIfNeeded will refresh the underlying caches for both TopSites and Highlights.
|
|
By default this will only refresh the highlights if the last fetch is older than 15 mins
|
|
By default this will only refresh topSites if KeyTopSitesCacheIsValid is false
|
|
*/
|
|
func refreshIfNeeded(forceHighlights highlights: Bool, forceTopSites topSites: Bool) {
|
|
guard !profile.isShutdown else {
|
|
return
|
|
}
|
|
|
|
// Highlights are cached for 15 mins
|
|
let userEnabledHighlights = profile.prefs.boolForKey(PrefsKeys.ASRecentHighlightsVisible) ?? true
|
|
let lastInvalidationTime = profile.prefs.unsignedLongForKey(PrefsKeys.ASLastInvalidation) ?? 0
|
|
let shouldInvalidateHighlights = (highlights || (Date.now() - lastInvalidationTime > invalidationTime)) && userEnabledHighlights
|
|
|
|
// KeyTopSitesCacheIsValid is false when we want to invalidate. Thats why this logic is so backwards
|
|
let shouldInvalidateTopSites = topSites || !(profile.prefs.boolForKey(PrefsKeys.KeyTopSitesCacheIsValid) ?? false)
|
|
if !shouldInvalidateTopSites && !shouldInvalidateHighlights {
|
|
// There is nothing to refresh. Bye
|
|
return
|
|
}
|
|
|
|
self.delegate?.willInvalidateDataSources(forceHighlights: highlights, forceTopSites: topSites)
|
|
self.profile.recommendations.repopulate(invalidateTopSites: shouldInvalidateTopSites, invalidateHighlights: shouldInvalidateHighlights).uponQueue(DispatchQueue.main) { _ in
|
|
if shouldInvalidateTopSites {
|
|
self.profile.prefs.setBool(true, forKey: PrefsKeys.KeyTopSitesCacheIsValid)
|
|
}
|
|
|
|
if shouldInvalidateHighlights {
|
|
let newInvalidationTime = shouldInvalidateHighlights ? Date.now() : lastInvalidationTime
|
|
self.profile.prefs.setLong(newInvalidationTime, forKey: PrefsKeys.ASLastInvalidation)
|
|
}
|
|
|
|
self.delegate?.didInvalidateDataSources(refresh: highlights || topSites, highlightsRefreshed: shouldInvalidateHighlights, topSitesRefreshed: shouldInvalidateTopSites)
|
|
}
|
|
}
|
|
|
|
@objc func notificationReceived(_ notification: Notification) {
|
|
switch notification.name {
|
|
case NotificationProfileDidFinishSyncing, NotificationFirefoxAccountChanged, NotificationPrivateDataClearedHistory:
|
|
refreshIfNeeded(forceHighlights: true, forceTopSites: true)
|
|
default:
|
|
log.warning("Received unexpected notification \(notification.name)")
|
|
}
|
|
}
|
|
}
|