blob: 2dc587c192a1ce53f1c9b74093c26f7098d07474 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
|
//
// WelcomeInteractor.swift
// MullvadVPN
//
// Created by Mojgan on 2023-06-29.
// Copyright © 2025 Mullvad VPN AB. All rights reserved.
//
import Foundation
import MullvadLogging
import MullvadTypes
import StoreKit
final class WelcomeInteractor: @unchecked Sendable {
private let tunnelManager: TunnelManager
/// Interval used for periodic polling account updates.
private let accountUpdateTimerInterval: Duration = .minutes(1)
private var accountUpdateTimer: DispatchSourceTimer?
private let logger = Logger(label: "\(WelcomeInteractor.self)")
private var tunnelObserver: TunnelObserver?
private(set) var products: [SKProduct]?
var didAddMoreCredit: (() -> Void)?
var viewWillAppear = false {
didSet {
guard viewWillAppear else { return }
startAccountUpdateTimer()
}
}
var viewDidDisappear = false {
didSet {
guard viewDidDisappear else { return }
stopAccountUpdateTimer()
}
}
var accountNumber: String {
tunnelManager.deviceState.accountData?.number ?? ""
}
var viewModel: WelcomeViewModel {
WelcomeViewModel(
deviceName: tunnelManager.deviceState.deviceData?.capitalizedName ?? "",
accountNumber: tunnelManager.deviceState.accountData?.number.formattedAccountNumber ?? ""
)
}
init(
tunnelManager: TunnelManager
) {
self.tunnelManager = tunnelManager
let tunnelObserver =
TunnelBlockObserver(didUpdateDeviceState: { [weak self] _, deviceState, previousDeviceState in
let isInactive = previousDeviceState.accountData?.isExpired == true
let isActive = deviceState.accountData?.isExpired == false
if isInactive && isActive {
self?.didAddMoreCredit?()
}
})
tunnelManager.addObserver(tunnelObserver)
self.tunnelObserver = tunnelObserver
}
private func startAccountUpdateTimer() {
logger.debug(
"Start polling account updates every \(accountUpdateTimerInterval) second(s)."
)
let timer = DispatchSource.makeTimerSource(queue: .main)
timer.setEventHandler { [weak self] in
self?.tunnelManager.updateAccountData()
}
accountUpdateTimer?.cancel()
accountUpdateTimer = timer
timer.schedule(
wallDeadline: .now() + accountUpdateTimerInterval,
repeating: accountUpdateTimerInterval.timeInterval
)
timer.activate()
}
private func stopAccountUpdateTimer() {
logger.debug(
"Stop polling account updates."
)
accountUpdateTimer?.cancel()
accountUpdateTimer = nil
}
}
|