From 4166d82875dcb224d3d67b9e5d01f58f7c7d22d2 Mon Sep 17 00:00:00 2001 From: Navan Chauhan Date: Wed, 3 Jan 2024 01:03:50 +0530 Subject: add telemetrydeck and format --- iGopherBrowser.xcodeproj/project.pbxproj | 162 ++++++++++++++++++++- .../xcshareddata/swiftpm/Package.resolved | 9 ++ .../xcshareddata/xcschemes/iGopherBrowser.xcscheme | 90 ++++++++++++ .../xcschemes/iGopherBrowserUITests.xcscheme | 69 +++++++++ .../xcschemes/xcschememanagement.plist | 23 +++ iGopherBrowser/BrowserView.swift | 137 ++++++++++++++--- iGopherBrowser/ContentView.swift | 8 +- iGopherBrowser/FileView.swift | 22 ++- iGopherBrowser/SettingsView.swift | 80 ++++++++++ iGopherBrowser/iGopherBrowserApp.swift | 14 ++ iGopherBrowserUITests.xctestplan | 24 +++ iGopherBrowserUITests/iGopherBrowserUITests.swift | 162 +++++++++++++++++++++ .../iGopherBrowserUITestsLaunchTests.swift | 32 ++++ 13 files changed, 792 insertions(+), 40 deletions(-) create mode 100644 iGopherBrowser.xcodeproj/xcshareddata/xcschemes/iGopherBrowser.xcscheme create mode 100644 iGopherBrowser.xcodeproj/xcshareddata/xcschemes/iGopherBrowserUITests.xcscheme create mode 100644 iGopherBrowser/SettingsView.swift create mode 100644 iGopherBrowserUITests.xctestplan create mode 100644 iGopherBrowserUITests/iGopherBrowserUITests.swift create mode 100644 iGopherBrowserUITests/iGopherBrowserUITestsLaunchTests.swift diff --git a/iGopherBrowser.xcodeproj/project.pbxproj b/iGopherBrowser.xcodeproj/project.pbxproj index c75763c..e200c0c 100644 --- a/iGopherBrowser.xcodeproj/project.pbxproj +++ b/iGopherBrowser.xcodeproj/project.pbxproj @@ -12,13 +12,27 @@ 3E1BCC5C2B297E9C00A4CB69 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 3E1BCC5B2B297E9C00A4CB69 /* Assets.xcassets */; }; 3E1BCC602B297E9C00A4CB69 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 3E1BCC5F2B297E9C00A4CB69 /* Preview Assets.xcassets */; }; 3E1BCC862B299E9F00A4CB69 /* SidebarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E1BCC852B299E9F00A4CB69 /* SidebarView.swift */; }; + 3E52F6422B3697B000F0921C /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E52F6412B3697B000F0921C /* SettingsView.swift */; }; + 3E76CF862B36AC2900979E1A /* iGopherBrowserUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E76CF852B36AC2900979E1A /* iGopherBrowserUITests.swift */; }; + 3E76CF882B36AC2900979E1A /* iGopherBrowserUITestsLaunchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E76CF872B36AC2900979E1A /* iGopherBrowserUITestsLaunchTests.swift */; }; 3EC1DF8D2B323A1900EDD707 /* SwiftGopherClient in Frameworks */ = {isa = PBXBuildFile; productRef = 3EC1DF8C2B323A1900EDD707 /* SwiftGopherClient */; }; + 3ECFE7432B4493F300AEBAE0 /* TelemetryClient in Frameworks */ = {isa = PBXBuildFile; productRef = 3ECFE7422B4493F300AEBAE0 /* TelemetryClient */; }; 3EFB9C0D2B2E4F06005EAD7C /* SearchInputView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EFB9C0C2B2E4F06005EAD7C /* SearchInputView.swift */; }; 3EFB9C0F2B2E6325005EAD7C /* FileView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EFB9C0E2B2E6325005EAD7C /* FileView.swift */; }; 3EFB9C112B2E869C005EAD7C /* BrowserView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EFB9C102B2E869C005EAD7C /* BrowserView.swift */; }; 3EFB9C132B2E872A005EAD7C /* Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EFB9C122B2E872A005EAD7C /* Helpers.swift */; }; /* End PBXBuildFile section */ +/* Begin PBXContainerItemProxy section */ + 3E76CF892B36AC2900979E1A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 3E1BCC4A2B297E9B00A4CB69 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 3E1BCC512B297E9B00A4CB69; + remoteInfo = iGopherBrowser; + }; +/* End PBXContainerItemProxy section */ + /* Begin PBXFileReference section */ 3E1BCC522B297E9B00A4CB69 /* iGopherBrowser.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = iGopherBrowser.app; sourceTree = BUILT_PRODUCTS_DIR; }; 3E1BCC552B297E9B00A4CB69 /* iGopherBrowserApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = iGopherBrowserApp.swift; sourceTree = ""; }; @@ -28,6 +42,11 @@ 3E1BCC5F2B297E9C00A4CB69 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; 3E1BCC612B297E9C00A4CB69 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 3E1BCC852B299E9F00A4CB69 /* SidebarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SidebarView.swift; sourceTree = ""; }; + 3E52F6412B3697B000F0921C /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = ""; }; + 3E76CF832B36AC2900979E1A /* iGopherBrowserUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = iGopherBrowserUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 3E76CF852B36AC2900979E1A /* iGopherBrowserUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = iGopherBrowserUITests.swift; sourceTree = ""; }; + 3E76CF872B36AC2900979E1A /* iGopherBrowserUITestsLaunchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = iGopherBrowserUITestsLaunchTests.swift; sourceTree = ""; }; + 3EA9102E2B399F150078150C /* iGopherBrowserUITests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = iGopherBrowserUITests.xctestplan; sourceTree = ""; }; 3EFB9C0C2B2E4F06005EAD7C /* SearchInputView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchInputView.swift; sourceTree = ""; }; 3EFB9C0E2B2E6325005EAD7C /* FileView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileView.swift; sourceTree = ""; }; 3EFB9C102B2E869C005EAD7C /* BrowserView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrowserView.swift; sourceTree = ""; }; @@ -40,6 +59,14 @@ buildActionMask = 2147483647; files = ( 3EC1DF8D2B323A1900EDD707 /* SwiftGopherClient in Frameworks */, + 3ECFE7432B4493F300AEBAE0 /* TelemetryClient in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 3E76CF802B36AC2900979E1A /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( ); runOnlyForDeploymentPostprocessing = 0; }; @@ -49,7 +76,9 @@ 3E1BCC492B297E9B00A4CB69 = { isa = PBXGroup; children = ( + 3EA9102E2B399F150078150C /* iGopherBrowserUITests.xctestplan */, 3E1BCC542B297E9B00A4CB69 /* iGopherBrowser */, + 3E76CF842B36AC2900979E1A /* iGopherBrowserUITests */, 3E1BCC532B297E9B00A4CB69 /* Products */, 3E1BCC7A2B29885900A4CB69 /* Frameworks */, ); @@ -59,6 +88,7 @@ isa = PBXGroup; children = ( 3E1BCC522B297E9B00A4CB69 /* iGopherBrowser.app */, + 3E76CF832B36AC2900979E1A /* iGopherBrowserUITests.xctest */, ); name = Products; sourceTree = ""; @@ -77,6 +107,7 @@ 3EFB9C0E2B2E6325005EAD7C /* FileView.swift */, 3EFB9C102B2E869C005EAD7C /* BrowserView.swift */, 3EFB9C122B2E872A005EAD7C /* Helpers.swift */, + 3E52F6412B3697B000F0921C /* SettingsView.swift */, ); path = iGopherBrowser; sourceTree = ""; @@ -96,6 +127,15 @@ name = Frameworks; sourceTree = ""; }; + 3E76CF842B36AC2900979E1A /* iGopherBrowserUITests */ = { + isa = PBXGroup; + children = ( + 3E76CF852B36AC2900979E1A /* iGopherBrowserUITests.swift */, + 3E76CF872B36AC2900979E1A /* iGopherBrowserUITestsLaunchTests.swift */, + ); + path = iGopherBrowserUITests; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -114,11 +154,30 @@ name = iGopherBrowser; packageProductDependencies = ( 3EC1DF8C2B323A1900EDD707 /* SwiftGopherClient */, + 3ECFE7422B4493F300AEBAE0 /* TelemetryClient */, ); productName = iGopherBrowser; productReference = 3E1BCC522B297E9B00A4CB69 /* iGopherBrowser.app */; productType = "com.apple.product-type.application"; }; + 3E76CF822B36AC2900979E1A /* iGopherBrowserUITests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 3E76CF8B2B36AC2900979E1A /* Build configuration list for PBXNativeTarget "iGopherBrowserUITests" */; + buildPhases = ( + 3E76CF7F2B36AC2900979E1A /* Sources */, + 3E76CF802B36AC2900979E1A /* Frameworks */, + 3E76CF812B36AC2900979E1A /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 3E76CF8A2B36AC2900979E1A /* PBXTargetDependency */, + ); + name = iGopherBrowserUITests; + productName = iGopherBrowserUITests; + productReference = 3E76CF832B36AC2900979E1A /* iGopherBrowserUITests.xctest */; + productType = "com.apple.product-type.bundle.ui-testing"; + }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ @@ -132,6 +191,10 @@ 3E1BCC512B297E9B00A4CB69 = { CreatedOnToolsVersion = 15.0; }; + 3E76CF822B36AC2900979E1A = { + CreatedOnToolsVersion = 15.0; + TestTargetID = 3E1BCC512B297E9B00A4CB69; + }; }; }; buildConfigurationList = 3E1BCC4D2B297E9B00A4CB69 /* Build configuration list for PBXProject "iGopherBrowser" */; @@ -145,12 +208,14 @@ mainGroup = 3E1BCC492B297E9B00A4CB69; packageReferences = ( 3EC1DF8B2B323A0600EDD707 /* XCRemoteSwiftPackageReference "swift-gopher" */, + 3ECFE7412B4493F300AEBAE0 /* XCRemoteSwiftPackageReference "SwiftClient" */, ); productRefGroup = 3E1BCC532B297E9B00A4CB69 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 3E1BCC512B297E9B00A4CB69 /* iGopherBrowser */, + 3E76CF822B36AC2900979E1A /* iGopherBrowserUITests */, ); }; /* End PBXProject section */ @@ -165,6 +230,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 3E76CF812B36AC2900979E1A /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -173,6 +245,7 @@ buildActionMask = 2147483647; files = ( 3EFB9C0F2B2E6325005EAD7C /* FileView.swift in Sources */, + 3E52F6422B3697B000F0921C /* SettingsView.swift in Sources */, 3E1BCC582B297E9B00A4CB69 /* ContentView.swift in Sources */, 3EFB9C112B2E869C005EAD7C /* BrowserView.swift in Sources */, 3EFB9C132B2E872A005EAD7C /* Helpers.swift in Sources */, @@ -182,8 +255,25 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 3E76CF7F2B36AC2900979E1A /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 3E76CF882B36AC2900979E1A /* iGopherBrowserUITestsLaunchTests.swift in Sources */, + 3E76CF862B36AC2900979E1A /* iGopherBrowserUITests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXSourcesBuildPhase section */ +/* Begin PBXTargetDependency section */ + 3E76CF8A2B36AC2900979E1A /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 3E1BCC512B297E9B00A4CB69 /* iGopherBrowser */; + targetProxy = 3E76CF892B36AC2900979E1A /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + /* Begin XCBuildConfiguration section */ 3E1BCC622B297E9C00A4CB69 /* Debug */ = { isa = XCBuildConfiguration; @@ -307,7 +397,7 @@ CODE_SIGN_ENTITLEMENTS = iGopherBrowser/iGopherBrowser.entitlements; "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; + CURRENT_PROJECT_VERSION = 6; DEVELOPMENT_ASSET_PATHS = "\"iGopherBrowser/Preview Content\""; DEVELOPMENT_TEAM = 6BS49F3GLW; ENABLE_HARDENED_RUNTIME = YES; @@ -328,7 +418,7 @@ LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks"; "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 14.0; - MARKETING_VERSION = 1.0; + MARKETING_VERSION = 1.0.3; PRODUCT_BUNDLE_IDENTIFIER = com.navanchauhan.iGopherBrowser; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = auto; @@ -348,7 +438,7 @@ CODE_SIGN_ENTITLEMENTS = iGopherBrowser/iGopherBrowser.entitlements; "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; + CURRENT_PROJECT_VERSION = 6; DEVELOPMENT_ASSET_PATHS = "\"iGopherBrowser/Preview Content\""; DEVELOPMENT_TEAM = 6BS49F3GLW; ENABLE_HARDENED_RUNTIME = YES; @@ -369,7 +459,7 @@ LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks"; "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 14.0; - MARKETING_VERSION = 1.0; + MARKETING_VERSION = 1.0.3; PRODUCT_BUNDLE_IDENTIFIER = com.navanchauhan.iGopherBrowser; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = auto; @@ -381,6 +471,48 @@ }; name = Release; }; + 3E76CF8C2B36AC2900979E1A /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = 6BS49F3GLW; + GENERATE_INFOPLIST_FILE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 17.0; + MACOSX_DEPLOYMENT_TARGET = 14.0; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.navanchauhan.iGopherBrowserUITests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = auto; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_TARGET_NAME = iGopherBrowser; + }; + name = Debug; + }; + 3E76CF8D2B36AC2900979E1A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = 6BS49F3GLW; + GENERATE_INFOPLIST_FILE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 17.0; + MACOSX_DEPLOYMENT_TARGET = 14.0; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.navanchauhan.iGopherBrowserUITests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = auto; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_TARGET_NAME = iGopherBrowser; + }; + name = Release; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -402,6 +534,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + 3E76CF8B2B36AC2900979E1A /* Build configuration list for PBXNativeTarget "iGopherBrowserUITests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 3E76CF8C2B36AC2900979E1A /* Debug */, + 3E76CF8D2B36AC2900979E1A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; /* End XCConfigurationList section */ /* Begin XCRemoteSwiftPackageReference section */ @@ -413,6 +554,14 @@ kind = branch; }; }; + 3ECFE7412B4493F300AEBAE0 /* XCRemoteSwiftPackageReference "SwiftClient" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/TelemetryDeck/SwiftClient"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 1.5.0; + }; + }; /* End XCRemoteSwiftPackageReference section */ /* Begin XCSwiftPackageProductDependency section */ @@ -421,6 +570,11 @@ package = 3EC1DF8B2B323A0600EDD707 /* XCRemoteSwiftPackageReference "swift-gopher" */; productName = SwiftGopherClient; }; + 3ECFE7422B4493F300AEBAE0 /* TelemetryClient */ = { + isa = XCSwiftPackageProductDependency; + package = 3ECFE7412B4493F300AEBAE0 /* XCRemoteSwiftPackageReference "SwiftClient" */; + productName = TelemetryClient; + }; /* End XCSwiftPackageProductDependency section */ }; rootObject = 3E1BCC4A2B297E9B00A4CB69 /* Project object */; diff --git a/iGopherBrowser.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/iGopherBrowser.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 9cc4163..a52fef6 100644 --- a/iGopherBrowser.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/iGopherBrowser.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -44,6 +44,15 @@ "revision" : "ebf8b9c365a6ce043bf6e6326a04b15589bd285e", "version" : "1.20.0" } + }, + { + "identity" : "swiftclient", + "kind" : "remoteSourceControl", + "location" : "https://github.com/TelemetryDeck/SwiftClient", + "state" : { + "revision" : "98500be378267abaa072ed08c2caf7da6493489e", + "version" : "1.5.0" + } } ], "version" : 2 diff --git a/iGopherBrowser.xcodeproj/xcshareddata/xcschemes/iGopherBrowser.xcscheme b/iGopherBrowser.xcodeproj/xcshareddata/xcschemes/iGopherBrowser.xcscheme new file mode 100644 index 0000000..14a1259 --- /dev/null +++ b/iGopherBrowser.xcodeproj/xcshareddata/xcschemes/iGopherBrowser.xcscheme @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/iGopherBrowser.xcodeproj/xcshareddata/xcschemes/iGopherBrowserUITests.xcscheme b/iGopherBrowser.xcodeproj/xcshareddata/xcschemes/iGopherBrowserUITests.xcscheme new file mode 100644 index 0000000..37ba178 --- /dev/null +++ b/iGopherBrowser.xcodeproj/xcshareddata/xcschemes/iGopherBrowserUITests.xcscheme @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/iGopherBrowser.xcodeproj/xcuserdata/navanchauhan.xcuserdatad/xcschemes/xcschememanagement.plist b/iGopherBrowser.xcodeproj/xcuserdata/navanchauhan.xcuserdatad/xcschemes/xcschememanagement.plist index d87001e..b2389df 100644 --- a/iGopherBrowser.xcodeproj/xcuserdata/navanchauhan.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/iGopherBrowser.xcodeproj/xcuserdata/navanchauhan.xcuserdatad/xcschemes/xcschememanagement.plist @@ -9,6 +9,29 @@ orderHint 0 + iGopherBrowserUITests.xcscheme_^#shared#^_ + + orderHint + 1 + + + SuppressBuildableAutocreation + + 3E1BCC512B297E9B00A4CB69 + + primary + + + 3E52F6462B369DC200F0921C + + primary + + + 3E76CF822B36AC2900979E1A + + primary + + diff --git a/iGopherBrowser/BrowserView.swift b/iGopherBrowser/BrowserView.swift index 9aa45cc..2e158f6 100644 --- a/iGopherBrowser/BrowserView.swift +++ b/iGopherBrowser/BrowserView.swift @@ -7,9 +7,20 @@ import GopherHelpers import SwiftUI +import TelemetryClient import swiftGopherClient +func openURL(url: URL) { + #if os(OSX) + NSWorkspace.shared.open(url) + #else + UIApplication.shared.open(url) + #endif +} + struct BrowserView: View { + @AppStorage("homeURL") var homeURL: URL = URL(string: "gopher://gopher.navan.dev:70/")! + @State var homeURLString = "gopher://gopher.navan.dev:70/" @State var url: String = "" @State private var gopherItems: [gopherItem] = [] @@ -24,6 +35,8 @@ struct BrowserView: View { @State private var showSearchInput = false @State var selectedSearchItem: Int? + @State private var showPreferences = false + let client = GopherClient() var body: some View { @@ -36,25 +49,31 @@ struct BrowserView: View { Text(item.message) .font(.system(size: 12, design: .monospaced)) .frame(height: 20) - .listRowInsets(EdgeInsets()) .listRowSeparator(.hidden) + .padding(.vertical, -8) } else if item.parsedItemType == .directory { - HStack { - Text(Image(systemName: "folder")) - Text(item.message) - Spacer() - }.onTapGesture { + Button(action: { performGopherRequest(host: item.host, port: item.port, selector: item.selector) - } + }) { + HStack { + Text(Image(systemName: "folder")) + Text(item.message) + Spacer() + } + }.buttonStyle(PlainButtonStyle()) + } else if item.parsedItemType == .search { - HStack { - Text(Image(systemName: "magnifyingglass")) - Text(item.message) - Spacer() - }.onTapGesture { + Button(action: { self.selectedSearchItem = idx self.showSearchInput = true - } + }) { + HStack { + Text(Image(systemName: "magnifyingglass")) + Text(item.message) + Spacer() + } + }.buttonStyle(PlainButtonStyle()) + } else if item.parsedItemType == .text { NavigationLink(destination: FileView(item: item)) { HStack { @@ -63,6 +82,19 @@ struct BrowserView: View { Spacer() } } + } else if item.selector.hasPrefix("URL:") { + if let url = URL(string: item.selector.replacingOccurrences(of: "URL:", with: "")) { + //UIApplication.shared.canOpenURL(url) { + Button(action: { + openURL(url: url) + }) { + HStack { + Image(systemName: "link") + Text(item.message) + Spacer() + } + }.buttonStyle(PlainButtonStyle()) + } } else if [.doc, .image, .gif, .movie, .sound, .bitmap].contains(item.parsedItemType) { NavigationLink(destination: FileView(item: item)) { @@ -73,10 +105,18 @@ struct BrowserView: View { } } } else { - Text(item.message) - .onTapGesture { - performGopherRequest(host: item.host, port: item.port, selector: item.selector) + Button(action: { + TelemetryManager.send( + "applicationBrowsedUnknown", + with: ["gopherURL": "\(item.host):\(item.port)\(item.selector)"]) + performGopherRequest(host: item.host, port: item.port, selector: item.selector) + }) { + HStack { + Text(Image(systemName: "questionmark.app.dashed")) + Text(item.message) + Spacer() } + }.buttonStyle(PlainButtonStyle()) } } @@ -104,6 +144,9 @@ struct BrowserView: View { Text("Weird bug. Please Dismiss -> Press Go -> Try Again") Button("Dismiss") { self.showSearchInput = false + }.onAppear { + TelemetryManager.send( + "applicationSearchError", with: ["gopherURL": "\(self.url)"]) } } @@ -121,11 +164,11 @@ struct BrowserView: View { Spacer() TextField("Enter a URL", text: $url) - #if !os(OSX) - .keyboardType(.URL) - .autocapitalization(.none) - #endif + .keyboardType(.URL) + .autocapitalization(.none) .padding(10) + .background(Color.gray.opacity(0.2)) + .cornerRadius(10) Spacer() } //.background(Color.white) @@ -134,7 +177,9 @@ struct BrowserView: View { Button( "Go", action: { + TelemetryManager.send("applicationClickedGo", with: ["gopherURL": "\(self.url)"]) performGopherRequest(clearForward: false) + } ) .keyboardShortcut(.defaultAction) @@ -143,10 +188,16 @@ struct BrowserView: View { } Spacer() } + .padding(.bottom, 10) + .padding(.top, 5) HStack { Spacer() Button { - performGopherRequest(host: "gopher.navan.dev", port: 70, selector: "/") + print(homeURL, "home") + TelemetryManager.send("applicationClickedHome", with: ["gopherURL": "\(self.url)"]) + performGopherRequest( + host: homeURL.host ?? "gopher.navan.dev", port: homeURL.port ?? 70, + selector: homeURL.path) } label: { Label("Home", systemImage: "house") .labelStyle(.iconOnly) @@ -156,6 +207,9 @@ struct BrowserView: View { if let curNode = backwardStack.popLast() { forwardStack.append(curNode) if let prevNode = backwardStack.popLast() { + TelemetryManager.send( + "applicationClickedBack", + with: ["gopherURL": "\(prevNode.host):\(prevNode.port)\(prevNode.selector)"]) performGopherRequest( host: prevNode.host, port: prevNode.port, selector: prevNode.selector, clearForward: false) @@ -169,7 +223,9 @@ struct BrowserView: View { Spacer() Button { if let nextNode = forwardStack.popLast() { - //backwardStack.append(nextNode) + TelemetryManager.send( + "applicationClickedForward", + with: ["gopherURL": "\(nextNode.host):\(nextNode.port)\(nextNode.selector)"]) performGopherRequest( host: nextNode.host, port: nextNode.port, selector: nextNode.selector, clearForward: false) @@ -180,6 +236,13 @@ struct BrowserView: View { } .disabled(forwardStack.isEmpty) Spacer() + Button { + self.showPreferences = true + } label: { + Label("Settings", systemImage: "gear") + .labelStyle(.iconOnly) + } + Spacer() } } #else @@ -187,7 +250,10 @@ struct BrowserView: View { HStack { Spacer() Button { - performGopherRequest(host: "gopher.navan.dev", port: 70, selector: "/") + TelemetryManager.send("applicationClickedHome", with: ["gopherURL": "\(self.url)"]) + performGopherRequest( + host: homeURL.host ?? "gopher.navan.dev", port: homeURL.port ?? 70, + selector: homeURL.path) } label: { Label("Home", systemImage: "house") .labelStyle(.iconOnly) @@ -197,6 +263,9 @@ struct BrowserView: View { if let curNode = backwardStack.popLast() { forwardStack.append(curNode) if let prevNode = backwardStack.popLast() { + TelemetryManager.send( + "applicationClickedBack", + with: ["gopherURL": "\(prevNode.host):\(prevNode.port)\(prevNode.selector)"]) performGopherRequest( host: prevNode.host, port: prevNode.port, selector: prevNode.selector, clearForward: false) @@ -210,7 +279,9 @@ struct BrowserView: View { Button { if let nextNode = forwardStack.popLast() { - //backwardStack.append(nextNode) + TelemetryManager.send( + "applicationClickedForward", + with: ["gopherURL": "\(nextNode.host):\(nextNode.port)\(nextNode.selector)"]) performGopherRequest( host: nextNode.host, port: nextNode.port, selector: nextNode.selector, clearForward: false) @@ -235,6 +306,7 @@ struct BrowserView: View { Button( "Go", action: { + TelemetryManager.send("applicationClickedGo", with: ["gopherURL": "\(self.url)"]) performGopherRequest(clearForward: false) } ) @@ -252,6 +324,21 @@ struct BrowserView: View { performGopherRequest(host: node.host, port: node.port, selector: node.selector) } } + .sheet( + isPresented: $showPreferences, + onDismiss: { + print("badm", homeURL, homeURLString) + if let url = URL(string: homeURLString) { + self.homeURL = url + } + } + ) { + #if os(iOS) + SettingsView(homeURL: $homeURL, homeURLString: $homeURLString) + #else + SettingsView() + #endif + } } private func performGopherRequest( @@ -310,6 +397,8 @@ struct BrowserView: View { self.gopherItems = resp case .failure(let error): + TelemetryManager.send( + "applicationRequestError", with: ["gopherURL": "\(self.url)", "errorMessage": "\(error)"]) print("Error \(error)") var item = gopherItem(rawLine: "Error \(error)") item.message = "Error \(error)" diff --git a/iGopherBrowser/ContentView.swift b/iGopherBrowser/ContentView.swift index 31c9688..5de5d8c 100644 --- a/iGopherBrowser/ContentView.swift +++ b/iGopherBrowser/ContentView.swift @@ -53,7 +53,7 @@ struct ContentView: View { } -#Preview { - ContentView() - //.modelContainer(for: Item.self, inMemory: true) -} +//#Preview { +// ContentView() +// //.modelContainer(for: Item.self, inMemory: true) +//} diff --git a/iGopherBrowser/FileView.swift b/iGopherBrowser/FileView.swift index 32b7068..b0578d8 100644 --- a/iGopherBrowser/FileView.swift +++ b/iGopherBrowser/FileView.swift @@ -8,6 +8,7 @@ import Foundation import GopherHelpers import QuickLook import SwiftUI +import TelemetryClient import swiftGopherClient func determineFileType(data: Data) -> String? { @@ -45,23 +46,21 @@ struct FileView: View { @State private var fileURL: URL? @State private var QLURL: URL? - let fileSignatures: [String: [UInt8]] = [ - "jpg": [0xFF, 0xD8, 0xFF], - "png": [0x89, 0x50, 0x4E, 0x47], - "gif": [0x47, 0x49, 0x46], - "pdf": [0x25, 0x50, 0x44, 0x46], - ] - var body: some View { if item.parsedItemType == .text { GeometryReader { geometry in ScrollView { VStack { Text(fileContent) + .padding() + .multilineTextAlignment(.leading) + .lineLimit(nil) + .frame(maxWidth: .infinity) + .fixedSize(horizontal: false, vertical: true) .onAppear { readFile(item) } - .frame(width: geometry.size.width, height: geometry.size.height) + // .frame(width: geometry.size.width, height: geometry.size.height) Spacer() } } @@ -108,6 +107,13 @@ struct FileView: View { let fileURL = tempDirURL.appendingPathComponent( UUID().uuidString + ".\(determineFileType(data: fileData) ?? "unkown")") print(fileURL) + + if determineFileType(data: fileData) == nil { + TelemetryManager.send( + "applicationUnableToDetectFiletype", + with: ["gopherURL": "\(item.host):\(item.port)\(item.selector)"]) + } + try fileData.write(to: fileURL) self.fileURL = fileURL } catch { diff --git a/iGopherBrowser/SettingsView.swift b/iGopherBrowser/SettingsView.swift new file mode 100644 index 0000000..0dda622 --- /dev/null +++ b/iGopherBrowser/SettingsView.swift @@ -0,0 +1,80 @@ +// +// SettingsView.swift +// iGopherBrowser +// +// Created by Navan Chauhan on 12/22/23. +// + +import SwiftUI + +struct SettingsView: View { + #if os(iOS) + @Binding var homeURL: URL + @Binding var homeURLString: String + #endif + #if os(macOS) + @AppStorage("homeURL") var homeURL: URL = URL(string: "gopher://gopher.navan.dev:70/")! + @State var homeURLString: String = "" + #endif + @State private var showAlert = false + @State private var alertMessage: String = "" + + @Environment(\.dismiss) var dismiss + + var body: some View { + Form { + Section(header: Text("Preferences")) { + VStack { + TextField("Home URL", text: $homeURLString) + .textFieldStyle(RoundedBorderTextFieldStyle()) + .disableAutocorrection(true) + // .onAppear { + // // Convert URL to String when the view appears + // self.homeURLString = homeURL.absoluteString + // } + .onSubmit { + // Convert String back to URL when the user submits the text + if let url = URL(string: homeURLString) { + self.homeURL = url + } + } + HStack { + Button( + "Save", + action: { + if let url = URL(string: homeURLString) { + homeURL = url + print("Saved \(self.homeURL)") + #if os(iOS) + dismiss() + #endif + } else { + self.alertMessage = "Unable to convert \(homeURLString) to a URL" + self.showAlert = true + } + }) + Button( + "Reset Preferences", + action: { + self.homeURL = URL(string: "gopher://gopher.navan.dev:70/")! + #if os(iOS) + dismiss() + #endif + }) + } + } + } + } + #if os(OSX) + .padding(20) + .frame(width: 350, height: 100) + #endif + .alert(isPresented: $showAlert) { + Alert( + title: Text("Error Saving"), + message: Text(alertMessage), + dismissButton: .default(Text("Got it!")) + ) + } + } +} diff --git a/iGopherBrowser/iGopherBrowserApp.swift b/iGopherBrowser/iGopherBrowserApp.swift index 93c3b8a..e18d6f5 100644 --- a/iGopherBrowser/iGopherBrowserApp.swift +++ b/iGopherBrowser/iGopherBrowserApp.swift @@ -6,6 +6,7 @@ // import SwiftUI +import TelemetryClient @main struct iGopherBrowserApp: App { @@ -18,5 +19,18 @@ struct iGopherBrowserApp: App { SidebarCommands() #endif } + #if os(macOS) + Settings { + SettingsView() + } + #endif + } + + init() { + let configuration = TelemetryManagerConfiguration( + appID: "400187ED-ADA9-4AB4-91F8-8825AD8FC67C") + TelemetryManager.initialize(with: configuration) + + TelemetryManager.send("applicationDidFinishLaunching") } } diff --git a/iGopherBrowserUITests.xctestplan b/iGopherBrowserUITests.xctestplan new file mode 100644 index 0000000..09f3723 --- /dev/null +++ b/iGopherBrowserUITests.xctestplan @@ -0,0 +1,24 @@ +{ + "configurations" : [ + { + "id" : "C47F42D6-0DC7-4807-9A28-832707F0E1A0", + "name" : "Test Scheme Action", + "options" : { + + } + } + ], + "defaultOptions" : { + + }, + "testTargets" : [ + { + "target" : { + "containerPath" : "container:iGopherBrowser.xcodeproj", + "identifier" : "3E76CF822B36AC2900979E1A", + "name" : "iGopherBrowserUITests" + } + } + ], + "version" : 1 +} diff --git a/iGopherBrowserUITests/iGopherBrowserUITests.swift b/iGopherBrowserUITests/iGopherBrowserUITests.swift new file mode 100644 index 0000000..8f98729 --- /dev/null +++ b/iGopherBrowserUITests/iGopherBrowserUITests.swift @@ -0,0 +1,162 @@ +// +// iGopherBrowserUITests.swift +// iGopherBrowserUITests +// +// Created by Navan Chauhan on 12/22/23. +// + +import XCTest + +final class iGopherBrowserUITests: XCTestCase { + + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + + // In UI tests it is usually best to stop immediately when a failure occurs. + continueAfterFailure = false + + // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. + } + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + func testExample() throws { + + let app = XCUIApplication() + app.launch() + + let screenshot = app.windows.firstMatch.screenshot() + let attachment = XCTAttachment(screenshot: screenshot) + attachment.lifetime = .keepAlways + attachment.name = "Home Screen" + add(attachment) + + let settingsButton = app.buttons["Settings"] + settingsButton.tap() + + let collectionViewsQuery = app.collectionViews + + collectionViewsQuery.buttons["Reset Preferences"].tap() + + app.buttons["Home"].tap() + + while !(collectionViewsQuery /*@START_MENU_TOKEN@*/.staticTexts[ + "About Swift-Gopher" + ] /*[[".cells",".buttons[\", About Swift-Gopher\"].staticTexts[\"About Swift-Gopher\"]",".staticTexts[\"About Swift-Gopher\"]"],[[[-1,2],[-1,1],[-1,0,1]],[[-1,2],[-1,1]]],[0]]@END_MENU_TOKEN@*/ + .exists) + { + app.swipeUp() + } + + let screenshot1 = app.windows.firstMatch.screenshot() + let attachment1 = XCTAttachment(screenshot: screenshot1) + attachment1.lifetime = .keepAlways + attachment1.name = "Default Gopher Server" + add(attachment1) + + //let app = XCUIApplication() + let homeButton = app.buttons["Home"] + homeButton.tap() + + while !(collectionViewsQuery.staticTexts["About Swift-Gopher"].exists) { + app.swipeUp() + } + + collectionViewsQuery /*@START_MENU_TOKEN@*/.staticTexts[ + "About Swift-Gopher" + ] /*[[".cells",".buttons[\", About Swift-Gopher\"].staticTexts[\"About Swift-Gopher\"]",".staticTexts[\"About Swift-Gopher\"]"],[[[-1,2],[-1,1],[-1,0,1]],[[-1,2],[-1,1]]],[0]]@END_MENU_TOKEN@*/ + .tap() + app.buttons["Back"].tap() + collectionViewsQuery /*@START_MENU_TOKEN@*/.staticTexts[ + "All the gopher servers in the world (via Floodgap)" + ] /*[[".cells",".buttons[\", All the gopher servers in the world (via Floodgap)\"].staticTexts[\"All the gopher servers in the world (via Floodgap)\"]",".staticTexts[\"All the gopher servers in the world (via Floodgap)\"]"],[[[-1,2],[-1,1],[-1,0,1]],[[-1,2],[-1,1]]],[0]]@END_MENU_TOKEN@*/ + .tap() + collectionViewsQuery /*@START_MENU_TOKEN@*/.staticTexts[ + "Search Gopherspace with Veronica-2" + ] /*[[".cells",".buttons[\", Search Gopherspace with Veronica-2\"].staticTexts[\"Search Gopherspace with Veronica-2\"]",".staticTexts[\"Search Gopherspace with Veronica-2\"]"],[[[-1,2],[-1,1],[-1,0,1]],[[-1,2],[-1,1]]],[0]]@END_MENU_TOKEN@*/ + .tap() + collectionViewsQuery /*@START_MENU_TOKEN@*/.staticTexts[ + "Search Veronica-2" + ] /*[[".cells",".buttons[\", Search Veronica-2\"].staticTexts[\"Search Veronica-2\"]",".staticTexts[\"Search Veronica-2\"]"],[[[-1,2],[-1,1],[-1,0,1]],[[-1,2],[-1,1]]],[0]]@END_MENU_TOKEN@*/ + .tap() + app.buttons["Dismiss"].tap() + app.buttons["Go"].tap() + collectionViewsQuery /*@START_MENU_TOKEN@*/.staticTexts[ + "Search Veronica-2" + ] /*[[".cells",".buttons[\", Search Veronica-2\"].staticTexts[\"Search Veronica-2\"]",".staticTexts[\"Search Veronica-2\"]"],[[[-1,2],[-1,1],[-1,0,1]],[[-1,2],[-1,1]]],[0]]@END_MENU_TOKEN@*/ + .tap() + + let screenshot3 = app.windows.firstMatch.screenshot() + let attachment3 = XCTAttachment(screenshot: screenshot3) + attachment3.lifetime = .keepAlways + attachment3.name = "Search Interface" + add(attachment3) + + let searchTextField = app.textFields["Search"] + searchTextField.tap() + searchTextField.typeText("Navan") + app.buttons["Search"].tap() + collectionViewsQuery /*@START_MENU_TOKEN@*/.staticTexts[ + "navan-smash.jpg" + ] /*[[".cells",".buttons[\", navan-smash.jpg\"].staticTexts[\"navan-smash.jpg\"]",".staticTexts[\"navan-smash.jpg\"]"],[[[-1,2],[-1,1],[-1,0,1]],[[-1,2],[-1,1]]],[0]]@END_MENU_TOKEN@*/ + .tap() + app.buttons["Preview Document"].tap() + app.buttons["QLOverlayDoneButtonAccessibilityIdentifier"].tap() + app.buttons["Back"].tap() + + settingsButton.tap() + + let homeUrlTextField = collectionViewsQuery /*@START_MENU_TOKEN@*/.textFields[ + "Home URL"] /*[[".cells.textFields[\"Home URL\"]",".textFields[\"Home URL\"]"],[[[-1,1],[-1,0]]],[0]]@END_MENU_TOKEN@*/ + homeUrlTextField.tap() + + homeUrlTextField.coordinate(withNormalizedOffset: CGVectorMake(0.9, 0.9)).tap() + + let deleteKey = app /*@START_MENU_TOKEN@*/.keys[ + "delete"] /*[[".keyboards.keys[\"delete\"]",".keys[\"delete\"]"],[[[-1,1],[-1,0]]],[0]]@END_MENU_TOKEN@*/ + for _ in 0...30 { + deleteKey.tap() + } + + homeUrlTextField.typeText("gopher://gopher.floodgap.com:70/") + + let saveButton = collectionViewsQuery /*@START_MENU_TOKEN@*/.buttons[ + "Save"] /*[[".cells.buttons[\"Save\"]",".buttons[\"Save\"]"],[[[-1,1],[-1,0]]],[0]]@END_MENU_TOKEN@*/ + saveButton.tap() + homeButton.tap() + + while !(collectionViewsQuery.staticTexts["Search Veronica-2"].exists) { + app.swipeUp() + } + + app.buttons["Back"].tap() + app.buttons["Forward"].tap() + + // let screenshot2 = app.windows.firstMatch.screenshot() + // let attachment2 = XCTAttachment(screenshot: screenshot2) + // attachment2.lifetime = .keepAlways + // add(attachment2) + + // let searchButton = collectionViewsQuery.buttons[", Search Veronica-2"] + // searchButton.tap() + + // app.buttons["Dismiss"].tap() + // + // let goButton = app.buttons["Go"] + // goButton.tap() + // + // searchButton.tap() + + } + + // func testLaunchPerformance() throws { + // if #available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 7.0, *) { + // // This measures how long it takes to launch your application. + // measure(metrics: [XCTApplicationLaunchMetric()]) { + // XCUIApplication().launch() + // } + // } + // } +} diff --git a/iGopherBrowserUITests/iGopherBrowserUITestsLaunchTests.swift b/iGopherBrowserUITests/iGopherBrowserUITestsLaunchTests.swift new file mode 100644 index 0000000..d095deb --- /dev/null +++ b/iGopherBrowserUITests/iGopherBrowserUITestsLaunchTests.swift @@ -0,0 +1,32 @@ +// +// iGopherBrowserUITestsLaunchTests.swift +// iGopherBrowserUITests +// +// Created by Navan Chauhan on 12/22/23. +// + +//import XCTest +// +//final class iGopherBrowserUITestsLaunchTests: XCTestCase { +// +// override class var runsForEachTargetApplicationUIConfiguration: Bool { +// true +// } +// +// override func setUpWithError() throws { +// continueAfterFailure = false +// } +// +//// func testLaunch() throws { +//// let app = XCUIApplication() +//// app.launch() +//// +//// // Insert steps here to perform after app launch but before taking a screenshot, +//// // such as logging into a test account or navigating somewhere in the app +//// +//// let attachment = XCTAttachment(screenshot: app.screenshot()) +//// attachment.name = "Launch Screen" +//// attachment.lifetime = .keepAlways +//// add(attachment) +//// } +//} -- cgit v1.2.3