Group multiple timestamps
This commit is contained in:
@@ -357,20 +357,27 @@
|
|||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
|
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
|
||||||
<prototypes>
|
<prototypes>
|
||||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="HostDetailCell" textLabel="J2P-mU-Vad" style="IBUITableViewCellStyleDefault" id="ZCA-Dz-i92">
|
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="HostDetailCell" textLabel="J2P-mU-Vad" detailTextLabel="eWb-mX-udN" style="IBUITableViewCellStyleValue1" id="ZCA-Dz-i92">
|
||||||
<rect key="frame" x="0.0" y="28" width="320" height="43.5"/>
|
<rect key="frame" x="0.0" y="28" width="320" height="43.5"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="ZCA-Dz-i92" id="nxe-48-jAQ">
|
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="ZCA-Dz-i92" id="nxe-48-jAQ">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="320" height="43.5"/>
|
<rect key="frame" x="0.0" y="0.0" width="320" height="43.5"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Title" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" enabled="NO" adjustsFontSizeToFit="NO" id="J2P-mU-Vad">
|
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Title" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="J2P-mU-Vad">
|
||||||
<rect key="frame" x="16" y="0.0" width="288" height="43.5"/>
|
<rect key="frame" x="16" y="12" width="33.5" height="20.5"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
|
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
|
||||||
<nil key="textColor"/>
|
<nil key="textColor"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
|
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Detail" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="eWb-mX-udN">
|
||||||
|
<rect key="frame" x="260" y="12" width="44" height="20.5"/>
|
||||||
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
|
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
|
||||||
|
<color key="textColor" systemColor="secondaryLabelColor" red="0.23529411759999999" green="0.23529411759999999" blue="0.26274509800000001" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<nil key="highlightedColor"/>
|
||||||
|
</label>
|
||||||
</subviews>
|
</subviews>
|
||||||
</tableViewCellContentView>
|
</tableViewCellContentView>
|
||||||
</tableViewCell>
|
</tableViewCell>
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ class DBWrapper {
|
|||||||
$0.1 + ($1.1.contains(.ignored) ? 1 : 0)) }}
|
$0.1 + ($1.1.contains(.ignored) ? 1 : 0)) }}
|
||||||
}
|
}
|
||||||
|
|
||||||
func listOfTimes(_ domain: String) -> [(Timestamp, Bool)] {
|
func listOfTimes(_ domain: String) -> [GroupedTsOccurrence] {
|
||||||
return AppDB?.timesForDomain(domain, since: earliestEntry)?.reversed() ?? []
|
return AppDB?.timesForDomain(domain, since: earliestEntry)?.reversed() ?? []
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,10 +2,6 @@ import Foundation
|
|||||||
import SQLite3
|
import SQLite3
|
||||||
|
|
||||||
typealias Timestamp = Int64
|
typealias Timestamp = Int64
|
||||||
struct GroupedDomain {
|
|
||||||
let domain: String, total: Int32, blocked: Int32, lastModified: Timestamp
|
|
||||||
var options: FilterOptions? = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
struct FilterOptions: OptionSet {
|
struct FilterOptions: OptionSet {
|
||||||
let rawValue: Int32
|
let rawValue: Int32
|
||||||
@@ -196,6 +192,11 @@ private struct DNSQueryT: SQLTable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct GroupedDomain {
|
||||||
|
let domain: String, total: Int32, blocked: Int32, lastModified: Timestamp
|
||||||
|
var options: FilterOptions? = nil
|
||||||
|
}
|
||||||
|
|
||||||
extension SQLiteDatabase {
|
extension SQLiteDatabase {
|
||||||
|
|
||||||
// MARK: insert
|
// MARK: insert
|
||||||
@@ -251,14 +252,18 @@ extension SQLiteDatabase {
|
|||||||
allDomainsGrouped("WHERE ts >= ? AND ts < ?", bind: [BindInt64(ts1), BindInt64(ts2)])
|
allDomainsGrouped("WHERE ts >= ? AND ts < ?", bind: [BindInt64(ts1), BindInt64(ts2)])
|
||||||
}
|
}
|
||||||
|
|
||||||
func timesForDomain(_ fullDomain: String, since ts: Timestamp = 0) -> [(Timestamp, Bool)]? {
|
func timesForDomain(_ fullDomain: String, since ts: Timestamp = 0) -> [GroupedTsOccurrence]? {
|
||||||
try? run(sql: "SELECT ts, logOpt FROM req WHERE ts >= ? AND domain = ?;",
|
try? run(sql: "SELECT ts, COUNT(ts), SUM(logOpt>0) FROM req WHERE ts >= ? AND domain = ? GROUP BY ts;",
|
||||||
bind: [BindInt64(ts), BindText(fullDomain)]) {
|
bind: [BindInt64(ts), BindText(fullDomain)]) {
|
||||||
allRows($0) { (sqlite3_column_int64($0, 0), sqlite3_column_int($0, 1) > 0) }
|
allRows($0) {
|
||||||
|
(sqlite3_column_int64($0, 0), sqlite3_column_int($0, 1), sqlite3_column_int($0, 2))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typealias GroupedTsOccurrence = (ts: Timestamp, total: Int32, blocked: Int32)
|
||||||
|
|
||||||
|
|
||||||
// MARK: - DNSFilterT
|
// MARK: - DNSFilterT
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import UIKit
|
|||||||
class TVCHostDetails: UITableViewController {
|
class TVCHostDetails: UITableViewController {
|
||||||
|
|
||||||
public var fullDomain: String!
|
public var fullDomain: String!
|
||||||
private var dataSource: [(ts: Timestamp, blocked: Bool)] = []
|
private var dataSource: [GroupedTsOccurrence] = []
|
||||||
|
|
||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
@@ -26,7 +26,8 @@ class TVCHostDetails: UITableViewController {
|
|||||||
let cell = tableView.dequeueReusableCell(withIdentifier: "HostDetailCell")!
|
let cell = tableView.dequeueReusableCell(withIdentifier: "HostDetailCell")!
|
||||||
let src = dataSource[indexPath.row]
|
let src = dataSource[indexPath.row]
|
||||||
cell.textLabel?.text = src.ts.asDateTime()
|
cell.textLabel?.text = src.ts.asDateTime()
|
||||||
cell.imageView?.image = (src.blocked ? UIImage(named: "shield-x") : nil)
|
cell.detailTextLabel?.text = (src.total > 1) ? "\(src.total)x" : nil
|
||||||
|
cell.imageView?.image = (src.blocked > 0 ? UIImage(named: "shield-x") : nil)
|
||||||
return cell
|
return cell
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user