Skip to content

Commit

Permalink
Add enabling/disabling ui statistics
Browse files Browse the repository at this point in the history
- Change appearance.show market and balance buttons
  • Loading branch information
ant013 committed Jun 5, 2024
1 parent e93dd78 commit 6c0d523
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 75 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13291,7 +13291,7 @@
repositoryURL = "https://github.com/zcash/ZcashLightClientKit";
requirement = {
kind = exactVersion;
version = 2.1.5;
version = 2.1.8;
};
};
D3993DAA28F42549008720FB /* XCRemoteSwiftPackageReference "WalletConnectSwiftV2" */ = {
Expand Down
150 changes: 84 additions & 66 deletions UnstoppableWallet/UnstoppableWallet/Core/Managers/StatManager.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Alamofire
import Combine
import Foundation
import HsToolKit
import MarketKit
Expand All @@ -10,6 +11,8 @@ func stat(page: StatPage, section: StatSection? = nil, event: StatEvent) {

class StatManager {
private static let keyLastSent = "stat_last_sent"
private static let keySendingAllowed = "sending_allowed"

private static let sendThreshold: TimeInterval = 1 * 60 * 60 // 1 hour

private let marketKit: MarketKit.Kit
Expand All @@ -18,83 +21,98 @@ class StatManager {
private let appVersion: String
private let appId: String?

var allowed: Bool {
didSet {
userDefaultsStorage.set(value: allowed, for: Self.keySendingAllowed)
allowedSubject.send(allowed)
}
}

private let allowedSubject = PassthroughSubject<Bool, Never>()
var allowedPublisher: AnyPublisher<Bool, Never> {
allowedSubject.eraseToAnyPublisher()
}

init(marketKit: MarketKit.Kit, storage: StatStorage, userDefaultsStorage: UserDefaultsStorage) {
self.marketKit = marketKit
self.storage = storage
self.userDefaultsStorage = userDefaultsStorage

appVersion = AppConfig.appVersion
appId = AppConfig.appId
allowed = userDefaultsStorage.value(for: StatManager.keySendingAllowed) ?? true
}

func logStat(eventPage _: StatPage, eventSection _: StatSection? = nil, event _: StatEvent) {
// var parameters: [String: Any]?
//
// if let params = event.params {
// parameters = [String: Any]()
//
// for (key, value) in params {
// parameters?[key.rawValue] = value
// }
// }
//
// let record = StatRecord(
// timestamp: Int(Date().timeIntervalSince1970),
// eventPage: eventPage.rawValue,
// eventSection: eventSection?.rawValue,
// event: event.name,
// params: parameters
// )
//
// do {
// try storage.save(record: record)
// } catch {
// print("Cannot save StatRecord: \(error)")
// }
func logStat(eventPage: StatPage, eventSection: StatSection? = nil, event: StatEvent) {
guard allowed else { return }
var parameters: [String: Any]?

if let params = event.params {
parameters = [String: Any]()

for (key, value) in params {
parameters?[key.rawValue] = value
}
}

let record = StatRecord(
timestamp: Int(Date().timeIntervalSince1970),
eventPage: eventPage.rawValue,
eventSection: eventSection?.rawValue,
event: event.name,
params: parameters
)

do {
try storage.save(record: record)
} catch {
print("Cannot save StatRecord: \(error)")
}
}

func sendStats() {
// let lastSent: Double? = userDefaultsStorage.value(for: Self.keyLastSent)
//
// if let lastSent, Date().timeIntervalSince1970 - lastSent < Self.sendThreshold {
// return
// }
//
// Task { [storage] in
// let records = try storage.all()
//
// guard !records.isEmpty else {
// return
// }
//
// let stats = records.map { record in
// var object: [String: Any] = [
// "time": record.timestamp,
// "event_page": record.eventPage,
// "event": record.event,
// ]
//
// if let eventSection = record.eventSection {
// object["event_section"] = eventSection
// }
//
// if let params = record.params {
// for (key, value) in params {
// object[key] = value
// }
// }
//
// return object
// }
//
//// let data = try JSONSerialization.data(withJSONObject: stats)
//// let string = String(data: data, encoding: .utf8)
//// print(string ?? "N/A")
//
// try await marketKit.send(stats: stats, appVersion: appVersion, appId: appId)
//
// userDefaultsStorage.set(value: Date().timeIntervalSince1970, for: Self.keyLastSent)
// try storage.clear()
// }
guard allowed else { return }
let lastSent: Double? = userDefaultsStorage.value(for: Self.keyLastSent)

if let lastSent, Date().timeIntervalSince1970 - lastSent < Self.sendThreshold {
return
}

Task { [storage] in
let records = try storage.all()

guard !records.isEmpty else {
return
}

let stats = records.map { record in
var object: [String: Any] = [
"time": record.timestamp,
"event_page": record.eventPage,
"event": record.event,
]

if let eventSection = record.eventSection {
object["event_section"] = eventSection
}

if let params = record.params {
for (key, value) in params {
object[key] = value
}
}

return object
}

// let data = try JSONSerialization.data(withJSONObject: stats)
// let string = String(data: data, encoding: .utf8)
// print(string ?? "N/A")

try await marketKit.send(stats: stats, appVersion: appVersion, appId: appId)

userDefaultsStorage.set(value: Date().timeIntervalSince1970, for: Self.keyLastSent)
try storage.clear()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,16 +55,40 @@ class PrivacyPolicyViewController: ThemeViewController {
return [
Section(
id: "privacy-section",
footerState: .margin(height: .margin32),
footerState: .margin(height: .margin16),
rows: infoRows
),
]
}

private var statAllowedSections: [SectionProtocol] {
[
Section(
id: "stat-allowed-section",
footerState: .margin(height: .margin32),
rows: [
tableView.universalRow48(
id: "stat-allowed-cell",
image: .local(UIImage(named: "share_1_24")),
title: .body("settings.privacy.allow".localized),
accessoryType: .switch(
isOn: App.shared.statManager.allowed,
onSwitch: { enabled in
App.shared.statManager.allowed = enabled
}
),
isFirst: true,
isLast: true
),
]
),
]
}
}

extension PrivacyPolicyViewController: SectionsDataSource {
func buildSections() -> [SectionProtocol] {
privacySections
privacySections + statAllowedSections
}
}

Expand All @@ -79,9 +103,8 @@ extension PrivacyPolicyViewController {
title: "settings.privacy".localized,
description: "settings.privacy.description".localized(AppConfig.appName),
viewItems: [
"settings.privacy.statement.user_data_storage".localized,
"settings.privacy.statement.data_usage".localized,
"settings.privacy.statement.data_privacy".localized,
"settings.privacy.statement.data_storage".localized,
"settings.privacy.statement.user_account".localized,
]
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1532,11 +1532,11 @@
// Settings -> Privacy

"settings.privacy" = "Privacy";
"settings.privacy.description" = "%@ doesn't collect any data or use analytics tools that may expose any data about its users. The wallet is designed to ensure a high level of privacy for its users.";
"settings.privacy.statement.user_data_storage" = "User data always remains on the user's device.";
"settings.privacy.description" = "%@ doesn't collect personal data that expose your private information i.e. coin balances or addresses. While we gather some UI usage statistics, it's solely for understanding our user base and app usage trends. That can be disabled if you wish.";
"settings.privacy.statement.data_usage" = "The wallet doesn't collect any data about users.";
"settings.privacy.statement.data_privacy" = "The wallet doesn't share any data about users.";
"settings.privacy.statement.user_account" = "There are no user accounts or databases keeping user data elsewhere.";
"settings.privacy.statement.data_storage" = "There are no user accounts or databases storing user data.";
"settings.privacy.statement.user_account" = "If allowed the wallet will share app usage habits with Unstoppable team. This is to understand which features are being used (or not) by our users. Being a privacy focused app we need some way to evaluate our efforts and without this we have no idea whether the features we built are being used or not.";
"settings.privacy.allow" = "Share UI Data";

// Settings -> Appearance

Expand Down

0 comments on commit 6c0d523

Please sign in to comment.