diff --git a/AppDebugMode-iOS-Sample/AppDebugMode-iOS-Sample/Application/AppDelegate.swift b/AppDebugMode-iOS-Sample/AppDebugMode-iOS-Sample/Application/AppDelegate.swift index 8f1a25d..9a2a0bd 100644 --- a/AppDebugMode-iOS-Sample/AppDebugMode-iOS-Sample/Application/AppDelegate.swift +++ b/AppDebugMode-iOS-Sample/AppDebugMode-iOS-Sample/Application/AppDelegate.swift @@ -5,7 +5,7 @@ // Created by Lukas Kubaliak on 14/09/2023. // -import UIKit +import SwiftUI #if DEBUG import AppDebugMode #endif @@ -16,18 +16,23 @@ class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? private var dependencyContainer = DependencyContainer() + #if DEBUG + var model: CustomControlsModel = CustomControlsModel() + #endif + func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { window = UIWindow() - + #if DEBUG AppDebugModeProvider.shared.setup( serversCollections: Constants.ServersCollections.allClases, onServerChange: { debugPrint("Server has been changed") }, - cacheManager: dependencyContainer.cacheManager + cacheManager: dependencyContainer.cacheManager, + customControls: { CustomControlsView(model: model) } ) #endif @@ -38,3 +43,35 @@ class AppDelegate: UIResponder, UIApplicationDelegate { } +#if DEBUG +final class CustomControlsModel: ObservableObject { + + @Published var isOn: Bool = false + +} + +struct CustomControlsView: View { + + @ObservedObject var model: CustomControlsModel + + var body: some View { + VStack(spacing: 20) { + Button { + print("IsOn: \(model.isOn)") + } label: { + Text("Print is on: \(model.isOn)") + } + + Toggle("Toggle is on", isOn: $model.isOn) + Toggle("Toggle is on", isOn: $model.isOn) + + NavigationLink { + Text("Hello") + } label: { + Text("Click me") + } + } + } + +} +#endif diff --git a/Sources/AppDebugMode/Providers/AppDebugModeProvider.swift b/Sources/AppDebugMode/Providers/AppDebugModeProvider.swift index 9f6278e..d515e21 100644 --- a/Sources/AppDebugMode/Providers/AppDebugModeProvider.swift +++ b/Sources/AppDebugMode/Providers/AppDebugModeProvider.swift @@ -13,7 +13,7 @@ public final class AppDebugModeProvider { // MARK: - Singleton public static let shared = AppDebugModeProvider() - + // MARK: - Initialization private init() {} @@ -24,6 +24,10 @@ public final class AppDebugModeProvider { internal var serversCollections: [ApiServerCollection] = [] internal var onServerChange: (() -> Void)? internal var pushNotificationsProvider: PushNotificationsProvider? + internal var customControls: any View = EmptyView() + internal var customControlsViewIsVisible: Bool { + !(customControls is EmptyView) + } // MARK: - Public - Variables @@ -50,11 +54,19 @@ public final class AppDebugModeProvider { public extension AppDebugModeProvider { + /// Setup the AppDebugModeProvider with the given parameters. + /// - Parameters: + /// - serversCollections: The collections of servers to be displayed in the app debug mode. + /// - onServerChange: The closure to be called when the server is changed. + /// - cacheManager: The cache manager to be used in the app debug mode. + /// - firebaseMessaging: The Firebase Messaging to be used in the app debug mode. + /// - customControls: The custom controls to be displayed in the app debug mode. func setup( serversCollections: [ApiServerCollection] = [], onServerChange: (() -> Void)? = nil, cacheManager: Any? = nil, - firebaseMessaging: AnyObject? = nil + firebaseMessaging: AnyObject? = nil, + @ViewBuilder customControls: () -> some View = { EmptyView() } ) { self.serversCollections = serversCollections self.onServerChange = onServerChange @@ -70,6 +82,7 @@ public extension AppDebugModeProvider { if StandardOutputService.shared.shouldRedirectLogsToAppDebugMode { StandardOutputService.shared.redirectLogsToAppDebugMode() } + self.customControls = customControls() } func getSelectedServer(for serverCollection: ApiServerCollection) -> ApiServer { @@ -77,8 +90,11 @@ public extension AppDebugModeProvider { } func start() -> UIViewController { - let viewController = AppDebugView(serversCollections: AppDebugModeProvider.shared.serversCollections) - .eraseToUIViewController() + let viewController = AppDebugView( + serversCollections: AppDebugModeProvider.shared.serversCollections, + customControls: AnyView( AppDebugModeProvider.shared.customControls), + customControlsViewIsVisible: AppDebugModeProvider.shared.customControlsViewIsVisible + ).eraseToUIViewController() let navigationController = UINavigationController(rootViewController: viewController) navigationController.navigationBar.configureSolidAppearance() diff --git a/Sources/AppDebugMode/Views/AppDebugView.swift b/Sources/AppDebugMode/Views/AppDebugView.swift index 498ac05..56ee81e 100644 --- a/Sources/AppDebugMode/Views/AppDebugView.swift +++ b/Sources/AppDebugMode/Views/AppDebugView.swift @@ -7,15 +7,17 @@ import SwiftUI -struct AppDebugView: View { - +struct AppDebugView: View { + @Environment(\.presentationMode) var presentationMode @Environment(\.hostingControllerHolder) var viewControlleeHolder // MARK: - Properties private var screens: [Screen] - + let customControls: CustomControls + let customControlsViewIsVisible: Bool + struct Screen { let title: String @@ -26,7 +28,7 @@ struct AppDebugView: View { // MARK: - Init - init(serversCollections: [ApiServerCollection]) { + init(serversCollections: [ApiServerCollection], customControls: CustomControls, customControlsViewIsVisible: Bool) { self.screens = [] if !AppDebugModeProvider.shared.serversCollections.isEmpty { @@ -83,6 +85,9 @@ struct AppDebugView: View { destination: AnyView(ConsoleLogsView()) ) ]) + + self.customControls = customControls + self.customControlsViewIsVisible = customControlsViewIsVisible } @@ -121,6 +126,9 @@ private extension AppDebugView { func appDebugViewList() -> some View { List { settingsSection() + if customControlsViewIsVisible { + customControlsSection() + } dangerZoneSection() } .listStyle(.insetGrouped) @@ -159,7 +167,19 @@ private extension AppDebugView { .foregroundColor(AppDebugColors.textSecondary) } } - + + func customControlsSection() -> some View { + Section { + customControls + .foregroundColor(AppDebugColors.textPrimary) + .buttonStyle(ButtonControlStyle()) + .listRowBackground(AppDebugColors.backgroundSecondary) + } header: { + Text("Custom controls") + .foregroundColor(AppDebugColors.textSecondary) + } + } + func dangerZoneSection() -> some View { Section { ResetAppView() diff --git a/Sources/AppDebugMode/Views/Buttons/Styles/ButtonControlStyle.swift b/Sources/AppDebugMode/Views/Buttons/Styles/ButtonControlStyle.swift new file mode 100644 index 0000000..5320d8b --- /dev/null +++ b/Sources/AppDebugMode/Views/Buttons/Styles/ButtonControlStyle.swift @@ -0,0 +1,21 @@ +// +// ButtonControlStyle.swift +// +// +// Created by Matus Klasovity on 20/05/2024. +// + +import SwiftUI + +struct ButtonControlStyle: ButtonStyle { + + func makeBody(configuration: Configuration) -> some View { + configuration.label + .padding(.vertical, 12) + .frame(maxWidth: .infinity, alignment: .center) + .background(configuration.isPressed ? AppDebugColors.primary.opacity(0.5) : AppDebugColors.primary) + .cornerRadius(8) + .foregroundColor(AppDebugColors.black) + } + +}