Skip to content

Commit

Permalink
Merge pull request #33 from GoodRequest/feature/debugman
Browse files Browse the repository at this point in the history
feat: Debugman Integration
  • Loading branch information
matusklasovity authored Jun 7, 2024
2 parents 3e7383f + 2a1b2c3 commit 6dbaf1e
Show file tree
Hide file tree
Showing 13 changed files with 486 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSBonjourServices</key>
<array>
<string>_Debugman._tcp</string>
</array>
<key>NSLocalNetworkUsageDescription</key>
<string>Test</string>
<key>CFBundleDocumentTypes</key>
<array>
<dict>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,21 @@ final class RequestManager: RequestManagerType {
#if DEBUG
StandardOutputService.shared.connectCustomLogStreamPublisher(monitor.subscribeToMessages())
#endif
session = NetworkSession(baseUrl: baseServer.rawValue, configuration: .init(urlSessionConfiguration: .default, interceptor: nil, serverTrustManager: nil, eventMonitors: [monitor]))

#if DEBUG
let urlSessionConfig = AppDebugModeProvider.shared.proxySettingsProvider.urlSessionConfiguration
#else
let urlSessionConfig = URLSessionConfiguration.default
#endif

session = NetworkSession(
baseUrl: baseServer.rawValue,
configuration: NetworkSessionConfiguration(
urlSessionConfiguration: urlSessionConfig,
interceptor: nil,
eventMonitors: [monitor]
)
)
}

