Files
QuickDrop/QuickDrop/View/UserManual/TutorialView.swift
T

203 lines
6.8 KiB
Swift

//
// TutorialView.swift
// QuickDrop
//
// Created by Leon Böttger on 05.03.25.
//
import AppKit
import LUI
import SwiftUI
struct TutorialView: View {
let tab: Tab
let openPlus: () -> Void
let openAppAdvertisementView: () -> Void
@State private var licenseWindow: NSWindow?
@ObservedObject var iapManager = IAPManager.sharedInstance
var body: some View {
LargeAppIconView(title: tab.title) {
VStack {
Group {
if tab == .troubleshooting {
FAQView(faqItems: [
.init(question: "FaqNotVisibleOrConnectingQuestion", answer: "FaqNotVisibleOrConnectingAnswer"),
.init(question: "FaqPhotoDateNotPreservedQuestion", answer: "FaqPhotoDateNotPreservedAnswer"),
.init(question: "FaqAndroidDeviceNotVisibleQuestion", answer: "FaqAndroidDeviceNotVisibleAnswer"),
.init(question: "FaqTrustedDevicesQuestion", answer: "FaqTrustedDevicesAnswer"),
.init(question: "MultipleFilesSendingQuestion", answer: "MultipleFilesSendingAnswer"),
.init(question: "FaqBugQuestion", answer: "FaqBugAnswer"),
])
.padding(.top)
}
else {
Text(tab.text.localized())
.multilineTextAlignment(.leading)
.fixedSize(horizontal: false, vertical: true)
.padding()
}
}
.frame(width: 550)
if tab == .receive {
HStack(spacing: 30) {
Button {
licenseWindow = openLicenseWindow()
} label: {
Text("Acknowledgements")
.underline()
.font(.footnote)
.opacity(0.5)
}
.buttonStyle(.plain)
#if !GITHUB
if !iapManager.plusVersionState {
Button {
openPlus()
} label: {
Text("SupportQuickDrop")
.underline()
.font(.footnote)
.opacity(0.5)
}
.buttonStyle(.plain)
}
#endif
#if DEBUG
Button {
IAPManager.sharedInstance.plusVersionState = false
Settings.sharedInstance.deleteAllUserDefaults()
} label: {
Text("ResetAllSettings")
.underline()
.font(.footnote)
.opacity(0.5)
}
.buttonStyle(.plain)
#endif
}
.padding()
}
else if tab == .send {
EnableExtensionView()
}
else if tab == .notificationSync {
Button {
openAppAdvertisementView()
} label: {
Text("DownloadMobileApp".localized())
}
.buttonStyle(.borderedProminent)
.padding()
}
}
}
}
}
struct EnableExtensionView: View {
@State private var showSharePicker = false
@State private var shareItems: [Any] = []
@State private var isExtensionEnabled = false
@State private var showSuccessCheckmark = false
@State private var animateCheckmark = false
private let timer = Timer.publish(every: 1.0, on: .main, in: .common).autoconnect()
init(canShowIntialCheckmark: Bool = false) {
let isEnabled = Self.isEnabled()
_isExtensionEnabled = State(initialValue: isEnabled)
if canShowIntialCheckmark && isEnabled {
_showSuccessCheckmark = State(initialValue: true)
_animateCheckmark = State(initialValue: true)
}
}
var body: some View {
if !isExtensionEnabled {
Button("EnableQuickDropExtension".localized()) {
shareItems = [
"EnableQuickDropExtensionDescription".localized()
]
showSharePicker = true
}
.background(
SharingPickerPresenter(
isPresented: $showSharePicker,
sharingItems: shareItems
)
)
.padding()
.onReceive(timer) { _ in
updateEnabledState()
}
}
else if showSuccessCheckmark {
Image(systemName: "checkmark.circle.fill")
.font(.system(size: 20))
.foregroundColor(.green)
.background(Circle().foregroundColor(.white).frame(width: 18, height: 18))
.scaleEffect(animateCheckmark ? 1.0 : 0.5)
.animation(.easeOut(duration: 0.4), value: animateCheckmark)
.onAppear {
animateCheckmark = true
}
.padding()
}
}
private func updateEnabledState() {
let enabled = Self.isEnabled()
if enabled != isExtensionEnabled {
withAnimation(.smooth) {
isExtensionEnabled = enabled
if enabled {
showSuccessCheckmark = true
}
}
}
}
private static func isEnabled() -> Bool {
NSSharingService(
named: NSSharingService.Name("com.leonboettger.neardrop.ShareExtension")
) != nil
}
}
private struct SharingPickerPresenter: NSViewRepresentable {
@Binding var isPresented: Bool
let sharingItems: [Any]
func makeNSView(context: Context) -> NSView { NSView() }
func updateNSView(_ nsView: NSView, context: Context) {
guard isPresented else { return }
let picker = NSSharingServicePicker(items: sharingItems)
DispatchQueue.main.async {
picker.show(relativeTo: nsView.bounds, of: nsView, preferredEdge: .minY)
isPresented = false
}
}
}
#Preview {
WelcomeScreen(openPlusScreen: {}, openAppAdvertisementView: {}, openCableTransmissionView: {}, checkForNetworkIssues: {})
}