diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..a0310eb --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,34 @@ +name: CI + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + workflow_dispatch: + +jobs: + build: + + runs-on: macos-14 + timeout-minutes: 10 + + steps: + - uses: maxim-lobanov/setup-xcode@v1 + with: + xcode-version: '15.4' + - uses: actions/checkout@v4 + - name: Build + run: xcodebuild -project Browsy.xcodeproj -scheme Browsy -sdk macosx CODE_SIGNING_ALLOWED=NO + # Temporarily disabled until we have a way to run tests and sign the app. + # - name: Test + # run: xcodebuild -project Browsy.xcodeproj -scheme Browsy -sdk macosx CODE_SIGNING_ALLOWED=NO test + # - name: Archive + # run: xcodebuild -project Browsy.xcodeproj -scheme Browsy -sdk macosx -archivePath Browsy CODE_SIGNING_ALLOWED=NO archive + # - name: Zip + # run: zip -r Browsy.xcarchive.zip Browsy.xcarchive + # - name: Upload + # uses: actions/upload-artifact@v4 + # with: + # name: Browsy.xcarchive.zip + # path: Browsy.xcarchive.zip diff --git a/.gitignore b/.gitignore index 2c22487..52fe2f7 100644 --- a/.gitignore +++ b/.gitignore @@ -2,27 +2,13 @@ # # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore -## Build generated -build/ -DerivedData/ - -## Various settings -*.pbxuser -!default.pbxuser -*.mode1v3 -!default.mode1v3 -*.mode2v3 -!default.mode2v3 -*.perspectivev3 -!default.perspectivev3 +## User settings xcuserdata/ -## Other -*.moved-aside -*.xcuserstate - ## Obj-C/Swift specific *.hmap + +## App packaging *.ipa *.dSYM.zip *.dSYM @@ -35,6 +21,14 @@ playground.xcworkspace # # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. # Packages/ +# Package.pins +# Package.resolved +# *.xcodeproj +# +# Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata +# hence it is not needed unless you have added a package configuration file to your project +# .swiftpm + .build/ # CocoaPods @@ -44,22 +38,25 @@ playground.xcworkspace # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control # # Pods/ +# +# Add this line if you want to avoid checking in source code from the Xcode workspace +# *.xcworkspace # Carthage # # Add this line if you want to avoid checking in source code from Carthage dependencies. # Carthage/Checkouts -Carthage/Build +Carthage/Build/ # fastlane # -# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the -# screenshots whenever they are needed. +# It is recommended to not store the screenshots in the git repo. +# Instead, use fastlane to re-generate the screenshots whenever they are needed. # For more information about the recommended setup visit: -# https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md +# https://docs.fastlane.tools/best-practices/source-control/#source-control fastlane/report.xml fastlane/Preview.html -fastlane/screenshots +fastlane/screenshots/**/*.png fastlane/test_output diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 89914b6..0000000 --- a/.travis.yml +++ /dev/null @@ -1,9 +0,0 @@ -os: osx -osx_image: xcode9.2 -language: swift -xcode_project: Browsy.xcodeproj # path to your xcodeproj folder -xcode_scheme: Browsy -script: - - xcodebuild -scheme Browsy -configuration Release build test -after_success: - - bash <(curl -s https://codecov.io/bash) diff --git a/Browsy.xcodeproj/project.pbxproj b/Browsy.xcodeproj/project.pbxproj index 2b7f771..96d2967 100644 --- a/Browsy.xcodeproj/project.pbxproj +++ b/Browsy.xcodeproj/project.pbxproj @@ -3,48 +3,87 @@ archiveVersion = 1; classes = { }; - objectVersion = 46; + objectVersion = 56; objects = { /* Begin PBXBuildFile section */ - 19BCEE671E8FC82500871C0A /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19BCEE661E8FC82500871C0A /* ViewController.swift */; }; - 19E1A0771FF7E1180072376A /* BrowsyTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19E1A0761FF7E1180072376A /* BrowsyTests.swift */; }; - 19E940C01E8EEACC003F354A /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19E940BF1E8EEACC003F354A /* AppDelegate.swift */; }; - 19E940C41E8EEACC003F354A /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 19E940C31E8EEACC003F354A /* Assets.xcassets */; }; - 19E940C71E8EEACC003F354A /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 19E940C51E8EEACC003F354A /* Main.storyboard */; }; + 1914FE292C1B782800F32B05 /* Sparkle in Frameworks */ = {isa = PBXBuildFile; productRef = 1914FE282C1B782800F32B05 /* Sparkle */; }; + 194634C92C0BB1AE002F8AFE /* MenuView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 194634C82C0BB1AE002F8AFE /* MenuView.swift */; }; + 19626BA12C0881C30034D54F /* BrowsyApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19626BA02C0881C30034D54F /* BrowsyApp.swift */; }; + 19626BA52C0881C40034D54F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 19626BA42C0881C40034D54F /* Assets.xcassets */; }; + 19626BA82C0881C40034D54F /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 19626BA72C0881C40034D54F /* Preview Assets.xcassets */; }; + 19626BB32C0881C50034D54F /* BrowsyTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19626BB22C0881C50034D54F /* BrowsyTests.swift */; }; + 19626BBD2C0881C50034D54F /* BrowsyUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19626BBC2C0881C50034D54F /* BrowsyUITests.swift */; }; + 19626BBF2C0881C50034D54F /* BrowsyUITestsLaunchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19626BBE2C0881C50034D54F /* BrowsyUITestsLaunchTests.swift */; }; + 197019582C08AA8800D63B8E /* ChooserScreenBindingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 197019572C08AA8800D63B8E /* ChooserScreenBindingView.swift */; }; + 1979A8C42C09B58000E3E062 /* ChooserScreenPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1979A8C32C09B58000E3E062 /* ChooserScreenPresenter.swift */; }; + 1979A8C62C09B6BA00E3E062 /* BrowserManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1979A8C52C09B6BA00E3E062 /* BrowserManager.swift */; }; + 1979A8C82C09BC2300E3E062 /* Dependencies.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1979A8C72C09BC2300E3E062 /* Dependencies.swift */; }; + 1979A8CA2C09CAD900E3E062 /* ChooserWindowManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1979A8C92C09CAD900E3E062 /* ChooserWindowManager.swift */; }; + 1979A8CC2C09D51000E3E062 /* BrowsyAppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1979A8CB2C09D51000E3E062 /* BrowsyAppDelegate.swift */; }; + 1981D6A72C0A662000D60F8B /* ChooserScreenPresenterTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1981D6A62C0A662000D60F8B /* ChooserScreenPresenterTest.swift */; }; + 1981D6AA2C0A735B00D60F8B /* ChooserScreenView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1981D6A92C0A735B00D60F8B /* ChooserScreenView.swift */; }; + 1981D6AD2C0A741900D60F8B /* Browser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1981D6AC2C0A741900D60F8B /* Browser.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ - 19E1A0791FF7E1180072376A /* PBXContainerItemProxy */ = { + 19626BAF2C0881C50034D54F /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 19E940B41E8EEACC003F354A /* Project object */; + containerPortal = 19626B952C0881C30034D54F /* Project object */; proxyType = 1; - remoteGlobalIDString = 19E940BB1E8EEACC003F354A; + remoteGlobalIDString = 19626B9C2C0881C30034D54F; + remoteInfo = Browsy; + }; + 19626BB92C0881C50034D54F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 19626B952C0881C30034D54F /* Project object */; + proxyType = 1; + remoteGlobalIDString = 19626B9C2C0881C30034D54F; remoteInfo = Browsy; }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ - 19BCEE661E8FC82500871C0A /* ViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; - 19E1A0741FF7E1180072376A /* BrowsyTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = BrowsyTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 19E1A0761FF7E1180072376A /* BrowsyTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrowsyTests.swift; sourceTree = ""; }; - 19E1A0781FF7E1180072376A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 19E940BC1E8EEACC003F354A /* Browsy.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Browsy.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 19E940BF1E8EEACC003F354A /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 19E940C31E8EEACC003F354A /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 19E940C61E8EEACC003F354A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 19E940C81E8EEACC003F354A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 194634C82C0BB1AE002F8AFE /* MenuView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuView.swift; sourceTree = ""; }; + 19626B9D2C0881C30034D54F /* Browsy.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Browsy.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 19626BA02C0881C30034D54F /* BrowsyApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrowsyApp.swift; sourceTree = ""; }; + 19626BA42C0881C40034D54F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 19626BA72C0881C40034D54F /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; + 19626BA92C0881C40034D54F /* Browsy.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Browsy.entitlements; sourceTree = ""; }; + 19626BAE2C0881C50034D54F /* BrowsyTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = BrowsyTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 19626BB22C0881C50034D54F /* BrowsyTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrowsyTests.swift; sourceTree = ""; }; + 19626BB82C0881C50034D54F /* BrowsyUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = BrowsyUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 19626BBC2C0881C50034D54F /* BrowsyUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrowsyUITests.swift; sourceTree = ""; }; + 19626BBE2C0881C50034D54F /* BrowsyUITestsLaunchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrowsyUITestsLaunchTests.swift; sourceTree = ""; }; + 197019572C08AA8800D63B8E /* ChooserScreenBindingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChooserScreenBindingView.swift; sourceTree = ""; }; + 1970195E2C08C28000D63B8E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; + 1979A8C32C09B58000E3E062 /* ChooserScreenPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChooserScreenPresenter.swift; sourceTree = ""; }; + 1979A8C52C09B6BA00E3E062 /* BrowserManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrowserManager.swift; sourceTree = ""; }; + 1979A8C72C09BC2300E3E062 /* Dependencies.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Dependencies.swift; sourceTree = ""; }; + 1979A8C92C09CAD900E3E062 /* ChooserWindowManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChooserWindowManager.swift; sourceTree = ""; }; + 1979A8CB2C09D51000E3E062 /* BrowsyAppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrowsyAppDelegate.swift; sourceTree = ""; }; + 1981D6A62C0A662000D60F8B /* ChooserScreenPresenterTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChooserScreenPresenterTest.swift; sourceTree = ""; }; + 1981D6A92C0A735B00D60F8B /* ChooserScreenView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChooserScreenView.swift; sourceTree = ""; }; + 1981D6AC2C0A741900D60F8B /* Browser.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Browser.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ - 19E1A0711FF7E1180072376A /* Frameworks */ = { + 19626B9A2C0881C30034D54F /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1914FE292C1B782800F32B05 /* Sparkle in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 19626BAB2C0881C50034D54F /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; - 19E940B91E8EEACC003F354A /* Frameworks */ = { + 19626BB52C0881C50034D54F /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( @@ -54,236 +93,296 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 19E1A0751FF7E1180072376A /* BrowsyTests */ = { + 19626B942C0881C30034D54F = { isa = PBXGroup; children = ( - 19E1A0761FF7E1180072376A /* BrowsyTests.swift */, - 19E1A0781FF7E1180072376A /* Info.plist */, + 19626B9F2C0881C30034D54F /* Browsy */, + 19626BB12C0881C50034D54F /* BrowsyTests */, + 19626BBB2C0881C50034D54F /* BrowsyUITests */, + 19626B9E2C0881C30034D54F /* Products */, + ); + sourceTree = ""; + }; + 19626B9E2C0881C30034D54F /* Products */ = { + isa = PBXGroup; + children = ( + 19626B9D2C0881C30034D54F /* Browsy.app */, + 19626BAE2C0881C50034D54F /* BrowsyTests.xctest */, + 19626BB82C0881C50034D54F /* BrowsyUITests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 19626B9F2C0881C30034D54F /* Browsy */ = { + isa = PBXGroup; + children = ( + 1981D6AB2C0A73E400D60F8B /* BrowserManager */, + 1981D6A52C0A63FD00D60F8B /* ChooserScreen */, + 1970195E2C08C28000D63B8E /* Info.plist */, + 19626BA02C0881C30034D54F /* BrowsyApp.swift */, + 19626BA42C0881C40034D54F /* Assets.xcassets */, + 19626BA92C0881C40034D54F /* Browsy.entitlements */, + 19626BA62C0881C40034D54F /* Preview Content */, + 1979A8C72C09BC2300E3E062 /* Dependencies.swift */, + 1979A8CB2C09D51000E3E062 /* BrowsyAppDelegate.swift */, + 194634C82C0BB1AE002F8AFE /* MenuView.swift */, + ); + path = Browsy; + sourceTree = ""; + }; + 19626BA62C0881C40034D54F /* Preview Content */ = { + isa = PBXGroup; + children = ( + 19626BA72C0881C40034D54F /* Preview Assets.xcassets */, + ); + path = "Preview Content"; + sourceTree = ""; + }; + 19626BB12C0881C50034D54F /* BrowsyTests */ = { + isa = PBXGroup; + children = ( + 1981D6A82C0A67C200D60F8B /* ChooserScreen */, + 19626BB22C0881C50034D54F /* BrowsyTests.swift */, ); path = BrowsyTests; sourceTree = ""; }; - 19E940B31E8EEACC003F354A = { + 19626BBB2C0881C50034D54F /* BrowsyUITests */ = { isa = PBXGroup; children = ( - 19E940BE1E8EEACC003F354A /* Browsy */, - 19E1A0751FF7E1180072376A /* BrowsyTests */, - 19E940BD1E8EEACC003F354A /* Products */, + 19626BBC2C0881C50034D54F /* BrowsyUITests.swift */, + 19626BBE2C0881C50034D54F /* BrowsyUITestsLaunchTests.swift */, ); + path = BrowsyUITests; sourceTree = ""; }; - 19E940BD1E8EEACC003F354A /* Products */ = { + 1981D6A52C0A63FD00D60F8B /* ChooserScreen */ = { isa = PBXGroup; children = ( - 19E940BC1E8EEACC003F354A /* Browsy.app */, - 19E1A0741FF7E1180072376A /* BrowsyTests.xctest */, + 1979A8C92C09CAD900E3E062 /* ChooserWindowManager.swift */, + 197019572C08AA8800D63B8E /* ChooserScreenBindingView.swift */, + 1979A8C32C09B58000E3E062 /* ChooserScreenPresenter.swift */, + 1981D6A92C0A735B00D60F8B /* ChooserScreenView.swift */, ); - name = Products; + path = ChooserScreen; sourceTree = ""; }; - 19E940BE1E8EEACC003F354A /* Browsy */ = { + 1981D6A82C0A67C200D60F8B /* ChooserScreen */ = { isa = PBXGroup; children = ( - 19BCEE661E8FC82500871C0A /* ViewController.swift */, - 19E940BF1E8EEACC003F354A /* AppDelegate.swift */, - 19E940C31E8EEACC003F354A /* Assets.xcassets */, - 19E940C51E8EEACC003F354A /* Main.storyboard */, - 19E940C81E8EEACC003F354A /* Info.plist */, + 1981D6A62C0A662000D60F8B /* ChooserScreenPresenterTest.swift */, ); - path = Browsy; + path = ChooserScreen; + sourceTree = ""; + }; + 1981D6AB2C0A73E400D60F8B /* BrowserManager */ = { + isa = PBXGroup; + children = ( + 1979A8C52C09B6BA00E3E062 /* BrowserManager.swift */, + 1981D6AC2C0A741900D60F8B /* Browser.swift */, + ); + path = BrowserManager; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ - 19E1A0731FF7E1180072376A /* BrowsyTests */ = { + 19626B9C2C0881C30034D54F /* Browsy */ = { isa = PBXNativeTarget; - buildConfigurationList = 19E1A07D1FF7E1180072376A /* Build configuration list for PBXNativeTarget "BrowsyTests" */; + buildConfigurationList = 19626BC22C0881C50034D54F /* Build configuration list for PBXNativeTarget "Browsy" */; buildPhases = ( - 19E1A0701FF7E1180072376A /* Sources */, - 19E1A0711FF7E1180072376A /* Frameworks */, - 19E1A0721FF7E1180072376A /* Resources */, + 19626B992C0881C30034D54F /* Sources */, + 19626B9A2C0881C30034D54F /* Frameworks */, + 19626B9B2C0881C30034D54F /* Resources */, ); buildRules = ( ); dependencies = ( - 19E1A07A1FF7E1180072376A /* PBXTargetDependency */, + ); + name = Browsy; + packageProductDependencies = ( + 1914FE282C1B782800F32B05 /* Sparkle */, + ); + productName = Browsy; + productReference = 19626B9D2C0881C30034D54F /* Browsy.app */; + productType = "com.apple.product-type.application"; + }; + 19626BAD2C0881C50034D54F /* BrowsyTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 19626BC52C0881C50034D54F /* Build configuration list for PBXNativeTarget "BrowsyTests" */; + buildPhases = ( + 19626BAA2C0881C50034D54F /* Sources */, + 19626BAB2C0881C50034D54F /* Frameworks */, + 19626BAC2C0881C50034D54F /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 19626BB02C0881C50034D54F /* PBXTargetDependency */, ); name = BrowsyTests; productName = BrowsyTests; - productReference = 19E1A0741FF7E1180072376A /* BrowsyTests.xctest */; + productReference = 19626BAE2C0881C50034D54F /* BrowsyTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; - 19E940BB1E8EEACC003F354A /* Browsy */ = { + 19626BB72C0881C50034D54F /* BrowsyUITests */ = { isa = PBXNativeTarget; - buildConfigurationList = 19E940CB1E8EEACC003F354A /* Build configuration list for PBXNativeTarget "Browsy" */; + buildConfigurationList = 19626BC82C0881C50034D54F /* Build configuration list for PBXNativeTarget "BrowsyUITests" */; buildPhases = ( - 19E940B81E8EEACC003F354A /* Sources */, - 19E940B91E8EEACC003F354A /* Frameworks */, - 19E940BA1E8EEACC003F354A /* Resources */, + 19626BB42C0881C50034D54F /* Sources */, + 19626BB52C0881C50034D54F /* Frameworks */, + 19626BB62C0881C50034D54F /* Resources */, ); buildRules = ( ); dependencies = ( + 19626BBA2C0881C50034D54F /* PBXTargetDependency */, ); - name = Browsy; - productName = Browsy; - productReference = 19E940BC1E8EEACC003F354A /* Browsy.app */; - productType = "com.apple.product-type.application"; + name = BrowsyUITests; + productName = BrowsyUITests; + productReference = 19626BB82C0881C50034D54F /* BrowsyUITests.xctest */; + productType = "com.apple.product-type.bundle.ui-testing"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ - 19E940B41E8EEACC003F354A /* Project object */ = { + 19626B952C0881C30034D54F /* Project object */ = { isa = PBXProject; attributes = { - LastSwiftUpdateCheck = 0920; - LastUpgradeCheck = 0920; - ORGANIZATIONNAME = kJulio; + BuildIndependentTargetsInParallel = 1; + LastSwiftUpdateCheck = 1540; + LastUpgradeCheck = 1540; TargetAttributes = { - 19E1A0731FF7E1180072376A = { - CreatedOnToolsVersion = 9.2; - ProvisioningStyle = Automatic; - TestTargetID = 19E940BB1E8EEACC003F354A; + 19626B9C2C0881C30034D54F = { + CreatedOnToolsVersion = 15.4; }; - 19E940BB1E8EEACC003F354A = { - CreatedOnToolsVersion = 8.3; - DevelopmentTeam = C4T5VAUNJX; - LastSwiftMigration = 0910; - ProvisioningStyle = Automatic; + 19626BAD2C0881C50034D54F = { + CreatedOnToolsVersion = 15.4; + TestTargetID = 19626B9C2C0881C30034D54F; + }; + 19626BB72C0881C50034D54F = { + CreatedOnToolsVersion = 15.4; + TestTargetID = 19626B9C2C0881C30034D54F; }; }; }; - buildConfigurationList = 19E940B71E8EEACC003F354A /* Build configuration list for PBXProject "Browsy" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; + buildConfigurationList = 19626B982C0881C30034D54F /* Build configuration list for PBXProject "Browsy" */; + compatibilityVersion = "Xcode 14.0"; + developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); - mainGroup = 19E940B31E8EEACC003F354A; - productRefGroup = 19E940BD1E8EEACC003F354A /* Products */; + mainGroup = 19626B942C0881C30034D54F; + packageReferences = ( + 1914FE272C1B782800F32B05 /* XCRemoteSwiftPackageReference "Sparkle" */, + ); + productRefGroup = 19626B9E2C0881C30034D54F /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( - 19E940BB1E8EEACC003F354A /* Browsy */, - 19E1A0731FF7E1180072376A /* BrowsyTests */, + 19626B9C2C0881C30034D54F /* Browsy */, + 19626BAD2C0881C50034D54F /* BrowsyTests */, + 19626BB72C0881C50034D54F /* BrowsyUITests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ - 19E1A0721FF7E1180072376A /* Resources */ = { + 19626B9B2C0881C30034D54F /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 19626BA82C0881C40034D54F /* Preview Assets.xcassets in Resources */, + 19626BA52C0881C40034D54F /* Assets.xcassets in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 19E940BA1E8EEACC003F354A /* Resources */ = { + 19626BAC2C0881C50034D54F /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 19626BB62C0881C50034D54F /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 19E940C41E8EEACC003F354A /* Assets.xcassets in Resources */, - 19E940C71E8EEACC003F354A /* Main.storyboard in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ - 19E1A0701FF7E1180072376A /* Sources */ = { + 19626B992C0881C30034D54F /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1979A8CC2C09D51000E3E062 /* BrowsyAppDelegate.swift in Sources */, + 194634C92C0BB1AE002F8AFE /* MenuView.swift in Sources */, + 1979A8C82C09BC2300E3E062 /* Dependencies.swift in Sources */, + 1981D6AA2C0A735B00D60F8B /* ChooserScreenView.swift in Sources */, + 1979A8CA2C09CAD900E3E062 /* ChooserWindowManager.swift in Sources */, + 197019582C08AA8800D63B8E /* ChooserScreenBindingView.swift in Sources */, + 1979A8C62C09B6BA00E3E062 /* BrowserManager.swift in Sources */, + 1981D6AD2C0A741900D60F8B /* Browser.swift in Sources */, + 1979A8C42C09B58000E3E062 /* ChooserScreenPresenter.swift in Sources */, + 19626BA12C0881C30034D54F /* BrowsyApp.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 19626BAA2C0881C50034D54F /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 19E1A0771FF7E1180072376A /* BrowsyTests.swift in Sources */, + 1981D6A72C0A662000D60F8B /* ChooserScreenPresenterTest.swift in Sources */, + 19626BB32C0881C50034D54F /* BrowsyTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 19E940B81E8EEACC003F354A /* Sources */ = { + 19626BB42C0881C50034D54F /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 19BCEE671E8FC82500871C0A /* ViewController.swift in Sources */, - 19E940C01E8EEACC003F354A /* AppDelegate.swift in Sources */, + 19626BBF2C0881C50034D54F /* BrowsyUITestsLaunchTests.swift in Sources */, + 19626BBD2C0881C50034D54F /* BrowsyUITests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ - 19E1A07A1FF7E1180072376A /* PBXTargetDependency */ = { + 19626BB02C0881C50034D54F /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 19E940BB1E8EEACC003F354A /* Browsy */; - targetProxy = 19E1A0791FF7E1180072376A /* PBXContainerItemProxy */; + target = 19626B9C2C0881C30034D54F /* Browsy */; + targetProxy = 19626BAF2C0881C50034D54F /* PBXContainerItemProxy */; }; -/* End PBXTargetDependency section */ - -/* Begin PBXVariantGroup section */ - 19E940C51E8EEACC003F354A /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 19E940C61E8EEACC003F354A /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; + 19626BBA2C0881C50034D54F /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 19626B9C2C0881C30034D54F /* Browsy */; + targetProxy = 19626BB92C0881C50034D54F /* PBXContainerItemProxy */; }; -/* End PBXVariantGroup section */ +/* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ - 19E1A07B1FF7E1180072376A /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CODE_SIGN_STYLE = Automatic; - COMBINE_HIDPI_IMAGES = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - INFOPLIST_FILE = BrowsyTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 10.13; - PRODUCT_BUNDLE_IDENTIFIER = net.kjulio.BrowsyTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 4.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Browsy.app/Contents/MacOS/Browsy"; - }; - name = Debug; - }; - 19E1A07C1FF7E1180072376A /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CODE_SIGN_STYLE = Automatic; - COMBINE_HIDPI_IMAGES = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - INFOPLIST_FILE = BrowsyTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 10.13; - PRODUCT_BUNDLE_IDENTIFIER = net.kjulio.BrowsyTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 4.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Browsy.app/Contents/MacOS/Browsy"; - }; - name = Release; - }; - 19E940C91E8EEACC003F354A /* Debug */ = { + 19626BC02C0881C50034D54F /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; @@ -291,19 +390,22 @@ CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; @@ -317,29 +419,33 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.12; - MTL_ENABLE_DEBUG_INFO = YES; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MACOSX_DEPLOYMENT_TARGET = 14.5; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; }; name = Debug; }; - 19E940CA1E8EEACC003F354A /* Release */ = { + 19626BC12C0881C50034D54F /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; @@ -347,19 +453,22 @@ CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; @@ -367,74 +476,208 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.12; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MACOSX_DEPLOYMENT_TARGET = 14.5; MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; SDKROOT = macosx; - SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_COMPILATION_MODE = wholemodule; }; name = Release; }; - 19E940CC1E8EEACC003F354A /* Debug */ = { + 19626BC32C0881C50034D54F /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_ENTITLEMENTS = Browsy/Browsy.entitlements; + CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = "\"Browsy/Preview Content\""; DEVELOPMENT_TEAM = C4T5VAUNJX; + ENABLE_HARDENED_RUNTIME = YES; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = Browsy/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = net.kjulio.Browsy; + INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities"; + INFOPLIST_KEY_LSUIElement = YES; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 13.0; + MARKETING_VERSION = 0.1; + PRODUCT_BUNDLE_IDENTIFIER = net.marcoromano.Browsy; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_SWIFT3_OBJC_INFERENCE = Default; - SWIFT_VERSION = 4.0; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; }; name = Debug; }; - 19E940CD1E8EEACC003F354A /* Release */ = { + 19626BC42C0881C50034D54F /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_ENTITLEMENTS = Browsy/Browsy.entitlements; + CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = "\"Browsy/Preview Content\""; DEVELOPMENT_TEAM = C4T5VAUNJX; + ENABLE_HARDENED_RUNTIME = YES; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = Browsy/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = net.kjulio.Browsy; + INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities"; + INFOPLIST_KEY_LSUIElement = YES; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 13.0; + MARKETING_VERSION = 0.1; + PRODUCT_BUNDLE_IDENTIFIER = net.marcoromano.Browsy; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; + 19626BC62C0881C50034D54F /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = C4T5VAUNJX; + GENERATE_INFOPLIST_FILE = YES; + MACOSX_DEPLOYMENT_TARGET = 14.5; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = net.marcoromano.BrowsyTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Browsy.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Browsy"; + }; + name = Debug; + }; + 19626BC72C0881C50034D54F /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = C4T5VAUNJX; + GENERATE_INFOPLIST_FILE = YES; + MACOSX_DEPLOYMENT_TARGET = 14.5; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = net.marcoromano.BrowsyTests; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_SWIFT3_OBJC_INFERENCE = Default; - SWIFT_VERSION = 4.0; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Browsy.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Browsy"; + }; + name = Release; + }; + 19626BC92C0881C50034D54F /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = C4T5VAUNJX; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = net.marcoromano.BrowsyUITests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TEST_TARGET_NAME = Browsy; + }; + name = Debug; + }; + 19626BCA2C0881C50034D54F /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = C4T5VAUNJX; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = net.marcoromano.BrowsyUITests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TEST_TARGET_NAME = Browsy; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 19E1A07D1FF7E1180072376A /* Build configuration list for PBXNativeTarget "BrowsyTests" */ = { + 19626B982C0881C30034D54F /* Build configuration list for PBXProject "Browsy" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 19626BC02C0881C50034D54F /* Debug */, + 19626BC12C0881C50034D54F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 19626BC22C0881C50034D54F /* Build configuration list for PBXNativeTarget "Browsy" */ = { isa = XCConfigurationList; buildConfigurations = ( - 19E1A07B1FF7E1180072376A /* Debug */, - 19E1A07C1FF7E1180072376A /* Release */, + 19626BC32C0881C50034D54F /* Debug */, + 19626BC42C0881C50034D54F /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 19E940B71E8EEACC003F354A /* Build configuration list for PBXProject "Browsy" */ = { + 19626BC52C0881C50034D54F /* Build configuration list for PBXNativeTarget "BrowsyTests" */ = { isa = XCConfigurationList; buildConfigurations = ( - 19E940C91E8EEACC003F354A /* Debug */, - 19E940CA1E8EEACC003F354A /* Release */, + 19626BC62C0881C50034D54F /* Debug */, + 19626BC72C0881C50034D54F /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 19E940CB1E8EEACC003F354A /* Build configuration list for PBXNativeTarget "Browsy" */ = { + 19626BC82C0881C50034D54F /* Build configuration list for PBXNativeTarget "BrowsyUITests" */ = { isa = XCConfigurationList; buildConfigurations = ( - 19E940CC1E8EEACC003F354A /* Debug */, - 19E940CD1E8EEACC003F354A /* Release */, + 19626BC92C0881C50034D54F /* Debug */, + 19626BCA2C0881C50034D54F /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ + +/* Begin XCRemoteSwiftPackageReference section */ + 1914FE272C1B782800F32B05 /* XCRemoteSwiftPackageReference "Sparkle" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/sparkle-project/Sparkle"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 2.6.3; + }; + }; +/* End XCRemoteSwiftPackageReference section */ + +/* Begin XCSwiftPackageProductDependency section */ + 1914FE282C1B782800F32B05 /* Sparkle */ = { + isa = XCSwiftPackageProductDependency; + package = 1914FE272C1B782800F32B05 /* XCRemoteSwiftPackageReference "Sparkle" */; + productName = Sparkle; + }; +/* End XCSwiftPackageProductDependency section */ }; - rootObject = 19E940B41E8EEACC003F354A /* Project object */; + rootObject = 19626B952C0881C30034D54F /* Project object */; } diff --git a/Browsy.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Browsy.xcodeproj/project.xcworkspace/contents.xcworkspacedata index 29790dc..919434a 100644 --- a/Browsy.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ b/Browsy.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -2,6 +2,6 @@ + location = "self:"> diff --git a/Browsy.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Browsy.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/Browsy.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Browsy.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Browsy.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved new file mode 100644 index 0000000..d380910 --- /dev/null +++ b/Browsy.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -0,0 +1,15 @@ +{ + "originHash" : "e721da7f9826abdffcb6185e886155efa2514bd6234475f1afa893e29eb258d6", + "pins" : [ + { + "identity" : "sparkle", + "kind" : "remoteSourceControl", + "location" : "https://github.com/sparkle-project/Sparkle", + "state" : { + "revision" : "b456fd404954a9e13f55aa0c88cd5a40b8399638", + "version" : "2.6.3" + } + } + ], + "version" : 3 +} diff --git a/Browsy.xcodeproj/xcuserdata/julionb.xcuserdatad/xcschemes/Browsy.xcscheme b/Browsy.xcodeproj/xcuserdata/julionb.xcuserdatad/xcschemes/Browsy.xcscheme deleted file mode 100644 index 2a1c96f..0000000 --- a/Browsy.xcodeproj/xcuserdata/julionb.xcuserdatad/xcschemes/Browsy.xcscheme +++ /dev/null @@ -1,103 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Browsy.xcodeproj/xcuserdata/julionb.xcuserdatad/xcschemes/xcschememanagement.plist b/Browsy.xcodeproj/xcuserdata/julionb.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index 6adc0a7..0000000 --- a/Browsy.xcodeproj/xcuserdata/julionb.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,22 +0,0 @@ - - - - - SchemeUserState - - Browsy.xcscheme - - orderHint - 0 - - - SuppressBuildableAutocreation - - 19E940BB1E8EEACC003F354A - - primary - - - - - diff --git a/Browsy/AppDelegate.swift b/Browsy/AppDelegate.swift deleted file mode 100644 index 79947fa..0000000 --- a/Browsy/AppDelegate.swift +++ /dev/null @@ -1,69 +0,0 @@ -// -// AppDelegate.swift -// Browsy -// -// Created by julionb on 31/03/2017. -// Copyright © 2017 kJulio. All rights reserved. -// - -import Cocoa - -@NSApplicationMain -class AppDelegate: NSObject, NSApplicationDelegate { - - var lastUrl: URL? { - didSet { - NotificationCenter.default.post( - name: NSNotification.Name(rawValue: "lastUrl"), - object: nil) - } - } - - func applicationDidFinishLaunching(_ aNotification: Notification) { - // Insert code here to initialize your application - } - - func applicationWillTerminate(_ aNotification: Notification) { - // Insert code here to tear down your application - } - - override func awakeFromNib() { - let eventManager = NSAppleEventManager.shared() - eventManager.setEventHandler( - self, - andSelector: #selector(self.handleGetURLEvent(replyEvent:)), - forEventClass: AEEventClass(kInternetEventClass), - andEventID: AEEventID(kAEGetURL) - ) - } - - @objc func handleGetURLEvent(replyEvent: NSAppleEventDescriptor?) { - if let aeEventDescriptor = replyEvent? - .paramDescriptor(forKeyword: AEKeyword(keyDirectObject)) { - let urlStr = aeEventDescriptor.stringValue - lastUrl = URL(string: urlStr!)! - } - - } - - /// appId: `nil` use the default HTTP client, or set what you want, - /// e.g. Safari `com.apple.Safari` - func openInSpecificBrowser(url: URL, appId: String? = nil) -> Bool { - return NSWorkspace.shared.open( - [url], - withAppBundleIdentifier: appId, - options: NSWorkspace.LaunchOptions.default, - additionalEventParamDescriptor: nil, - launchIdentifiers: nil - ) - } - - func openLastUrl(appId: String? = nil) -> Bool { - if (lastUrl != nil) { - return openInSpecificBrowser(url: lastUrl!, appId: appId) - } else { - return false - } - } - -} diff --git a/Browsy/Assets.xcassets/AccentColor.colorset/Contents.json b/Browsy/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 0000000..eb87897 --- /dev/null +++ b/Browsy/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Browsy/Assets.xcassets/AppIcon.appiconset/Contents.json b/Browsy/Assets.xcassets/AppIcon.appiconset/Contents.json index 388ddf3..6fa1116 100644 --- a/Browsy/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/Browsy/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,68 +1,68 @@ { "images" : [ { - "size" : "16x16", + "filename" : "browsy16.png", "idiom" : "mac", - "filename" : "dsadas-9.png", - "scale" : "1x" + "scale" : "1x", + "size" : "16x16" }, { - "size" : "16x16", + "filename" : "browsy32 1.png", "idiom" : "mac", - "filename" : "dsadas-8.png", - "scale" : "2x" + "scale" : "2x", + "size" : "16x16" }, { - "size" : "32x32", + "filename" : "browsy32.png", "idiom" : "mac", - "filename" : "dsadas-7.png", - "scale" : "1x" + "scale" : "1x", + "size" : "32x32" }, { - "size" : "32x32", + "filename" : "browsy64.png", "idiom" : "mac", - "filename" : "dsadas-6.png", - "scale" : "2x" + "scale" : "2x", + "size" : "32x32" }, { - "size" : "128x128", + "filename" : "browsy128.png", "idiom" : "mac", - "filename" : "dsadas-5.png", - "scale" : "1x" + "scale" : "1x", + "size" : "128x128" }, { - "size" : "128x128", + "filename" : "browsy256 1.png", "idiom" : "mac", - "filename" : "dsadas-4.png", - "scale" : "2x" + "scale" : "2x", + "size" : "128x128" }, { - "size" : "256x256", + "filename" : "browsy256.png", "idiom" : "mac", - "filename" : "dsadas-3.png", - "scale" : "1x" + "scale" : "1x", + "size" : "256x256" }, { - "size" : "256x256", + "filename" : "browsy512 1.png", "idiom" : "mac", - "filename" : "dsadas-2.png", - "scale" : "2x" + "scale" : "2x", + "size" : "256x256" }, { - "size" : "512x512", + "filename" : "browsy512.png", "idiom" : "mac", - "filename" : "dsadas-1.png", - "scale" : "1x" + "scale" : "1x", + "size" : "512x512" }, { - "size" : "512x512", + "filename" : "browsy1024.png", "idiom" : "mac", - "filename" : "dsadas.png", - "scale" : "2x" + "scale" : "2x", + "size" : "512x512" } ], "info" : { - "version" : 1, - "author" : "xcode" + "author" : "xcode", + "version" : 1 } -} \ No newline at end of file +} diff --git a/Browsy/Assets.xcassets/AppIcon.appiconset/browsy1024.png b/Browsy/Assets.xcassets/AppIcon.appiconset/browsy1024.png new file mode 100644 index 0000000..dc05e88 Binary files /dev/null and b/Browsy/Assets.xcassets/AppIcon.appiconset/browsy1024.png differ diff --git a/Browsy/Assets.xcassets/AppIcon.appiconset/browsy128.png b/Browsy/Assets.xcassets/AppIcon.appiconset/browsy128.png new file mode 100644 index 0000000..0264df8 Binary files /dev/null and b/Browsy/Assets.xcassets/AppIcon.appiconset/browsy128.png differ diff --git a/Browsy/Assets.xcassets/AppIcon.appiconset/browsy16.png b/Browsy/Assets.xcassets/AppIcon.appiconset/browsy16.png new file mode 100644 index 0000000..b3d7739 Binary files /dev/null and b/Browsy/Assets.xcassets/AppIcon.appiconset/browsy16.png differ diff --git a/Browsy/Assets.xcassets/AppIcon.appiconset/browsy256 1.png b/Browsy/Assets.xcassets/AppIcon.appiconset/browsy256 1.png new file mode 100644 index 0000000..4384c44 Binary files /dev/null and b/Browsy/Assets.xcassets/AppIcon.appiconset/browsy256 1.png differ diff --git a/Browsy/Assets.xcassets/AppIcon.appiconset/browsy256.png b/Browsy/Assets.xcassets/AppIcon.appiconset/browsy256.png new file mode 100644 index 0000000..4384c44 Binary files /dev/null and b/Browsy/Assets.xcassets/AppIcon.appiconset/browsy256.png differ diff --git a/Browsy/Assets.xcassets/AppIcon.appiconset/browsy32 1.png b/Browsy/Assets.xcassets/AppIcon.appiconset/browsy32 1.png new file mode 100644 index 0000000..3d291e2 Binary files /dev/null and b/Browsy/Assets.xcassets/AppIcon.appiconset/browsy32 1.png differ diff --git a/Browsy/Assets.xcassets/AppIcon.appiconset/browsy32.png b/Browsy/Assets.xcassets/AppIcon.appiconset/browsy32.png new file mode 100644 index 0000000..3d291e2 Binary files /dev/null and b/Browsy/Assets.xcassets/AppIcon.appiconset/browsy32.png differ diff --git a/Browsy/Assets.xcassets/AppIcon.appiconset/browsy512 1.png b/Browsy/Assets.xcassets/AppIcon.appiconset/browsy512 1.png new file mode 100644 index 0000000..62b222a Binary files /dev/null and b/Browsy/Assets.xcassets/AppIcon.appiconset/browsy512 1.png differ diff --git a/Browsy/Assets.xcassets/AppIcon.appiconset/browsy512.png b/Browsy/Assets.xcassets/AppIcon.appiconset/browsy512.png new file mode 100644 index 0000000..62b222a Binary files /dev/null and b/Browsy/Assets.xcassets/AppIcon.appiconset/browsy512.png differ diff --git a/Browsy/Assets.xcassets/AppIcon.appiconset/browsy64.png b/Browsy/Assets.xcassets/AppIcon.appiconset/browsy64.png new file mode 100644 index 0000000..fd24a3a Binary files /dev/null and b/Browsy/Assets.xcassets/AppIcon.appiconset/browsy64.png differ diff --git a/Browsy/Assets.xcassets/AppIcon.appiconset/dsadas-1.png b/Browsy/Assets.xcassets/AppIcon.appiconset/dsadas-1.png deleted file mode 100644 index 5b0bc5e..0000000 Binary files a/Browsy/Assets.xcassets/AppIcon.appiconset/dsadas-1.png and /dev/null differ diff --git a/Browsy/Assets.xcassets/AppIcon.appiconset/dsadas-2.png b/Browsy/Assets.xcassets/AppIcon.appiconset/dsadas-2.png deleted file mode 100644 index 5b0bc5e..0000000 Binary files a/Browsy/Assets.xcassets/AppIcon.appiconset/dsadas-2.png and /dev/null differ diff --git a/Browsy/Assets.xcassets/AppIcon.appiconset/dsadas-3.png b/Browsy/Assets.xcassets/AppIcon.appiconset/dsadas-3.png deleted file mode 100644 index 5b0bc5e..0000000 Binary files a/Browsy/Assets.xcassets/AppIcon.appiconset/dsadas-3.png and /dev/null differ diff --git a/Browsy/Assets.xcassets/AppIcon.appiconset/dsadas-4.png b/Browsy/Assets.xcassets/AppIcon.appiconset/dsadas-4.png deleted file mode 100644 index 5b0bc5e..0000000 Binary files a/Browsy/Assets.xcassets/AppIcon.appiconset/dsadas-4.png and /dev/null differ diff --git a/Browsy/Assets.xcassets/AppIcon.appiconset/dsadas-5.png b/Browsy/Assets.xcassets/AppIcon.appiconset/dsadas-5.png deleted file mode 100644 index 5b0bc5e..0000000 Binary files a/Browsy/Assets.xcassets/AppIcon.appiconset/dsadas-5.png and /dev/null differ diff --git a/Browsy/Assets.xcassets/AppIcon.appiconset/dsadas-6.png b/Browsy/Assets.xcassets/AppIcon.appiconset/dsadas-6.png deleted file mode 100644 index 5b0bc5e..0000000 Binary files a/Browsy/Assets.xcassets/AppIcon.appiconset/dsadas-6.png and /dev/null differ diff --git a/Browsy/Assets.xcassets/AppIcon.appiconset/dsadas-7.png b/Browsy/Assets.xcassets/AppIcon.appiconset/dsadas-7.png deleted file mode 100644 index 5b0bc5e..0000000 Binary files a/Browsy/Assets.xcassets/AppIcon.appiconset/dsadas-7.png and /dev/null differ diff --git a/Browsy/Assets.xcassets/AppIcon.appiconset/dsadas-8.png b/Browsy/Assets.xcassets/AppIcon.appiconset/dsadas-8.png deleted file mode 100644 index 5b0bc5e..0000000 Binary files a/Browsy/Assets.xcassets/AppIcon.appiconset/dsadas-8.png and /dev/null differ diff --git a/Browsy/Assets.xcassets/AppIcon.appiconset/dsadas-9.png b/Browsy/Assets.xcassets/AppIcon.appiconset/dsadas-9.png deleted file mode 100644 index 5b0bc5e..0000000 Binary files a/Browsy/Assets.xcassets/AppIcon.appiconset/dsadas-9.png and /dev/null differ diff --git a/Browsy/Assets.xcassets/AppIcon.appiconset/dsadas.png b/Browsy/Assets.xcassets/AppIcon.appiconset/dsadas.png deleted file mode 100644 index 5b0bc5e..0000000 Binary files a/Browsy/Assets.xcassets/AppIcon.appiconset/dsadas.png and /dev/null differ diff --git a/Browsy/Assets.xcassets/Background.colorset/Contents.json b/Browsy/Assets.xcassets/Background.colorset/Contents.json new file mode 100644 index 0000000..0425637 --- /dev/null +++ b/Browsy/Assets.xcassets/Background.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "1.000", + "green" : "1.000", + "red" : "1.000" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.000", + "green" : "0.000", + "red" : "0.000" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Browsy/Assets.xcassets/Contents.json b/Browsy/Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/Browsy/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Browsy/Assets.xcassets/MenuIcon.imageset/Contents.json b/Browsy/Assets.xcassets/MenuIcon.imageset/Contents.json new file mode 100644 index 0000000..6a12339 --- /dev/null +++ b/Browsy/Assets.xcassets/MenuIcon.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "browsymenu16.png", + "idiom" : "mac", + "scale" : "1x" + }, + { + "filename" : "browsymenu32.png", + "idiom" : "mac", + "scale" : "2x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "template" + } +} diff --git a/Browsy/Assets.xcassets/MenuIcon.imageset/browsymenu16.png b/Browsy/Assets.xcassets/MenuIcon.imageset/browsymenu16.png new file mode 100644 index 0000000..66e6369 Binary files /dev/null and b/Browsy/Assets.xcassets/MenuIcon.imageset/browsymenu16.png differ diff --git a/Browsy/Assets.xcassets/MenuIcon.imageset/browsymenu32.png b/Browsy/Assets.xcassets/MenuIcon.imageset/browsymenu32.png new file mode 100644 index 0000000..9994fa0 Binary files /dev/null and b/Browsy/Assets.xcassets/MenuIcon.imageset/browsymenu32.png differ diff --git a/Browsy/Base.lproj/Main.storyboard b/Browsy/Base.lproj/Main.storyboard deleted file mode 100644 index 6c40bd5..0000000 --- a/Browsy/Base.lproj/Main.storyboard +++ /dev/null @@ -1,801 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Default - - - - - - - Left to Right - - - - - - - Right to Left - - - - - - - - - - - Default - - - - - - - Left to Right - - - - - - - Right to Left - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Browsy/BrowserManager/Browser.swift b/Browsy/BrowserManager/Browser.swift new file mode 100644 index 0000000..66a2183 --- /dev/null +++ b/Browsy/BrowserManager/Browser.swift @@ -0,0 +1,19 @@ +// +// Browser.swift +// Browsy +// +// Created by julionb on 31/05/24. +// + +import Foundation +import AppKit + +struct Browser: Hashable { + let name: String + let icon: NSImage + let appUrl: URL +} + +func aBrowserList(number: Int = 3) -> [Browser] { + (1...number).map { i in Browser(name: "Browser \(i)", icon: NSImage(named: NSImage.actionTemplateName)!, appUrl: URL(string: "browser\(i).com")!) } +} diff --git a/Browsy/BrowserManager/BrowserManager.swift b/Browsy/BrowserManager/BrowserManager.swift new file mode 100644 index 0000000..6566a18 --- /dev/null +++ b/Browsy/BrowserManager/BrowserManager.swift @@ -0,0 +1,69 @@ +// +// BrowserManager.swift +// Browsy +// +// Created by julionb on 31/05/24. +// + +import AppKit + +protocol BrowserManager { + func getBrowserIdentifiers() -> [Browser] + func openURL(_ url: URL, in browserId: URL) + func setAsDefaultBrowser() +} + +class BrowserManagerImpl : BrowserManager { + + private let bundleMainUrl: URL + private let nsWorkspace: NSWorkspace + + init( + bundleMainUrl: URL, + nsWorkspace: NSWorkspace + ) { + self.bundleMainUrl = bundleMainUrl + self.nsWorkspace = nsWorkspace + } + + func getBrowserIdentifiers() -> [Browser] { + guard let schemeURL = URL(string: "https:") else { + return [] + } + let htmlHandlerAppsURLs: [URL] + let httpsHandlerAppsURLs: [URL] + htmlHandlerAppsURLs = nsWorkspace.urlsForApplications(toOpen: .html) + httpsHandlerAppsURLs = nsWorkspace.urlsForApplications(toOpen: schemeURL) + + return Set(htmlHandlerAppsURLs) + .intersection(httpsHandlerAppsURLs) + .filter { $0 != bundleMainUrl } + .compactMap { url in + guard let bundle = Bundle(url: url) else { + return nil + } + let icon = nsWorkspace.icon(forFile: url.path) + let name = bundle.object(forInfoDictionaryKey: "CFBundleName") as? String ?? "Unknown" + return Browser(name: name, icon: icon, appUrl: url) + } + } + + func openURL(_ url: URL, in browserId: URL) { + nsWorkspace.open( + [url], + withApplicationAt: browserId, + configuration: NSWorkspace.OpenConfiguration() + ) { (app, error) in + if let error = error { + print("Failed to open URL \(url) with application \(browserId): \(error)") + } + } + } + + func setAsDefaultBrowser() { + nsWorkspace.setDefaultApplication( + at: bundleMainUrl, + toOpenURLsWithScheme: "http" + ) + } +} diff --git a/Browsy/Browsy.entitlements b/Browsy/Browsy.entitlements new file mode 100644 index 0000000..625af03 --- /dev/null +++ b/Browsy/Browsy.entitlements @@ -0,0 +1,12 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.files.user-selected.read-only + + com.apple.security.network.client + + + diff --git a/Browsy/BrowsyApp.swift b/Browsy/BrowsyApp.swift new file mode 100644 index 0000000..ee13414 --- /dev/null +++ b/Browsy/BrowsyApp.swift @@ -0,0 +1,24 @@ +// +// BrowsyApp.swift +// Browsy +// +// Created by julionb on 30/05/24. +// + +import SwiftUI + +@main +struct BrowsyApp: App { + static let dependencies = Dependencies() + + @NSApplicationDelegateAdaptor(BrowsyAppDelegate.self) var appDelegate: BrowsyAppDelegate + + var body: some Scene { + MenuBarExtra("Browsy", image: "MenuIcon") { + MenuView( + quitAction: { NSApplication.shared.terminate(self) }, + checkForUpdates: { BrowsyApp.dependencies.spuStandardUpdaterController.updater.checkForUpdates() } + ) + } + } +} diff --git a/Browsy/BrowsyAppDelegate.swift b/Browsy/BrowsyAppDelegate.swift new file mode 100644 index 0000000..b7c53f5 --- /dev/null +++ b/Browsy/BrowsyAppDelegate.swift @@ -0,0 +1,38 @@ +// +// BrowsyAppDelegate.swift +// Browsy +// +// Created by julionb on 31/05/24. +// + +import AppKit + +class BrowsyAppDelegate: NSObject, NSApplicationDelegate { + + private let chooserWindowManager: ChooserWindowManager + private let browserManager: BrowserManager + + override init() { + chooserWindowManager = BrowsyApp.dependencies.chooserWindowManager + browserManager = BrowsyApp.dependencies.browserManager() + } + + func applicationDidFinishLaunching(_ notification: Notification) { + NSAppleEventManager.shared().setEventHandler( + self, + andSelector: #selector(handleGetURLEvent(event:replyEvent:)), + forEventClass: AEEventClass(kInternetEventClass), + andEventID: AEEventID(kAEGetURL) + ) + browserManager.setAsDefaultBrowser() + } + + @objc func handleGetURLEvent( + event: NSAppleEventDescriptor, + replyEvent: NSAppleEventDescriptor + ) { + if let urlString = event.paramDescriptor(forKeyword: keyDirectObject)?.stringValue, let url = URL(string: urlString) { + chooserWindowManager.showChooserWindow(url: url) + } + } +} diff --git a/Browsy/ChooserScreen/ChooserScreenBindingView.swift b/Browsy/ChooserScreen/ChooserScreenBindingView.swift new file mode 100644 index 0000000..2f8da04 --- /dev/null +++ b/Browsy/ChooserScreen/ChooserScreenBindingView.swift @@ -0,0 +1,19 @@ +// +// ChooserScreenBindingView.swift +// Browsy +// +// Created by julionb on 30/05/24. +// + +import SwiftUI + +struct ChooserScreenBindingView: View { + @ObservedObject var presenter: ChooserScreenPresenter + + var body: some View { + ChooserScreenView( + state: presenter.state, + onBrowserClicked: presenter.onBrowserClicked + ) + } +} diff --git a/Browsy/ChooserScreen/ChooserScreenPresenter.swift b/Browsy/ChooserScreen/ChooserScreenPresenter.swift new file mode 100644 index 0000000..3e405fb --- /dev/null +++ b/Browsy/ChooserScreen/ChooserScreenPresenter.swift @@ -0,0 +1,35 @@ +// +// ChooserScreenPresenter.swift +// Browsy +// +// Created by julionb on 31/05/24. +// + +import AppKit + +class ChooserScreenPresenter: ObservableObject { + + @Published private(set) var state: ChooserScreenState = ChooserScreenState(url: nil, browsers: []) + + private let browserManager: BrowserManager + private let url: URL + + init( + browserManager: BrowserManager, + url: URL + ) { + self.browserManager = browserManager + self.url = url + self.state = ChooserScreenState(url: url.host(), browsers: browserManager.getBrowserIdentifiers()) + } + + func onBrowserClicked(_ browser: URL) { + browserManager.openURL(url, in: browser) + NSApplication.shared.keyWindow?.close() + } +} + +struct ChooserScreenState { + let url: String? + let browsers: [Browser] +} diff --git a/Browsy/ChooserScreen/ChooserScreenView.swift b/Browsy/ChooserScreen/ChooserScreenView.swift new file mode 100644 index 0000000..b4e3b7b --- /dev/null +++ b/Browsy/ChooserScreen/ChooserScreenView.swift @@ -0,0 +1,50 @@ +// +// ChooserScreenView.swift +// Browsy +// +// Created by julionb on 31/05/24. +// + +import SwiftUI + +struct ChooserScreenView: View { + let state: ChooserScreenState + let onBrowserClicked: (URL) -> () + + var body: some View { + VStack(spacing: 0) { + Text(state.url ?? "") + List(state.browsers, id: \.self) { browser in + HStack { + Image(nsImage: browser.icon) + .resizable() + .scaledToFit() + .frame(width: 32, height: 32) + Text(browser.name) + .font(.headline) + Spacer() + } + .frame(maxWidth: .infinity, maxHeight: .infinity) + .onTapGesture { + onBrowserClicked(browser.appUrl) + } + .listRowBackground(Color(.background)) + } + }.listStyle(.plain) + .scrollContentBackground(.hidden) + .background(Color(.background)) + .cornerRadius(10) + .frame(minWidth:200, minHeight: 200) + .fixedSize() + } +} + +#Preview { + ChooserScreenView( + state: ChooserScreenState( + url: "www.apple.com", + browsers: aBrowserList(number: 6) + ), + onBrowserClicked: { _ in} + ) +} diff --git a/Browsy/ChooserScreen/ChooserWindowManager.swift b/Browsy/ChooserScreen/ChooserWindowManager.swift new file mode 100644 index 0000000..f5cad9a --- /dev/null +++ b/Browsy/ChooserScreen/ChooserWindowManager.swift @@ -0,0 +1,39 @@ +// +// ChooserWindowManager.swift +// Browsy +// +// Created by julionb on 31/05/24. +// + +import SwiftUI + +protocol ChooserWindowManager { + func showChooserWindow(url: URL) +} + +class ChooserWindowManagerImpl: ChooserWindowManager { + private let chooserScreenPresenterFactory: (URL) -> ChooserScreenPresenter + private let window: NSPanel + + init( + chooserScreenPresenterFactory: @escaping (URL) -> ChooserScreenPresenter + ) { + self.chooserScreenPresenterFactory = chooserScreenPresenterFactory + window = NSPanel( + contentRect: NSRect(x: 0, y: 0, width: 0, height: 0), + styleMask: [], + backing: .buffered, + defer: false + ) + window.backgroundColor = NSColor.clear + window.isReleasedWhenClosed = false + } + + func showChooserWindow(url: URL) { + window.contentView = NSHostingView( + rootView: ChooserScreenBindingView(presenter: chooserScreenPresenterFactory(url)) + ) + window.setFrameOrigin(NSEvent.mouseLocation) + window.orderFront(nil) + } +} diff --git a/Browsy/Dependencies.swift b/Browsy/Dependencies.swift new file mode 100644 index 0000000..fb8f7b2 --- /dev/null +++ b/Browsy/Dependencies.swift @@ -0,0 +1,63 @@ +// +// Dependencies.swift +// Browsy +// +// Created by julionb on 31/05/24. +// + +import AppKit +import Sparkle + +class Dependencies { + + lazy var spuStandardUpdaterController: SPUStandardUpdaterController = spuStandardUpdaterControllerFactory() + + lazy var chooserWindowManager: ChooserWindowManager = chooserWindowManagerFactory( + { url in + self.chooserScreenPresenterFactory( + self.browserManagerFactory(self.bundleMainUrlFactory(), self.nsWorkspaceFactory()), + url + ) + } + ) + + func browserManager() -> BrowserManager { + return browserManagerFactory(bundleMainUrlFactory(), nsWorkspaceFactory()) + } + + func chooserScreenPresenter(url: URL) -> ChooserScreenPresenter { + return chooserScreenPresenterFactory( + browserManagerFactory(bundleMainUrlFactory(), nsWorkspaceFactory()), + url + ) + } + + private let chooserWindowManagerFactory: (@escaping (URL) -> ChooserScreenPresenter) -> ChooserWindowManager = { chooserScreenPresenterFactory in + return ChooserWindowManagerImpl( + chooserScreenPresenterFactory: chooserScreenPresenterFactory + ) + } + + private let browserManagerFactory: (URL, NSWorkspace) -> BrowserManager = { bundleMainUrl, nsWorkspace in + return BrowserManagerImpl( + bundleMainUrl: bundleMainUrl, + nsWorkspace: nsWorkspace + ) + } + + private let chooserScreenPresenterFactory = { browserManager, url in + ChooserScreenPresenter(browserManager: browserManager, url: url) + } + + private let bundleMainUrlFactory: () -> URL = { Bundle.main.bundleURL } + + private let nsWorkspaceFactory: () -> NSWorkspace = { NSWorkspace.shared } + + private let spuStandardUpdaterControllerFactory: () -> SPUStandardUpdaterController = { + SPUStandardUpdaterController( + startingUpdater: true, + updaterDelegate: nil, + userDriverDelegate: nil + ) + } +} diff --git a/Browsy/Info.plist b/Browsy/Info.plist index 7cacf3f..fa667a4 100644 --- a/Browsy/Info.plist +++ b/Browsy/Info.plist @@ -2,44 +2,56 @@ - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIconFile - - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleURLTypes + CFBundleDocumentTypes + CFBundleTypeName + HTML document + CFBundleTypeRole + Viewer + LSHandlerRank + Default + LSItemContentTypes + + public.html + + + + CFBundleTypeName + XHTML document CFBundleTypeRole - Editor + Viewer + LSHandlerRank + Default + LSItemContentTypes + + public.xhtml + + + + CFBundleURLTypes + + CFBundleURLName - Browsy + Web site URL CFBundleURLSchemes http + https + + + + CFBundleURLName + Local file URL + CFBundleURLSchemes + + file - CFBundleVersion - 1 - LSMinimumSystemVersion - $(MACOSX_DEPLOYMENT_TARGET) - NSHumanReadableCopyright - Copyright © 2017 kJulio. All rights reserved. - NSMainStoryboardFile - Main - NSPrincipalClass - NSApplication + SUFeedURL + https://julioromano.github.io/Browsy/appcast.xml + SUPublicEDKey + KQG1xpXYiIMtaQazFvIvP0dZ5D/cpFfMoVUJ7XK766s= diff --git a/Browsy/MenuView.swift b/Browsy/MenuView.swift new file mode 100644 index 0000000..966cf32 --- /dev/null +++ b/Browsy/MenuView.swift @@ -0,0 +1,28 @@ +// +// MenuView.swift +// Browsy +// +// Created by julionb on 01/06/24. +// + +import SwiftUI + +struct MenuView: View { + let quitAction: () -> Void + let checkForUpdates: () -> Void + + var body: some View { + Text("Browsy v0.1") + Button(action: checkForUpdates, label: { Text("Check for updates...") }) + Divider() + Button(action: quitAction, label: { Text("Quit") }) + .keyboardShortcut("q", modifiers: .command) + } +} + +#Preview { + MenuView( + quitAction: {}, + checkForUpdates: {} + ) +} diff --git a/Browsy/Preview Content/Preview Assets.xcassets/Contents.json b/Browsy/Preview Content/Preview Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/Browsy/Preview Content/Preview Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Browsy/ViewController.swift b/Browsy/ViewController.swift deleted file mode 100644 index 02d0454..0000000 --- a/Browsy/ViewController.swift +++ /dev/null @@ -1,137 +0,0 @@ - -// -// ViewController.swift -// Browsy -// -// Created by julionb on 31/03/2017. -// Copyright © 2017 kJulio. All rights reserved. -// - -import Cocoa - -class ViewController: NSViewController { - - @IBOutlet weak var urlField: NSTextField! - @IBOutlet weak var tableView: NSTableView! - var browserItems: [Bundle]? - - override func viewDidLoad() { - super.viewDidLoad() - // Do any additional setup after loading the view. - tableView.delegate = self - tableView.dataSource = self - NotificationCenter.default.addObserver( - self, - selector: #selector(self.refreshView(notification:)), - name: NSNotification.Name(rawValue: "lastUrl"), - object: nil - ) - reloadBrowserList() - } - - @objc func refreshView(notification: NSNotification) { - let appDelegate = NSApplication.shared.delegate as! AppDelegate - urlField.stringValue = (appDelegate.lastUrl?.absoluteString)! - } - - override var representedObject: Any? { - didSet { - // Update the view, if already loaded. - } - } - - func getInstalledBrowsers () -> [ Bundle ] { - var browsers = [ Bundle ]() - let array = LSCopyAllHandlersForURLScheme("https" as CFString)? - .takeRetainedValue() - // let array = LSCopyAllRoleHandlersForContentType( - // "public.html" as CFString, LSRolesMask.all)?.takeRetainedValue() - for i in 0.. Int { - return browserItems?.count ?? 0 - } - -} - -extension ViewController: NSTableViewDelegate { - - fileprivate enum CellIdentifiers { - static let NameCell = "NameCellID" - static let DescriptionCell = "DescriptionCellID" - } - - func tableView(_ tableView: NSTableView, - viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? { - var image: NSImage? - var text: String = "" - var cellIdentifier: String = "" - let dateFormatter = DateFormatter() - dateFormatter.dateStyle = .long - dateFormatter.timeStyle = .long - // 1 - guard let item = browserItems?[row] else { - return nil - } - // 2 - if tableColumn == tableView.tableColumns[0] { - - let appPath: String = item.bundlePath - let appIcon: NSImage = NSWorkspace.shared.icon(forFile: appPath) - - image = appIcon - text = item.bundleURL.lastPathComponent - cellIdentifier = CellIdentifiers.NameCell - } - // 3 - if let cell = tableView - .makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: cellIdentifier), owner: nil) as? NSTableCellView { - cell.textField?.stringValue = text - cell.imageView?.image = image ?? nil - return cell - } - return nil - } - - func tableViewSelectionDidChange(_ notification: Notification) { - let appDelegate = NSApplication.shared.delegate as! AppDelegate - let itemsSelected = tableView.selectedRowIndexes - for row in itemsSelected { - appDelegate.openLastUrl(appId: browserItems?[row].bundleIdentifier) - } - NSApplication.shared.terminate(self) - } - -} - -extension Bundle { - var displayName: String? { - return object(forInfoDictionaryKey: "CFBundleDisplayName") as? String - } -} diff --git a/BrowsyTests/BrowsyTests.swift b/BrowsyTests/BrowsyTests.swift index 0e71be3..14bfc86 100644 --- a/BrowsyTests/BrowsyTests.swift +++ b/BrowsyTests/BrowsyTests.swift @@ -2,34 +2,35 @@ // BrowsyTests.swift // BrowsyTests // -// Created by Marco Romano on 30/12/2017. -// Copyright © 2017 kJulio. All rights reserved. +// Created by julionb on 30/05/24. // import XCTest +@testable import Browsy -class BrowsyTests: XCTestCase { - - override func setUp() { - super.setUp() +final class BrowsyTests: XCTestCase { + + override func setUpWithError() throws { // Put setup code here. This method is called before the invocation of each test method in the class. } - - override func tearDown() { + + override func tearDownWithError() throws { // Put teardown code here. This method is called after the invocation of each test method in the class. - super.tearDown() } - - func testExample() { + + func testExample() throws { // This is an example of a functional test case. // Use XCTAssert and related functions to verify your tests produce the correct results. + // Any test you write for XCTest can be annotated as throws and async. + // Mark your test throws to produce an unexpected failure when your test encounters an uncaught error. + // Mark your test async to allow awaiting for asynchronous code to complete. Check the results with assertions afterwards. } - - func testPerformanceExample() { + + func testPerformanceExample() throws { // This is an example of a performance test case. self.measure { // Put the code you want to measure the time of here. } } - + } diff --git a/BrowsyTests/ChooserScreen/ChooserScreenPresenterTest.swift b/BrowsyTests/ChooserScreen/ChooserScreenPresenterTest.swift new file mode 100644 index 0000000..bf7e672 --- /dev/null +++ b/BrowsyTests/ChooserScreen/ChooserScreenPresenterTest.swift @@ -0,0 +1,52 @@ +// +// ChooserScreenPresenterTest.swift +// BrowsyTests +// +// Created by julionb on 31/05/24. +// + +import XCTest +@testable import Browsy + +class ChooserScreenPresenterTests: XCTestCase { + var presenter: ChooserScreenPresenter! + + override func setUp() { + super.setUp() + presenter = ChooserScreenPresenter( + browserManager: BrowserManagerFake(), + url: URL(string: "https://www.apple.com")! + ) + } + + override func tearDown() { + presenter = nil + super.tearDown() + } + + func testOnBrowserClicked() { + // Arrange + let testBrowser = URL(string: "https://www.example.com")! + + // Act + presenter.onBrowserClicked(testBrowser) + + // Assert + // Replace this with the actual expected behavior + XCTAssertEqual(presenter.state.url, "www.apple.com") + } +} + +class BrowserManagerFake: BrowserManager { + func getBrowserIdentifiers() -> [Browser] { + return aBrowserList() + } + + func openURL(_ url: URL, in browserId: URL) { + // no-op + } + + func setAsDefaultBrowser() { + // no-op + } +} diff --git a/BrowsyTests/Info.plist b/BrowsyTests/Info.plist deleted file mode 100644 index 6c40a6c..0000000 --- a/BrowsyTests/Info.plist +++ /dev/null @@ -1,22 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - BNDL - CFBundleShortVersionString - 1.0 - CFBundleVersion - 1 - - diff --git a/BrowsyUITests/BrowsyUITests.swift b/BrowsyUITests/BrowsyUITests.swift new file mode 100644 index 0000000..a3a9732 --- /dev/null +++ b/BrowsyUITests/BrowsyUITests.swift @@ -0,0 +1,41 @@ +// +// BrowsyUITests.swift +// BrowsyUITests +// +// Created by julionb on 30/05/24. +// + +import XCTest + +final class BrowsyUITests: 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 { + // UI tests must launch the application that they test. + let app = XCUIApplication() + app.launch() + + // Use XCTAssert and related functions to verify your tests produce the correct results. + } + + 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/BrowsyUITests/BrowsyUITestsLaunchTests.swift b/BrowsyUITests/BrowsyUITestsLaunchTests.swift new file mode 100644 index 0000000..e7e1b9a --- /dev/null +++ b/BrowsyUITests/BrowsyUITestsLaunchTests.swift @@ -0,0 +1,32 @@ +// +// BrowsyUITestsLaunchTests.swift +// BrowsyUITests +// +// Created by julionb on 30/05/24. +// + +import XCTest + +final class BrowsyUITestsLaunchTests: 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) + } +}