Skip to content

Commit

Permalink
Release Reminder (#667)
Browse files Browse the repository at this point in the history
  • Loading branch information
Jon-b-m authored May 10, 2024
1 parent 066a68a commit 62d49c6
Show file tree
Hide file tree
Showing 10 changed files with 137 additions and 13 deletions.
2 changes: 1 addition & 1 deletion Config.xcconfig
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
APP_DISPLAY_NAME = iAPS
APP_VERSION = 4.2.3
APP_VERSION = 4.3.0
APP_BUILD_NUMBER = 1
COPYRIGHT_NOTICE =
DEVELOPER_TEAM = ##TEAM_ID##
Expand Down
5 changes: 5 additions & 0 deletions Core_Data.xcdatamodeld/Core_Data.xcdatamodel/contents
Original file line number Diff line number Diff line change
Expand Up @@ -179,4 +179,9 @@
<attribute name="date" optional="YES" attributeType="Date" defaultDateTimeInterval="722095800" usesScalarValueType="NO"/>
<attribute name="hours" optional="YES" attributeType="Integer 16" defaultValueString="6" usesScalarValueType="YES"/>
</entity>
<entity name="VNr" representedClassName="VNr" syncable="YES" codeGenerationType="class">
<attribute name="date" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="dev" optional="YES" attributeType="String"/>
<attribute name="nr" optional="YES" attributeType="String"/>
</entity>
</model>
4 changes: 4 additions & 0 deletions FreeAPS.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
190EBCC829FF13AA00BA767D /* StatConfigStateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 190EBCC729FF13AA00BA767D /* StatConfigStateModel.swift */; };
190EBCCB29FF13CB00BA767D /* StatConfigRootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 190EBCCA29FF13CB00BA767D /* StatConfigRootView.swift */; };
190F8CF72BC6F70800EDB473 /* IllustrationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 190F8CF62BC6F70800EDB473 /* IllustrationView.swift */; };
191A9D162BED00A500028D48 /* Version.swift in Sources */ = {isa = PBXBuildFile; fileRef = 191A9D152BED00A500028D48 /* Version.swift */; };
191F62682AD6B05A004D7911 /* NightscoutSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 191F62672AD6B05A004D7911 /* NightscoutSettings.swift */; };
1920BF5D2B9DF53200E861FE /* BolusShortcut.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1920BF5C2B9DF53200E861FE /* BolusShortcut.swift */; };
19229B962AFBB84800CD91CA /* Predictions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19229B952AFBB84800CD91CA /* Predictions.swift */; };
Expand Down Expand Up @@ -564,6 +565,7 @@
190EBCCA29FF13CB00BA767D /* StatConfigRootView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatConfigRootView.swift; sourceTree = "<group>"; };
190F8CF62BC6F70800EDB473 /* IllustrationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IllustrationView.swift; sourceTree = "<group>"; };
1918333A26ADA46800F45722 /* fi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fi; path = fi.lproj/Localizable.strings; sourceTree = "<group>"; };
191A9D152BED00A500028D48 /* Version.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Version.swift; sourceTree = "<group>"; };
191F62672AD6B05A004D7911 /* NightscoutSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NightscoutSettings.swift; sourceTree = "<group>"; };
1920BF5C2B9DF53200E861FE /* BolusShortcut.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BolusShortcut.swift; sourceTree = "<group>"; };
192202902BAB567800B95BE8 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1869,6 +1871,7 @@
F2159A512BA60F7A00A0B716 /* FontWeight.swift */,
F2159A532BA6207F00A0B716 /* ContactTrickEntry.swift */,
F270F68C2BAE374C00F6D8DD /* FontTracking.swift */,
191A9D152BED00A500028D48 /* Version.swift */,
);
path = Models;
sourceTree = "<group>";
Expand Down Expand Up @@ -2958,6 +2961,7 @@
3811DE4225C9D4A100A708ED /* SettingsDataFlow.swift in Sources */,
3811DE2525C9D48300A708ED /* MainRootView.swift in Sources */,
CE94598229E9E3D30047C9C6 /* WatchConfigProvider.swift in Sources */,
191A9D162BED00A500028D48 /* Version.swift in Sources */,
38E44535274E411700EC9A94 /* Disk+Data.swift in Sources */,
3811DE3125C9D49500A708ED /* HomeProvider.swift in Sources */,
FE41E4D629463EE20047FD55 /* NightscoutPreferences.swift in Sources */,
Expand Down
14 changes: 12 additions & 2 deletions FreeAPS/Sources/APS/APSManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -967,10 +967,10 @@ final class BaseAPSManager: APSManager, Injectable {
// Add to statistics.JSON for upload to NS.
private func statistics() {
let stats = CoreDataStorage().fetchStats()
versionCheack()
let newVersion = UserDefaults.standard.bool(forKey: IAPSconfig.newVersion)

// Only save and upload twice per day
guard ((-1 * (stats.first?.lastrun ?? .distantPast).timeIntervalSinceNow.hours) > 8) || newVersion else {
guard ((-1 * (stats.first?.lastrun ?? .distantPast).timeIntervalSinceNow.hours) > 10) || newVersion else {
return
}

Expand Down Expand Up @@ -1232,6 +1232,16 @@ final class BaseAPSManager: APSManager, Injectable {
return identfier
}

private func versionCheack() {
if Date.now.hour % 2 == 0 {
if let last = CoreDataStorage().fetchVNr(),
(last.date ?? .distantFuture) > Date.now.addingTimeInterval(-1.hours.timeInterval)
{
nightscout.fetchVersion()
}
}
}

private func branch() -> String {
var branch = "Unknown"
if let branchFileURL = Bundle.main.url(forResource: "branch", withExtension: "txt"),
Expand Down
24 changes: 24 additions & 0 deletions FreeAPS/Sources/APS/Storage/CoreDataStorage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -138,4 +138,28 @@ final class CoreDataStorage {
}
UserDefaults.standard.set(false, forKey: IAPSconfig.newVersion)
}

func saveVNr(_ versions: Version?) {
if let version = versions {
coredataContext.performAndWait { [self] in
let saveNr = VNr(context: self.coredataContext)
saveNr.nr = version.main
saveNr.dev = version.dev
saveNr.date = Date.now
try? self.coredataContext.save()
}
}
}

func fetchVNr() -> VNr? {
var nr = [VNr]()
coredataContext.performAndWait {
let requestNr = VNr.fetchRequest() as NSFetchRequest<VNr>
let sort = NSSortDescriptor(key: "date", ascending: false)
requestNr.sortDescriptors = [sort]
requestNr.fetchLimit = 1
try? nr = coredataContext.fetch(requestNr)
}
return nr.first
}
}
13 changes: 13 additions & 0 deletions FreeAPS/Sources/Models/Version.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import Foundation

struct Version: JSON, Decodable {
var main: String
var dev: String
}

extension Version {
private enum CodingKeys: String, CodingKey {
case main
case dev
}
}
1 change: 1 addition & 0 deletions FreeAPS/Sources/Modules/Settings/SettingsStateModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ extension Settings {
private(set) var copyrightNotice = ""

override func subscribe() {
nightscoutManager.fetchVersion()
subscribeSetting(\.debugOptions, on: $debugOptions) { debugOptions = $0 }
subscribeSetting(\.closedLoop, on: $closedLoop) { closedLoop = $0 }
subscribeSetting(\.disableCGMError, on: $disableCGMError) { disableCGMError = $0 }
Expand Down
40 changes: 31 additions & 9 deletions FreeAPS/Sources/Modules/Settings/View/SettingsRootView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,43 @@ extension Settings {
@StateObject var state = StateModel()
@State private var showShareSheet = false

@FetchRequest(
entity: VNr.entity(),
sortDescriptors: [NSSortDescriptor(key: "date", ascending: false)], predicate: NSPredicate(
format: "nr != %@", "" as String
)
) var fetchedVersionNumber: FetchedResults<VNr>

var body: some View {
Form {
Section {
Toggle("Closed loop", isOn: $state.closedLoop)
}
header: {
if let expirationDate = Bundle.main.profileExpiration {
Text(
"iAPS v\(state.versionNumber) (\(state.buildNumber))\nBranch: \(state.branch) \(state.copyrightNotice)" +
"\nBuild Expires: " + expirationDate
).textCase(nil)
} else {
Text(
"iAPS v\(state.versionNumber) (\(state.buildNumber))\nBranch: \(state.branch) \(state.copyrightNotice)"
)
VStack(alignment: .leading) {
if let expirationDate = Bundle.main.profileExpiration {
Text(
"iAPS v\(state.versionNumber) (\(state.buildNumber))\nBranch: \(state.branch) \(state.copyrightNotice)" +
"\nBuild Expires: " + expirationDate
).textCase(nil)
} else {
Text(
"iAPS v\(state.versionNumber) (\(state.buildNumber))\nBranch: \(state.branch) \(state.copyrightNotice)"
)
}

if let latest = fetchedVersionNumber.first,
(latest.nr ?? "") > state
.versionNumber ||
((latest.nr ?? "") < state.versionNumber && (latest.dev ?? "") > state.versionNumber)
{
Text(
"Latest version on GitHub: " +
((latest.nr ?? "") < state.versionNumber ? (latest.dev ?? "") : (latest.nr ?? "")) + "\n"
)
.foregroundStyle(.orange).bold()
.multilineTextAlignment(.leading)
}
}
}

Expand Down
25 changes: 24 additions & 1 deletion FreeAPS/Sources/Services/Network/NightscoutAPI.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class NightscoutAPI {
static let statusPath = "/api/v1/devicestatus.json"
static let profilePath = "/api/v1/profile.json"
static let sharePath = "/upload.php"
static let versionPath = "/vcheck.php"
static let retryCount = 2
static let timeout: TimeInterval = 60
}
Expand Down Expand Up @@ -496,7 +497,7 @@ extension NightscoutAPI {
components.scheme = statURL.scheme
components.host = statURL.host
components.port = statURL.port
components.path = Config.sharePath
components.path = "/vcheck.php"

var request = URLRequest(url: components.url!)
request.allowsConstrainedNetworkAccess = false
Expand All @@ -511,6 +512,28 @@ extension NightscoutAPI {
.eraseToAnyPublisher()
}

func fetchVersion() -> AnyPublisher<Version, Swift.Error> {
let statURL = IAPSconfig.statURL
var components = URLComponents()
components.scheme = statURL.scheme
components.host = statURL.host
components.port = statURL.port
components.path = Config.versionPath

var request = URLRequest(url: components.url!)
request.allowsConstrainedNetworkAccess = true
request.timeoutInterval = Config.timeout

return service.run(request)
.retry(Config.retryCount)
.decode(type: Version.self, decoder: JSONCoding.decoder)
.catch { error -> AnyPublisher<Version, Swift.Error> in
warning(.nightscout, "Version fetching error: \(error.localizedDescription) \(request)")
return Just(Version(main: "", dev: "")).setFailureType(to: Swift.Error.self).eraseToAnyPublisher()
}
.eraseToAnyPublisher()
}

func uploadStatus(_ status: NightscoutStatus) -> AnyPublisher<Void, Swift.Error> {
var components = URLComponents()
components.scheme = url.scheme
Expand Down
22 changes: 22 additions & 0 deletions FreeAPS/Sources/Services/Network/NightscoutManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ protocol NightscoutManager: GlucoseSource {
func deleteAllNSoverrrides()
func deleteOverride()
func editOverride(_ profile: String, _ duration_: Double, _ date: Date)
func fetchVersion()
var cgmURL: URL? { get }
}

Expand Down Expand Up @@ -165,6 +166,27 @@ final class BaseNightscoutManager: NightscoutManager, Injectable {
.eraseToAnyPublisher()
}

func fetchVersion() {
guard let nightscout = nightscoutAPI, isNetworkReachable else {
return
}
processQueue.async {
nightscout.fetchVersion()
.sink { completion in
switch completion {
case .finished:
debug(.nightscout, "Version fetched from " + IAPSconfig.statURL.absoluteString)
case let .failure(error):
debug(.nightscout, error.localizedDescription)
}
}
receiveValue: { a in
CoreDataStorage().saveVNr(a)
}
.store(in: &self.lifetime)
}
}

func fetchTempTargets() -> AnyPublisher<[TempTarget], Never> {
guard let nightscout = nightscoutAPI, isNetworkReachable else {
return Just([]).eraseToAnyPublisher()
Expand Down

0 comments on commit 62d49c6

Please sign in to comment.