|
|
@@ -3,6 +3,7 @@ import LoopKit
|
|
|
import LoopKitUI
|
|
|
import SwiftUI
|
|
|
import Swinject
|
|
|
+import UIKit
|
|
|
|
|
|
extension Settings {
|
|
|
struct VersionInfo: Equatable {
|
|
|
@@ -34,6 +35,7 @@ extension Settings {
|
|
|
isDevUpdateAvailable: false
|
|
|
)
|
|
|
@State private var closedLoopDisabled = true
|
|
|
+ @State private var showCopiedToast = false
|
|
|
|
|
|
@Environment(\.colorScheme) var colorScheme
|
|
|
@EnvironmentObject var appIcons: Icons
|
|
|
@@ -98,30 +100,49 @@ extension Settings {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ private func copyVersionInfo(_ text: String) {
|
|
|
+ UIPasteboard.general.string = text
|
|
|
+ UINotificationFeedbackGenerator().notificationOccurred(.success)
|
|
|
+ withAnimation { showCopiedToast = true }
|
|
|
+ DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) {
|
|
|
+ withAnimation { showCopiedToast = false }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
var body: some View {
|
|
|
List {
|
|
|
if searchText.isEmpty {
|
|
|
let buildDetails = BuildDetails.shared
|
|
|
|
|
|
- Section(
|
|
|
- header: Text("BRANCH: \(buildDetails.branchAndSha)").textCase(nil),
|
|
|
- content: {
|
|
|
- /// The current development version of the app.
|
|
|
- ///
|
|
|
- /// Follows a semantic pattern where release versions are like `0.5.0`, and
|
|
|
- /// development versions increment with a fourth component (e.g., `0.5.0.1`, `0.5.0.2`)
|
|
|
- /// after the base release. For example:
|
|
|
- /// - After release `0.5.0` → `0.5.0`
|
|
|
- /// - First dev push → `0.5.0.1`
|
|
|
- /// - Next dev push → `0.5.0.2`
|
|
|
- /// - Next release `0.6.0` → `0.6.0`
|
|
|
- /// - Next dev push → `0.6.0.1`
|
|
|
- ///
|
|
|
- /// If the dev version is unavailable, `"unknown"` is returned.
|
|
|
- let devVersion = Bundle.main.appDevVersion ?? "unknown"
|
|
|
+ /// The current development version of the app.
|
|
|
+ ///
|
|
|
+ /// Follows a semantic pattern where release versions are like `0.5.0`, and
|
|
|
+ /// development versions increment with a fourth component (e.g., `0.5.0.1`, `0.5.0.2`)
|
|
|
+ /// after the base release. For example:
|
|
|
+ /// - After release `0.5.0` → `0.5.0`
|
|
|
+ /// - First dev push → `0.5.0.1`
|
|
|
+ /// - Next dev push → `0.5.0.2`
|
|
|
+ /// - Next release `0.6.0` → `0.6.0`
|
|
|
+ /// - Next dev push → `0.6.0.1`
|
|
|
+ ///
|
|
|
+ /// If the dev version is unavailable, `"unknown"` is returned.
|
|
|
+ let devVersion = Bundle.main.appDevVersion ?? "unknown"
|
|
|
|
|
|
- let buildNumber = Bundle.main.buildVersionNumber ?? String(localized: "Unknown")
|
|
|
+ let buildNumber = Bundle.main.buildVersionNumber ?? String(localized: "Unknown")
|
|
|
|
|
|
+ Section(
|
|
|
+ header: HStack(spacing: 4) {
|
|
|
+ Button {
|
|
|
+ copyVersionInfo(
|
|
|
+ "Trio v\(devVersion) (\(buildNumber)) \(buildDetails.branchAndSha)"
|
|
|
+ )
|
|
|
+ } label: {
|
|
|
+ Image(systemName: "doc.on.doc.fill")
|
|
|
+ }
|
|
|
+ .buttonStyle(.plain)
|
|
|
+ Text("BRANCH: \(buildDetails.branchAndSha)")
|
|
|
+ }.textCase(nil),
|
|
|
+ content: {
|
|
|
NavigationLink(destination: SubmodulesView(buildDetails: buildDetails)) {
|
|
|
HStack {
|
|
|
Image(appIcons.appIcon.rawValue)
|
|
|
@@ -310,6 +331,18 @@ extension Settings {
|
|
|
).listRowBackground(Color.chart)
|
|
|
}
|
|
|
}
|
|
|
+ .overlay(alignment: .bottom) {
|
|
|
+ if showCopiedToast {
|
|
|
+ Label("Copied", systemImage: "checkmark.circle.fill")
|
|
|
+ .font(.footnote.weight(.semibold))
|
|
|
+ .foregroundColor(.white)
|
|
|
+ .padding(.horizontal, 16)
|
|
|
+ .padding(.vertical, 10)
|
|
|
+ .background(.ultraThinMaterial, in: Capsule())
|
|
|
+ .padding(.bottom, 32)
|
|
|
+ .transition(.move(edge: .bottom).combined(with: .opacity))
|
|
|
+ }
|
|
|
+ }
|
|
|
.scrollContentBackground(.hidden).background(appState.trioBackgroundColor(for: colorScheme))
|
|
|
.sheet(isPresented: $shouldDisplayHint) {
|
|
|
SettingInputHintView(
|