This repository has been archived by the owner. It is now read-only.
Permalink
Cannot retrieve contributors at this time
executable file
121 lines (103 sloc)
3.53 KB
| /* 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 Shared | |
| import SwiftyJSON | |
| // These are taken from the Places docs | |
| // http://mxr.mozilla.org/mozilla-central/source/toolkit/components/places/nsINavHistoryService.idl#1187 | |
| @objc public enum VisitType: Int { | |
| case unknown = 0 | |
| /** | |
| * This transition type means the user followed a link and got a new toplevel | |
| * window. | |
| */ | |
| case link = 1 | |
| /** | |
| * This transition type means that the user typed the page's URL in the | |
| * URL bar or selected it from URL bar autocomplete results, clicked on | |
| * it from a history query (from the History sidebar, History menu, | |
| * or history query in the personal toolbar or Places organizer). | |
| */ | |
| case typed = 2 | |
| case bookmark = 3 | |
| case embed = 4 | |
| case permanentRedirect = 5 | |
| case temporaryRedirect = 6 | |
| case download = 7 | |
| case framedLink = 8 | |
| } | |
| // WKWebView has these: | |
| /* | |
| WKNavigationTypeLinkActivated, | |
| WKNavigationTypeFormSubmitted, | |
| WKNavigationTypeBackForward, | |
| WKNavigationTypeReload, | |
| WKNavigationTypeFormResubmitted, | |
| WKNavigationTypeOther = -1, | |
| */ | |
| /** | |
| * SiteVisit is a sop to the existing API, which expects to be able to go | |
| * backwards from a visit to a site, and preserve the ID of the database row. | |
| * Visit is the model of what lives on the wire: just a date and a type. | |
| * Ultimately we'll end up with something similar to ClientAndTabs: the tabs | |
| * don't need to know about the client, and visits don't need to know about | |
| * the site, because they're bound together. | |
| * | |
| * (Furthermore, we probably shouldn't ever need something like SiteVisit | |
| * to reach the UI: we care about "last visited", "visit count", or just | |
| * "places ordered by frecency" — we don't care about lists of visits.) | |
| */ | |
| open class Visit: Hashable { | |
| open let date: MicrosecondTimestamp | |
| open let type: VisitType | |
| open var hashValue: Int { | |
| return date.hashValue ^ type.hashValue | |
| } | |
| public init(date: MicrosecondTimestamp, type: VisitType = .unknown) { | |
| self.date = date | |
| self.type = type | |
| } | |
| open class func fromJSON(_ json: [String: Any]) -> Visit? { | |
| if let type = json["type"] as? Int, | |
| let typeEnum = VisitType(rawValue: type), | |
| let date = json["date"] as? Int64, date >= 0 { | |
| return Visit(date: MicrosecondTimestamp(date), type: typeEnum) | |
| } | |
| return nil | |
| } | |
| open func toJSON() -> [String: Any] { | |
| let d = NSNumber(value: self.date) | |
| let o: [String: Any] = ["type": self.type.rawValue, "date": d] | |
| return o | |
| } | |
| } | |
| public func ==(lhs: Visit, rhs: Visit) -> Bool { | |
| return lhs.date == rhs.date && | |
| lhs.type == rhs.type | |
| } | |
| open class SiteVisit: Visit { | |
| var id: Int? | |
| open let site: Site | |
| open override var hashValue: Int { | |
| return date.hashValue ^ type.hashValue ^ (id?.hashValue ?? 0) ^ (site.id ?? 0) | |
| } | |
| public init(site: Site, date: MicrosecondTimestamp, type: VisitType = .unknown) { | |
| self.site = site | |
| super.init(date: date, type: type) | |
| } | |
| } | |
| public func ==(lhs: SiteVisit, rhs: SiteVisit) -> Bool { | |
| if let lhsID = lhs.id, let rhsID = rhs.id { | |
| if lhsID != rhsID { | |
| return false | |
| } | |
| } else { | |
| if lhs.id != nil || rhs.id != nil { | |
| return false | |
| } | |
| } | |
| // TODO: compare Site. | |
| return lhs.date == rhs.date && | |
| lhs.type == rhs.type | |
| } |