func fetchLarge() -> AnyPublisher<LargeObjectResponse, AFError> {
Expand Down
29 changes: 29 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,35 @@ if StandardOutputService.shared.shouldRedirectLogsToAppDebugView {

#endif
```

## Debugman connection
If you want to enable app to send logs to Debugman you need to add following to your Info.plist file.
```xml
<key>NSBonjourServices</key>
<array>
<string>_Debugman._tcp</string>
</array>
<key>NSLocalNetworkUsageDescription</key>
<string>Proxy and debugger connection when running in DEBUG mode</string>
```

To enable proxy for Debugman you need to add AppDebugMode Proxy URL Sessiion Config to your Network session.
```swift
#if DEBUG
let urlSessionConfig = AppDebugModeProvider.shared.proxySettingsProvider.urlSessionConfiguration
#else
let urlSessionConfig = URLSessionConfiguration.default
#endif

session = NetworkSession(
baseUrl: baseServer.rawValue,
configuration: NetworkSessionConfiguration(
urlSessionConfiguration: urlSessionConfig,
interceptor: nil,
eventMonitors: [monitor]
)
)
```

## Activation in App
- In app you can activate debug mode by shaking device or in simulator by `CMD + CTRL + Z`
Expand Down
13 changes: 10 additions & 3 deletions Sources/AppDebugMode/Providers/AppDebugModeProvider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public final class AppDebugModeProvider {

// MARK: - Internal - Variables

internal let connectionManager = ConnectionsManager()
internal var servers: [ApiServer] = []
internal var serversCollections: [ApiServerCollection] = []
internal var onServerChange: (() -> Void)?
Expand All @@ -39,7 +40,11 @@ public final class AppDebugModeProvider {
public var selectedUserProfile: UserProfile? {
UserProfilesProvider.shared.selectedUserProfile
}


public var proxySettingsProvider: ProxySettingsProvider {
ProxySettingsProvider.shared
}

@available(*, deprecated, renamed: "selectedUserProfilePublisher")
public var selectedTestingUserPublisher = UserProfilesProvider.shared.selectedUserProfilePublisher
public var selectedUserProfilePublisher = UserProfilesProvider.shared.selectedUserProfilePublisher
Expand Down Expand Up @@ -94,8 +99,10 @@ public extension AppDebugModeProvider {
serversCollections: AppDebugModeProvider.shared.serversCollections,
customControls: AnyView( AppDebugModeProvider.shared.customControls),
customControlsViewIsVisible: AppDebugModeProvider.shared.customControlsViewIsVisible
).eraseToUIViewController()

)
.environmentObject(connectionManager)
.eraseToUIViewController()

let navigationController = UINavigationController(rootViewController: viewController)
navigationController.navigationBar.configureSolidAppearance()
return navigationController
Expand Down
94 changes: 94 additions & 0 deletions Sources/AppDebugMode/Providers/ConnectionsManager.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
//
// ConnectionsManager.swift
//
//
// Created by Matus Klasovity on 21/05/2024.
//

import Foundation
import MultipeerConnectivity

final class ConnectionsManager: NSObject, ObservableObject {

let session: MCSession
let browser: MCNearbyServiceBrowser

@Published var connectedPeers: [MCPeerID] = []

override init() {
let appName = Bundle.main.infoDictionary?[kCFBundleNameKey as String] as? String
let peer = MCPeerID(
displayName: UIDevice.current.name + " - " + (appName ?? "")
)

browser = MCNearbyServiceBrowser(
peer: peer,
serviceType: "Debugman"
)
session = MCSession(
peer: peer,
securityIdentity: nil,
encryptionPreference: .none
)
super.init()

session.delegate = self
}

func cancelConnection(to peer: MCPeerID) {
session.cancelConnectPeer(peer)
}

func sendToAllPeers(message: String) {
guard !session.connectedPeers.isEmpty else { return }

let data = Data(message.utf8)
do {
try session.send(data, toPeers: session.connectedPeers, with: .reliable)
} catch {
print("error sending data to peers: \(error)")
}
}

}


extension ConnectionsManager: MCSessionDelegate {

func session(_ session: MCSession, peer peerID: MCPeerID, didChange state: MCSessionState) {
switch state {
case .notConnected:
print("not connected to peer: \(peerID.displayName)")

case .connecting:
print("connecting to peer: \(peerID.displayName)")

case .connected:
print("connected to peer: \(peerID.displayName)")

@unknown default:
print("unknown state: \(state)")
}

DispatchQueue.main.async { [weak self] in
self?.connectedPeers = session.connectedPeers
}
}

func session(_ session: MCSession, didReceive data: Data, fromPeer peerID: MCPeerID) {
print("received data from peer: \(peerID)")
}

func session(_ session: MCSession, didReceive stream: InputStream, withName streamName: String, fromPeer peerID: MCPeerID) {
print("received stream from peer: \(peerID)")
}

func session(_ session: MCSession, didStartReceivingResourceWithName resourceName: String, fromPeer peerID: MCPeerID, with progress: Progress) {
print("started receiving resource from peer: \(peerID)")
}

func session(_ session: MCSession, didFinishReceivingResourceWithName resourceName: String, fromPeer peerID: MCPeerID, at localURL: URL?, withError error: (any Error)?) {
print("finished receiving resource from peer: \(peerID)")
}

}
40 changes: 40 additions & 0 deletions Sources/AppDebugMode/Providers/ProxySettingsProvider.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
//
// ProxySettingsProvider.swift
//
//
// Created by Matus Klasovity on 28/05/2024.
//

import Foundation
import GoodPersistence

public final class ProxySettingsProvider {

@UserDefaultValue("proxyIpAdress", defaultValue: "")
var proxyIpAdress: String

@UserDefaultValue("proxyPort", defaultValue: 8080)
var proxyPort: Int

public static let shared = ProxySettingsProvider()

public var urlSessionConfiguration: URLSessionConfiguration {
let urlSessionConfig = URLSessionConfiguration.default
urlSessionConfig.connectionProxyDictionary = [AnyHashable: Any]()
urlSessionConfig.connectionProxyDictionary?[kCFNetworkProxiesHTTPEnable as String] = 1
urlSessionConfig.connectionProxyDictionary?[kCFNetworkProxiesHTTPProxy as String] = proxyIpAdress
urlSessionConfig.connectionProxyDictionary?[kCFNetworkProxiesHTTPPort as String] = proxyPort
urlSessionConfig.connectionProxyDictionary?["HTTPSProxy"] = proxyIpAdress
urlSessionConfig.connectionProxyDictionary?["HTTPSPort"] = proxyPort

return urlSessionConfig
}

func updateProxySettings(ipAddress: String, port: Int) {
proxyIpAdress = ipAddress
proxyPort = port

exit(0)
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
//
// ConnectedPeersView.swift
//
//
// Created by Matus Klasovity on 28/05/2024.
//

import SwiftUI
import MultipeerConnectivity

struct ConnectedPeersView: View {

@State var isBrowserPresented: Bool = false
@EnvironmentObject var connectionsManager: ConnectionsManager

var body: some View {
Group {
if connectionsManager.connectedPeers.isEmpty {
Text("No connected peers")
.foregroundColor(AppDebugColors.textPrimary)
}

ForEach(connectionsManager.connectedPeers, id: \.displayName) { connectedPeer in
Text(connectedPeer.displayName)

.foregroundColor(AppDebugColors.textPrimary)
}
.onDelete { offset in
for index in offset {
connectionsManager.cancelConnection(to: connectionsManager.connectedPeers[index])
}
}

ButtonFilled(text: "Open browser") {
isBrowserPresented = true
}
.sheet(isPresented: $isBrowserPresented) {
BrowserRepresentableViewController(
browser: connectionsManager.browser,
session: connectionsManager.session
)
}
}
}

}

// MARK: - BrowserRepresentableViewController

private struct BrowserRepresentableViewController: UIViewControllerRepresentable {

let browser: MCNearbyServiceBrowser
let session: MCSession

func makeUIViewController(context: Context) -> UIViewController {
let viewController = MCBrowserViewController(
browser: browser,
session: session
)
viewController.delegate = context.coordinator

return viewController
}

func updateUIViewController(_ uiViewController: UIViewController, context: Context) {}

func makeCoordinator() -> Coordinator {
Coordinator()
}

final class Coordinator: NSObject, MCBrowserViewControllerDelegate {

func browserViewControllerDidFinish(_ browserViewController: MCBrowserViewController) {
browserViewController.dismiss(animated: true)
}

func browserViewControllerWasCancelled(_ browserViewController: MCBrowserViewController) {
browserViewController.dismiss(animated: true)
}

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
//
// ConnectionsSettingsView.swift
//
//
// Created by Matus Klasovity on 21/05/2024.
//

import SwiftUI

struct ConnectionsSettingsView: View {

var body: some View {
List {
connectedPeersSection()
proxySettingsSection()
}
.navigationTitle("Connections")
.listStyle(.insetGrouped)
.listBackgroundColor(AppDebugColors.backgroundPrimary, for: .insetGrouped)
}

}

// MARK: - Components

private extension ConnectionsSettingsView {

func connectedPeersSection() -> some View {
Section {
ConnectedPeersView()
.listRowSeparatorColor(AppDebugColors.primary, for: .insetGrouped)
.listRowBackground(AppDebugColors.backgroundSecondary)
} header: {
Text("Connected peers")
.foregroundColor(AppDebugColors.textSecondary)
}
}

func proxySettingsSection() -> some View {
Section {
ProxySettingsView()
.listRowBackground(AppDebugColors.backgroundSecondary)
.foregroundColor(AppDebugColors.textPrimary)
} header: {
Text("Proxy settings")
.foregroundColor(AppDebugColors.textSecondary)
}
}

}
Loading

0 comments on commit 6dbaf1e

Please sign in to comment.