Improve iOS introduction

This commit is contained in:
Leon Böttger committed 2025-11-15 15:06:14 +01:00
1 parent 1256b91d4f
commit 41b6eb8e3a
7 files changed
+567 -36

No files matched your search

+29 -23
View File
@@ -32,6 +32,8 @@ struct ContentView: View {
NavigationLinkLabel(imageName: "checkmark.shield.fill", text: "ManageTrustedDevices", backgroundColor: .green)
}
}
}, firstIntroductionView: {
LocalNetworkPermissionView()
})
}
}
@@ -44,6 +46,7 @@ struct DeviceListView: View {
#if !EXTENSION
@StateObject var receiveModel = ReceiveModel(controlPlusScreen: { show in
log("[DeviceListView] Setting showPlusScreen to \(show)")
errorVibration()
DeviceListViewModel.sharedInstance.showPlusScreen = show
})
#endif
@@ -62,36 +65,39 @@ struct DeviceListView: View {
BottomBarView(header: "QuickDrop", navigationBarLayout: isShareExtension() ? .SmallOnlyAlways : .Default, bottomViewHeight: 30) {
VStack {
VStack(alignment: .leading, spacing: 8) {
let attachments = nearbyConnectionManager.attachments
FormHeader(name: attachments == nil ? "YouAreVisibleAs".localized() : "YouAreSending".localized())
HStack {
if nearbyConnectionManager.hasLocalNetworkPermission {
VStack(alignment: .leading, spacing: 8) {
if let image = attachments?.previewImage {
image
.resizable()
.scaledToFill()
.frame(width: 10, height: 10)
let attachments = nearbyConnectionManager.attachments
FormHeader(name: attachments == nil ? "YouAreVisibleAs".localized() : "YouAreSending".localized())
HStack {
if let image = attachments?.previewImage {
image
.resizable()
.scaledToFill()
.frame(width: 10, height: 10)
}
LUIText(attachments?.shortDescription ?? NearbyConnectionManager.shared.deviceInfo.name ?? "Unknown".localized(), isBold: true)
.lineLimit(1)
}
LUIText(attachments?.shortDescription ?? NearbyConnectionManager.shared.deviceInfo.name ?? "Unknown".localized(), isBold: true)
.lineLimit(1)
.padding(.horizontal, 16)
.padding(.vertical, 6)
.background(sheetActive ? Color.sheetForegroundColor : Color.defaultForegroundColor)
.cornerRadius(24)
}
.padding(.horizontal, 16)
.padding(.vertical, 6)
.background(sheetActive ? Color.sheetForegroundColor : Color.defaultForegroundColor)
.cornerRadius(24)
.padding(.horizontal)
.padding(.top, 8)
.frame(maxWidth: .infinity, alignment: .leading)
}
.padding(.horizontal)
.padding(.top, 8)
.frame(maxWidth: .infinity, alignment: .leading)
if !nearbyConnectionManager.hasLocalNetworkPermission {
CardView(backgroundColor: .red, title: "NoNetworkAccess", titleSymbol: "network.slash") {
CardSubView(symbol: "exclamationmark.triangle.fill", text: "NoLocalNetworkAccessDescription")
LUIText("NoLocalNetworkAccessDescription", color: .white)
.frame(maxWidth: .infinity, alignment: .leading)
}
.padding(.bottom, 10)
.onTapGesture {
@@ -0,0 +1,52 @@
//
// LocalNetworkPermissionView.swift
// QuickDrop
//
// Created by Leon Böttger on 15.11.25.
//
import SwiftUI
import LUI
public struct LocalNetworkPermissionView: View {
@State var requestedLocalNetworkAccess = false
@Environment(\.scenePhase) var scenePhase
public var body: some View {
PermissionView(title: "introduction_local_network_access", symbol: "", subtitle: "introduction_local_network_access_description", permissionAction: {
if requestedLocalNetworkAccess {
// Something went wrong, user pressed again on continue. In this case, just continue with setup
IntroductionViewController.sharedInstance.canProceed = true
}
else {
// init manager to force local network access prompt
requestedLocalNetworkAccess = true
let manager = NearbyConnectionManager.shared
manager.startDeviceDiscovery()
}
}, canSkip: false, nextView: {
IntroductionDoneView()
}, nextViewSkip: {}, frontMockup: {
AppMockupFrontView()
}, backMockup: {
SymbolMockupView(symbol: "globe")
})
.onChange(of: scenePhase) { newValue in
// alert was removed from screen, app is foreground again -> continue with intro
if newValue == .active && requestedLocalNetworkAccess {
IntroductionViewController.sharedInstance.canProceed = true
}
}
}
}
#Preview {
NavigationView {
LocalNetworkPermissionView()
}
}
+10 -9
View File
@@ -76,7 +76,7 @@ final class ProgressAlert {
// MARK: - Update Progress
// progress: 0…1 → update progress, nil → finished
func updateProgress(_ progress: Double?, onCancel: @escaping () -> Void, completion: @escaping () -> Void = {}) {
func updateProgress(_ progress: Double?, onCancel: @escaping () -> Void, completion: @escaping () -> Void) {
// No progress to show, nothing shown currently → just complete
if progressAlert == nil && progress == nil {
@@ -86,21 +86,22 @@ final class ProgressAlert {
DispatchQueue.main.async {
// Show progress if not shown yet
if self.progressAlert == nil {
self.showProgressAlert(onCancel: onCancel)
}
if let p = progress {
// Show progress if not shown yet
if self.progressAlert == nil {
self.showProgressAlert(onCancel: onCancel)
}
self.progressView?.setProgress(Float(p), animated: true)
completion()
} else {
}
else {
// Completed: dismiss progress and show final alert
self.progressAlert?.dismiss(animated: true) {
completion()
self.progressAlert = nil
self.progressView = nil
}
self.progressAlert = nil
self.progressView = nil
}
}
}