| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291 |
- // LoopFollow
- // ImportExportSettingsView.swift
- import AVFoundation
- import SwiftUI
- import UIKit
- struct ImportExportSettingsView: View {
- @StateObject private var viewModel = ImportExportSettingsViewModel()
- var body: some View {
- NavigationView {
- List {
- // MARK: - Import Section
- Section("Import Settings") {
- Button(action: {
- viewModel.isShowingQRCodeScanner = true
- }) {
- HStack {
- Image(systemName: "qrcode.viewfinder")
- .foregroundColor(.blue)
- Text("Scan QR Code to Import Settings")
- }
- }
- .buttonStyle(.plain)
- }
- // MARK: - Export Section
- Section("Export Settings To QR Code") {
- ForEach(ImportExportSettingsViewModel.ExportType.allCases, id: \.self) { exportType in
- Button(action: {
- if exportType == .alarms {
- viewModel.showAlarmSelection()
- } else {
- viewModel.exportType = exportType
- if let qrString = viewModel.generateQRCodeForExport() {
- viewModel.qrCodeString = qrString
- viewModel.isShowingQRCodeDisplay = true
- }
- }
- }) {
- HStack {
- Image(systemName: exportType.icon)
- .foregroundColor(.blue)
- Text("Export \(exportType.rawValue)")
- Spacer()
- Image(systemName: exportType == .alarms ? "list.bullet" : "qrcode")
- .foregroundColor(.secondary)
- }
- }
- .buttonStyle(.plain)
- }
- }
- // MARK: - Status Message
- if !viewModel.qrCodeErrorMessage.isEmpty {
- Section {
- let isSuccess = viewModel.qrCodeErrorMessage.contains("successfully") || viewModel.qrCodeErrorMessage.contains("Successfully imported")
- let displayText = isSuccess ? "✅ \(viewModel.qrCodeErrorMessage)" : viewModel.qrCodeErrorMessage
- Text(displayText)
- .foregroundColor(isSuccess ? .green : .red)
- .font(.caption)
- }
- }
- }
- .navigationTitle("Import/Export Settings")
- .navigationBarTitleDisplayMode(.inline)
- }
- .sheet(isPresented: $viewModel.isShowingQRCodeScanner) {
- SimpleQRCodeScannerView { result in
- viewModel.handleQRCodeScanResult(result)
- }
- }
- .sheet(isPresented: $viewModel.isShowingQRCodeDisplay) {
- NavigationView {
- VStack {
- if !viewModel.qrCodeString.isEmpty {
- QRCodeDisplayView(
- qrCodeString: viewModel.qrCodeString,
- size: CGSize(width: 300, height: 300)
- )
- .padding()
- Text("Scan this QR code with another LoopFollow app to import \(viewModel.exportType.rawValue.lowercased())")
- .font(.caption)
- .foregroundColor(.secondary)
- .multilineTextAlignment(.center)
- .padding(.horizontal, 20)
- } else {
- Text("Failed to generate QR code")
- .foregroundColor(.red)
- .padding()
- }
- }
- .navigationTitle("Export \(viewModel.exportType.rawValue)")
- .navigationBarTitleDisplayMode(.inline)
- .navigationBarItems(trailing: Button("Close") {
- viewModel.isShowingQRCodeDisplay = false
- })
- }
- }
- .sheet(isPresented: $viewModel.isShowingAlarmSelection) {
- AlarmSelectionView(
- exportedAlarmIds: viewModel.exportedAlarmIds,
- onConfirm: { selectedAlarms in
- viewModel.exportSelectedAlarms(selectedAlarms)
- },
- onCancel: {
- viewModel.cancelAlarmSelection()
- }
- )
- }
- .onDisappear {
- viewModel.resetExportedAlarms()
- }
- .sheet(isPresented: $viewModel.showImportConfirmation) {
- ImportConfirmationView(viewModel: viewModel)
- }
- }
- }
- struct ImportConfirmationView: View {
- @ObservedObject var viewModel: ImportExportSettingsViewModel
- var body: some View {
- NavigationView {
- VStack(spacing: 20) {
- // Header
- VStack(spacing: 8) {
- Image(systemName: "square.and.arrow.down")
- .font(.system(size: 50))
- .foregroundColor(.blue)
- Text("Import Settings")
- .font(.title2)
- .fontWeight(.semibold)
- Text("Review the settings that will be imported")
- .font(.subheadline)
- .foregroundColor(.secondary)
- .multilineTextAlignment(.center)
- }
- .padding(.top, 20)
- // Settings Preview
- if let preview = viewModel.importPreview {
- VStack(alignment: .leading, spacing: 16) {
- Text("Settings to Import")
- .font(.headline)
- .padding(.horizontal)
- VStack(spacing: 12) {
- if let url = preview.nightscoutURL, !url.isEmpty {
- SettingRowView(
- icon: "network",
- title: "Nightscout URL",
- value: url,
- color: .blue
- )
- }
- if let username = preview.dexcomUsername, !username.isEmpty {
- SettingRowView(
- icon: "person.circle",
- title: "Dexcom Username",
- value: username,
- color: .green
- )
- }
- if let remoteType = preview.remoteType, !remoteType.isEmpty, remoteType != "None" {
- SettingRowView(
- icon: "antenna.radiowaves.left.and.right",
- title: "Remote Type",
- value: remoteType,
- color: .orange
- )
- }
- if preview.alarmCount > 0 {
- SettingRowView(
- icon: "bell",
- title: "Alarms",
- value: "\(preview.alarmCount) alarm(s): \(preview.alarmNames.joined(separator: ", "))",
- color: .red
- )
- }
- }
- .padding(.horizontal)
- }
- }
- // Warning
- VStack(spacing: 8) {
- HStack {
- Image(systemName: "exclamationmark.triangle")
- .foregroundColor(.orange)
- Text("Warning")
- .fontWeight(.semibold)
- .foregroundColor(.orange)
- }
- Text("This will overwrite your current settings")
- .font(.subheadline)
- .foregroundColor(.secondary)
- .multilineTextAlignment(.center)
- }
- .padding(.horizontal)
- Spacer()
- // Action Buttons
- VStack(spacing: 12) {
- Button(action: {
- viewModel.confirmImport()
- }) {
- HStack {
- Image(systemName: "checkmark")
- Text("Import Settings")
- }
- .font(.headline)
- .foregroundColor(.white)
- .frame(maxWidth: .infinity)
- .padding()
- .background(Color.blue)
- .cornerRadius(12)
- }
- Button(action: {
- viewModel.cancelImport()
- }) {
- HStack {
- Image(systemName: "xmark")
- Text("Cancel")
- }
- .font(.headline)
- .foregroundColor(.primary)
- .frame(maxWidth: .infinity)
- .padding()
- .background(Color(.systemGray6))
- .cornerRadius(12)
- }
- }
- .padding(.horizontal)
- .padding(.bottom, 20)
- }
- .navigationBarHidden(true)
- }
- }
- }
- struct SettingRowView: View {
- let icon: String
- let title: String
- let value: String
- let color: Color
- var body: some View {
- HStack(spacing: 12) {
- Image(systemName: icon)
- .font(.title2)
- .foregroundColor(color)
- .frame(width: 30)
- VStack(alignment: .leading, spacing: 2) {
- Text(title)
- .font(.subheadline)
- .fontWeight(.medium)
- Text(value)
- .font(.caption)
- .foregroundColor(.secondary)
- .lineLimit(2)
- }
- Spacer()
- }
- .padding()
- .background(Color(.systemGray6))
- .cornerRadius(10)
- }
- }
- #Preview {
- ImportExportSettingsView()
- }
|