diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..3167581e --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "Extern/Sparkle"] + path = Extern/Sparkle + url = https://github.com/sparkle-project/Sparkle.git diff --git a/.swiftlint.yml b/.swiftlint.yml index aef19e03..4fac1867 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -16,6 +16,9 @@ disabled_rules: - operator_whitespace - redundant_string_enum_value +excluded: + - Extern + opt_in_rules: # Prefer checking `isEmpty` over `count > 0` - empty_count @@ -28,4 +31,4 @@ trailing_comma: mandatory_comma: true identifier_name: min_length: - warning: 2 \ No newline at end of file + warning: 2 diff --git a/Aerial.xcodeproj/project.pbxproj b/Aerial.xcodeproj/project.pbxproj index 8bc4981f..db8b2127 100644 --- a/Aerial.xcodeproj/project.pbxproj +++ b/Aerial.xcodeproj/project.pbxproj @@ -35,6 +35,16 @@ 033D62AF216CAE2C00F3AF83 /* icon-night-dark.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 033D62AE216CAE2C00F3AF83 /* icon-night-dark.pdf */; }; 033D62B0216CAE2C00F3AF83 /* icon-night-dark.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 033D62AE216CAE2C00F3AF83 /* icon-night-dark.pdf */; }; 033D62B1216CAE2C00F3AF83 /* icon-night-dark.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 033D62AE216CAE2C00F3AF83 /* icon-night-dark.pdf */; }; + 034116CC23F9AD0100CD7674 /* Sparkle.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 034116B523F9ACE300CD7674 /* Sparkle.framework */; }; + 034116CD23F9AD0100CD7674 /* Sparkle.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 034116B523F9ACE300CD7674 /* Sparkle.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 034116CF23F9AD0600CD7674 /* Sparkle.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 034116B523F9ACE300CD7674 /* Sparkle.framework */; }; + 034116D023F9AD0600CD7674 /* Sparkle.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 034116B523F9ACE300CD7674 /* Sparkle.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 034116D323F9BD3100CD7674 /* PrefsUpdates.swift in Sources */ = {isa = PBXBuildFile; fileRef = 034116D223F9BD3100CD7674 /* PrefsUpdates.swift */; }; + 034116D423F9BD3100CD7674 /* PrefsUpdates.swift in Sources */ = {isa = PBXBuildFile; fileRef = 034116D223F9BD3100CD7674 /* PrefsUpdates.swift */; }; + 034116D923FADE3600CD7674 /* UpdateReleaseWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 034116D823FADE3600CD7674 /* UpdateReleaseWindow.xib */; }; + 034116DA23FADE3600CD7674 /* UpdateReleaseWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 034116D823FADE3600CD7674 /* UpdateReleaseWindow.xib */; }; + 034116DC23FADEDA00CD7674 /* UpdateReleaseController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 034116DB23FADEDA00CD7674 /* UpdateReleaseController.swift */; }; + 034116DD23FADEDA00CD7674 /* UpdateReleaseController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 034116DB23FADEDA00CD7674 /* UpdateReleaseController.swift */; }; 034F29B423A7A79B004B34D5 /* PWC+Info.swift in Sources */ = {isa = PBXBuildFile; fileRef = 034F29B323A7A79B004B34D5 /* PWC+Info.swift */; }; 034F29B723A7A93D004B34D5 /* InfoTableSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 034F29B623A7A93D004B34D5 /* InfoTableSource.swift */; }; 034F29B823A7A9B3004B34D5 /* InfoTableSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 034F29B623A7A93D004B34D5 /* InfoTableSource.swift */; }; @@ -164,9 +174,6 @@ 03E8731121662AEB002B469B /* AsynchronousOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E8730E216501ED002B469B /* AsynchronousOperation.swift */; }; 03E8731321675FE0002B469B /* TimeManagement.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E8731221675FE0002B469B /* TimeManagement.swift */; }; 03E87314216760B7002B469B /* TimeManagement.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E8731221675FE0002B469B /* TimeManagement.swift */; }; - 1CE1414C7F559B453E61831F /* Pods_AerialApp.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA0922E026F9FAC43AF7A569 /* Pods_AerialApp.framework */; }; - 42813D561DB8096CC34CB535 /* Pods_Aerial_Tests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7E7FC91C9058F0A22FBCC762 /* Pods_Aerial_Tests.framework */; }; - 70CA722D8D5D59C803F3B81B /* Pods_Aerial.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8C010F2542FCE112D8A6E5CA /* Pods_Aerial.framework */; }; AA7E2E5E1FC62E8B00E5F320 /* AerialPlayerItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA7E2E5D1FC62E8B00E5F320 /* AerialPlayerItem.swift */; }; F00864B423AAE7F0003210EF /* DarkMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = F00864B323AAE7F0003210EF /* DarkMode.swift */; }; F00864B523AAE7F0003210EF /* DarkMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = F00864B323AAE7F0003210EF /* DarkMode.swift */; }; @@ -208,6 +215,90 @@ /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ + 034116B423F9ACE300CD7674 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 034116A223F9ACE300CD7674 /* Sparkle.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 8DC2EF5B0486A6940098B216; + remoteInfo = Sparkle; + }; + 034116B623F9ACE300CD7674 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 034116A223F9ACE300CD7674 /* Sparkle.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 61B5F90209C4CEE200B25A18; + remoteInfo = "Sparkle Test App"; + }; + 034116B823F9ACE300CD7674 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 034116A223F9ACE300CD7674 /* Sparkle.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 612279D90DB5470200AB99EA; + remoteInfo = "Sparkle Unit Tests"; + }; + 034116BA23F9ACE300CD7674 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 034116A223F9ACE300CD7674 /* Sparkle.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 5D06E8D00FD68C7C005AE3F6; + remoteInfo = BinaryDelta; + }; + 034116BC23F9ACE300CD7674 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 034116A223F9ACE300CD7674 /* Sparkle.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 55C14BB7136EEF1500649790; + remoteInfo = Autoupdate; + }; + 034116BE23F9ACE300CD7674 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 034116A223F9ACE300CD7674 /* Sparkle.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 726B2B5D1C645FC900388755; + remoteInfo = "UI Tests"; + }; + 034116C023F9ACE300CD7674 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 034116A223F9ACE300CD7674 /* Sparkle.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 722954B41D04ADAF00ECF9CA; + remoteInfo = fileop; + }; + 034116C223F9ACE300CD7674 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 034116A223F9ACE300CD7674 /* Sparkle.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 5AE13FB31E0D9E07000D2C2C; + remoteInfo = generate_appcast; + }; + 034116C423F9ACE300CD7674 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 034116A223F9ACE300CD7674 /* Sparkle.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 5AB8F19F214DA72000A1187F; + remoteInfo = generate_keys; + }; + 034116C623F9ACE300CD7674 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 034116A223F9ACE300CD7674 /* Sparkle.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 5A5ADED7214EDE4900DF0099; + remoteInfo = sign_update; + }; + 034116C823F9ACE300CD7674 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 034116A223F9ACE300CD7674 /* Sparkle.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = EA4311EA229D651300A5503D; + remoteInfo = bsdiff; + }; + 034116CA23F9ACE300CD7674 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 034116A223F9ACE300CD7674 /* Sparkle.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = EA4311A0229D5FBC00A5503D; + remoteInfo = ed25519; + }; FA7199731D94EC5A00FBC99B /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = FACAF19C1BD9FC6000E539DC /* Project object */; @@ -217,6 +308,31 @@ }; /* End PBXContainerItemProxy section */ +/* Begin PBXCopyFilesBuildPhase section */ + 034116CE23F9AD0100CD7674 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 034116CD23F9AD0100CD7674 /* Sparkle.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; + 034116D123F9AD0600CD7674 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 034116D023F9AD0600CD7674 /* Sparkle.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + /* Begin PBXFileReference section */ 0306336723A1012200046A59 /* LocationLayer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationLayer.swift; sourceTree = ""; }; 0306336A23A142FA00046A59 /* LayerOffsets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LayerOffsets.swift; sourceTree = ""; }; @@ -232,6 +348,10 @@ 033192E0217B78240073B580 /* en.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = en.json; sourceTree = ""; }; 033D62AA216CADCD00F3AF83 /* icon-day-dark.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = "icon-day-dark.pdf"; sourceTree = ""; }; 033D62AE216CAE2C00F3AF83 /* icon-night-dark.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = "icon-night-dark.pdf"; sourceTree = ""; }; + 034116A223F9ACE300CD7674 /* Sparkle.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Sparkle.xcodeproj; path = Extern/Sparkle/Sparkle.xcodeproj; sourceTree = ""; }; + 034116D223F9BD3100CD7674 /* PrefsUpdates.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrefsUpdates.swift; sourceTree = ""; }; + 034116D823FADE3600CD7674 /* UpdateReleaseWindow.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = UpdateReleaseWindow.xib; sourceTree = ""; }; + 034116DB23FADEDA00CD7674 /* UpdateReleaseController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UpdateReleaseController.swift; sourceTree = ""; }; 034F29B323A7A79B004B34D5 /* PWC+Info.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PWC+Info.swift"; sourceTree = ""; }; 034F29B623A7A93D004B34D5 /* InfoTableSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfoTableSource.swift; sourceTree = ""; }; 034F29BE23A7E28E004B34D5 /* PrefsInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrefsInfo.swift; sourceTree = ""; }; @@ -301,19 +421,10 @@ 03E8730B2165013C002B469B /* DownloadManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DownloadManager.swift; sourceTree = ""; }; 03E8730E216501ED002B469B /* AsynchronousOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AsynchronousOperation.swift; sourceTree = ""; }; 03E8731221675FE0002B469B /* TimeManagement.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimeManagement.swift; sourceTree = ""; }; - 0C8FC8BFBDB12119C417B384 /* Pods-AerialApp.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AerialApp.debug.xcconfig"; path = "Pods/Target Support Files/Pods-AerialApp/Pods-AerialApp.debug.xcconfig"; sourceTree = ""; }; - 16D0EAF0612223CDB1E938A3 /* Pods-Aerial.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Aerial.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Aerial/Pods-Aerial.debug.xcconfig"; sourceTree = ""; }; - 431164E9C62B702ED573DE22 /* Pods-Aerial.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Aerial.release.xcconfig"; path = "Pods/Target Support Files/Pods-Aerial/Pods-Aerial.release.xcconfig"; sourceTree = ""; }; - 6F861C9769B40A0B8FBDC0E6 /* Pods-Aerial Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Aerial Tests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Aerial Tests/Pods-Aerial Tests.debug.xcconfig"; sourceTree = ""; }; - 7E7FC91C9058F0A22FBCC762 /* Pods_Aerial_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Aerial_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 8C010F2542FCE112D8A6E5CA /* Pods_Aerial.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Aerial.framework; sourceTree = BUILT_PRODUCTS_DIR; }; AA7E2E5D1FC62E8B00E5F320 /* AerialPlayerItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AerialPlayerItem.swift; sourceTree = ""; }; - C2789CB51C64430F9CDEABF1 /* Pods-Aerial Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Aerial Tests.release.xcconfig"; path = "Pods/Target Support Files/Pods-Aerial Tests/Pods-Aerial Tests.release.xcconfig"; sourceTree = ""; }; - E783122BE370B662D207D98F /* Pods-AerialApp.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AerialApp.release.xcconfig"; path = "Pods/Target Support Files/Pods-AerialApp/Pods-AerialApp.release.xcconfig"; sourceTree = ""; }; F00864B323AAE7F0003210EF /* DarkMode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DarkMode.swift; sourceTree = ""; }; F00864B623AAE8E9003210EF /* NightShift.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NightShift.swift; sourceTree = ""; }; F008DAFC23AADCFB00739DE1 /* Brightness.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Brightness.swift; sourceTree = ""; }; - FA0922E026F9FAC43AF7A569 /* Pods_AerialApp.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_AerialApp.framework; sourceTree = BUILT_PRODUCTS_DIR; }; FA143CD61BDA3E880041A82B /* AerialApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AerialApp.app; sourceTree = BUILT_PRODUCTS_DIR; }; FA143CE51BDA3EEF0041A82B /* AVKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVKit.framework; path = System/Library/Frameworks/AVKit.framework; sourceTree = SDKROOT; }; FA36BD3E1BE57F8E00D5E03B /* VideoDownload.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = VideoDownload.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; @@ -348,7 +459,7 @@ 03510C772185EF8F008F74F2 /* CoreLocation.framework in Frameworks */, 03510C6B21834EB2008F74F2 /* IOKit.framework in Frameworks */, FA143CE61BDA3EEF0041A82B /* AVKit.framework in Frameworks */, - 1CE1414C7F559B453E61831F /* Pods_AerialApp.framework in Frameworks */, + 034116CF23F9AD0600CD7674 /* Sparkle.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -356,7 +467,6 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 42813D561DB8096CC34CB535 /* Pods_Aerial_Tests.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -365,8 +475,8 @@ buildActionMask = 2147483647; files = ( 03510C732185EF76008F74F2 /* CoreLocation.framework in Frameworks */, + 034116CC23F9AD0100CD7674 /* Sparkle.framework in Frameworks */, 03510C6C21834EFF008F74F2 /* IOKit.framework in Frameworks */, - 70CA722D8D5D59C803F3B81B /* Pods_Aerial.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -407,6 +517,25 @@ path = Community; sourceTree = ""; }; + 034116A323F9ACE300CD7674 /* Products */ = { + isa = PBXGroup; + children = ( + 034116B523F9ACE300CD7674 /* Sparkle.framework */, + 034116B723F9ACE300CD7674 /* Sparkle Test App.app */, + 034116B923F9ACE300CD7674 /* Sparkle Unit Tests.xctest */, + 034116BB23F9ACE300CD7674 /* BinaryDelta */, + 034116BD23F9ACE300CD7674 /* Autoupdate.app */, + 034116BF23F9ACE300CD7674 /* UI Tests.xctest */, + 034116C123F9ACE300CD7674 /* fileop */, + 034116C323F9ACE300CD7674 /* generate_appcast */, + 034116C523F9ACE300CD7674 /* generate_keys */, + 034116C723F9ACE300CD7674 /* sign_update */, + 034116C923F9ACE300CD7674 /* libbsdiff.a */, + 034116CB23F9ACE300CD7674 /* libed25519.a */, + ); + name = Products; + sourceTree = ""; + }; 034F29B523A7A8E1004B34D5 /* PrefPanel */ = { isa = PBXGroup; children = ( @@ -434,6 +563,7 @@ 038D2EDD23B0FB0D00CD91F7 /* PrefsVideos.swift */, 0361B9A723D732A300B6252D /* PrefsDisplays.swift */, 0361B9AA23D73D4500B6252D /* PrefsTime.swift */, + 034116D223F9BD3100CD7674 /* PrefsUpdates.swift */, ); path = Prefs; sourceTree = ""; @@ -512,28 +642,13 @@ path = Hardware; sourceTree = ""; }; - F1B1238D786BBB1C50CB8803 /* Pods */ = { - isa = PBXGroup; - children = ( - 16D0EAF0612223CDB1E938A3 /* Pods-Aerial.debug.xcconfig */, - 431164E9C62B702ED573DE22 /* Pods-Aerial.release.xcconfig */, - 6F861C9769B40A0B8FBDC0E6 /* Pods-Aerial Tests.debug.xcconfig */, - C2789CB51C64430F9CDEABF1 /* Pods-Aerial Tests.release.xcconfig */, - 0C8FC8BFBDB12119C417B384 /* Pods-AerialApp.debug.xcconfig */, - E783122BE370B662D207D98F /* Pods-AerialApp.release.xcconfig */, - ); - name = Pods; - sourceTree = ""; - }; FA2D7AA01BDD849E009EA54C /* Frameworks */ = { isa = PBXGroup; children = ( + 034116A223F9ACE300CD7674 /* Sparkle.xcodeproj */, 03510C722185EF76008F74F2 /* CoreLocation.framework */, 03510C6A21834EB2008F74F2 /* IOKit.framework */, FA143CE51BDA3EEF0041A82B /* AVKit.framework */, - 8C010F2542FCE112D8A6E5CA /* Pods_Aerial.framework */, - 7E7FC91C9058F0A22FBCC762 /* Pods_Aerial_Tests.framework */, - FA0922E026F9FAC43AF7A569 /* Pods_AerialApp.framework */, ); name = Frameworks; sourceTree = ""; @@ -581,6 +696,7 @@ 0395835121807D1F008E8F9C /* thumbnail@2x.png */, FAC36F3A1BE1756D007F2A20 /* PreferencesWindow.xib */, 0313F9E522942AA500B074BB /* CustomVideos.xib */, + 034116D823FADE3600CD7674 /* UpdateReleaseWindow.xib */, ); path = Resources; sourceTree = ""; @@ -602,6 +718,7 @@ 03608A1122A54921008F08A2 /* PWC Tabs */, FAC36F3E1BE1756D007F2A20 /* PreferencesWindowController.swift */, 0313F9E722942B4500B074BB /* CustomVideoController.swift */, + 034116DB23FADEDA00CD7674 /* UpdateReleaseController.swift */, ); path = Controllers; sourceTree = ""; @@ -671,7 +788,6 @@ FA71996F1D94EC5A00FBC99B /* Tests */, FA2D7AA01BDD849E009EA54C /* Frameworks */, FACAF1A61BD9FC6000E539DC /* Products */, - F1B1238D786BBB1C50CB8803 /* Pods */, ); sourceTree = ""; }; @@ -703,12 +819,11 @@ isa = PBXNativeTarget; buildConfigurationList = FA143CE01BDA3E880041A82B /* Build configuration list for PBXNativeTarget "AerialApp" */; buildPhases = ( - B326E4EB5930FD08EEA5D212 /* [CP] Check Pods Manifest.lock */, FA74B8481D94DCE0004FE056 /* Run Script - Swiftlint */, FA143CD21BDA3E880041A82B /* Sources */, FA143CD31BDA3E880041A82B /* Frameworks */, FA143CD41BDA3E880041A82B /* Resources */, - 6F6791269A5D5F62796AE75A /* [CP] Embed Pods Frameworks */, + 034116D123F9AD0600CD7674 /* Embed Frameworks */, ); buildRules = ( ); @@ -723,7 +838,6 @@ isa = PBXNativeTarget; buildConfigurationList = FA7199751D94EC5A00FBC99B /* Build configuration list for PBXNativeTarget "Aerial Tests" */; buildPhases = ( - 3B10443BE2EC7A75E1F031DF /* [CP] Check Pods Manifest.lock */, FA71996A1D94EC5A00FBC99B /* Sources */, FA71996B1D94EC5A00FBC99B /* Frameworks */, FA71996C1D94EC5A00FBC99B /* Resources */, @@ -742,13 +856,12 @@ isa = PBXNativeTarget; buildConfigurationList = FACAF1AF1BD9FC6000E539DC /* Build configuration list for PBXNativeTarget "Aerial" */; buildPhases = ( - 910394578D35CCEBAEE0D456 /* [CP] Check Pods Manifest.lock */, 7E9B50FB2187D302002895ED /* Run Script - Swiftlint */, FACAF1A01BD9FC6000E539DC /* Sources */, FACAF1A11BD9FC6000E539DC /* Frameworks */, FACAF1A21BD9FC6000E539DC /* Headers */, FACAF1A31BD9FC6000E539DC /* Resources */, - 030E8CFC21C2CC13008272B9 /* [CP] Embed Pods Frameworks */, + 034116CE23F9AD0100CD7674 /* Embed Frameworks */, 038EF1B623E86DCA00E9D379 /* ShellScript */, ); buildRules = ( @@ -801,6 +914,12 @@ mainGroup = FACAF19B1BD9FC6000E539DC; productRefGroup = FACAF1A61BD9FC6000E539DC /* Products */; projectDirPath = ""; + projectReferences = ( + { + ProductGroup = 034116A323F9ACE300CD7674 /* Products */; + ProjectRef = 034116A223F9ACE300CD7674 /* Sparkle.xcodeproj */; + }, + ); projectRoot = ""; targets = ( FACAF1A41BD9FC6000E539DC /* Aerial */, @@ -810,6 +929,93 @@ }; /* End PBXProject section */ +/* Begin PBXReferenceProxy section */ + 034116B523F9ACE300CD7674 /* Sparkle.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = Sparkle.framework; + remoteRef = 034116B423F9ACE300CD7674 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 034116B723F9ACE300CD7674 /* Sparkle Test App.app */ = { + isa = PBXReferenceProxy; + fileType = wrapper.application; + path = "Sparkle Test App.app"; + remoteRef = 034116B623F9ACE300CD7674 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 034116B923F9ACE300CD7674 /* Sparkle Unit Tests.xctest */ = { + isa = PBXReferenceProxy; + fileType = wrapper.cfbundle; + path = "Sparkle Unit Tests.xctest"; + remoteRef = 034116B823F9ACE300CD7674 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 034116BB23F9ACE300CD7674 /* BinaryDelta */ = { + isa = PBXReferenceProxy; + fileType = "compiled.mach-o.executable"; + path = BinaryDelta; + remoteRef = 034116BA23F9ACE300CD7674 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 034116BD23F9ACE300CD7674 /* Autoupdate.app */ = { + isa = PBXReferenceProxy; + fileType = wrapper.application; + path = Autoupdate.app; + remoteRef = 034116BC23F9ACE300CD7674 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 034116BF23F9ACE300CD7674 /* UI Tests.xctest */ = { + isa = PBXReferenceProxy; + fileType = wrapper.cfbundle; + path = "UI Tests.xctest"; + remoteRef = 034116BE23F9ACE300CD7674 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 034116C123F9ACE300CD7674 /* fileop */ = { + isa = PBXReferenceProxy; + fileType = "compiled.mach-o.executable"; + path = fileop; + remoteRef = 034116C023F9ACE300CD7674 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 034116C323F9ACE300CD7674 /* generate_appcast */ = { + isa = PBXReferenceProxy; + fileType = "compiled.mach-o.executable"; + path = generate_appcast; + remoteRef = 034116C223F9ACE300CD7674 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 034116C523F9ACE300CD7674 /* generate_keys */ = { + isa = PBXReferenceProxy; + fileType = "compiled.mach-o.executable"; + path = generate_keys; + remoteRef = 034116C423F9ACE300CD7674 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 034116C723F9ACE300CD7674 /* sign_update */ = { + isa = PBXReferenceProxy; + fileType = "compiled.mach-o.executable"; + path = sign_update; + remoteRef = 034116C623F9ACE300CD7674 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 034116C923F9ACE300CD7674 /* libbsdiff.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libbsdiff.a; + remoteRef = 034116C823F9ACE300CD7674 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 034116CB23F9ACE300CD7674 /* libed25519.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libed25519.a; + remoteRef = 034116CA23F9ACE300CD7674 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; +/* End PBXReferenceProxy section */ + /* Begin PBXResourcesBuildPhase section */ FA143CD41BDA3E880041A82B /* Resources */ = { isa = PBXResourcesBuildPhase; @@ -839,6 +1045,7 @@ 035A92A9225F8C480095AB85 /* he.json in Resources */, 035A92A7225F8C480095AB85 /* de.json in Resources */, 0395835421807D1F008E8F9C /* thumbnail@2x.png in Resources */, + 034116DA23FADE3600CD7674 /* UpdateReleaseWindow.xib in Resources */, 03D1E79822848F7F00D10CF7 /* screen0.jpg in Resources */, 03D37FDC22145487005A146F /* fr.json in Resources */, ); @@ -880,6 +1087,7 @@ 038EBE9422D0AA3D00C7AD02 /* nl.json in Resources */, 033D62AF216CAE2C00F3AF83 /* icon-night-dark.pdf in Resources */, 0369985D2196103300E359D3 /* missingvideos.json in Resources */, + 034116D923FADE3600CD7674 /* UpdateReleaseWindow.xib in Resources */, 03E4B20D22DC7F8800C22EBE /* zh_TW.json in Resources */, FAC36F4F1BE1756D007F2A20 /* icon-night.pdf in Resources */, 0313F9E622942AA500B074BB /* CustomVideos.xib in Resources */, @@ -890,29 +1098,6 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 030E8CFC21C2CC13008272B9 /* [CP] Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${SRCROOT}/Pods/Target Support Files/Pods-Aerial/Pods-Aerial-frameworks.sh", - "${PODS_ROOT}/Sparkle/Sparkle.framework", - "${PODS_ROOT}/Sparkle/Sparkle.framework.dSYM", - ); - name = "[CP] Embed Pods Frameworks"; - outputFileListPaths = ( - ); - outputPaths = ( - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Sparkle.framework", - "${DWARF_DSYM_FOLDER_PATH}/Sparkle.framework.dSYM", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "# Type a script or drag a script file from your workspace to insert its path.\n\"${SRCROOT}/Pods/Target Support Files/Pods-Aerial/Pods-Aerial-frameworks.sh\"\n"; - }; 038EF1B623E86DCA00E9D379 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -930,44 +1115,6 @@ shellPath = /bin/sh; shellScript = "# Type a script or drag a script file from your workspace to insert its path.\nLOCATION=\"${BUILT_PRODUCTS_DIR}\"/\"${FRAMEWORKS_FOLDER_PATH}\"\n\n# By default, use the configured code signing identity for the project/target\nIDENTITY=\"${CODE_SIGN_IDENTITY}\"\nif [ \"$IDENTITY\" == \"\" ]\nthen\n # If a code signing identity is not specified, use ad hoc signing\n IDENTITY=\"-\"\nfi\ncodesign --verbose --force --deep -o runtime --sign \"$IDENTITY\" \"$LOCATION/Sparkle.framework/Versions/A/Resources/AutoUpdate.app\"\ncodesign --verbose --force -o runtime --sign \"$IDENTITY\" \"$LOCATION/Sparkle.framework/Versions/A\"\n"; }; - 3B10443BE2EC7A75E1F031DF /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Aerial Tests-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; - 6F6791269A5D5F62796AE75A /* [CP] Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-AerialApp/Pods-AerialApp-frameworks.sh", - "${PODS_ROOT}/Sparkle/Sparkle.framework", - "${PODS_ROOT}/Sparkle/Sparkle.framework.dSYM", - ); - name = "[CP] Embed Pods Frameworks"; - outputPaths = ( - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Sparkle.framework", - "${DWARF_DSYM_FOLDER_PATH}/Sparkle.framework.dSYM", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-AerialApp/Pods-AerialApp-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; 7E9B50FB2187D302002895ED /* Run Script - Swiftlint */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -982,42 +1129,6 @@ shellPath = /bin/sh; shellScript = "#if which swiftlint >/dev/null; then\n# if [ -z \"$CI\" ]; then\n# make --directory=${SRCROOT} xcode-lint\n# fi\n#else\n# echo \"warning: SwiftLint not installed, install using `brew install swiftlint`\"\n#fi\nif which swiftlint >/dev/null; then\n swiftlint autocorrect\nelse\n echo \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi\n"; }; - 910394578D35CCEBAEE0D456 /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Aerial-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; - B326E4EB5930FD08EEA5D212 /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-AerialApp-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; FA74B8481D94DCE0004FE056 /* Run Script - Swiftlint */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -1065,6 +1176,7 @@ 03608A2122A55BC2008F08A2 /* PWC+Cache.swift in Sources */, 038D2EE523B6565900CD91F7 /* InfoBatteryView.swift in Sources */, 030D9B7C21551A8D00961E95 /* AerialPlayerItem.swift in Sources */, + 034116DD23FADEDA00CD7674 /* UpdateReleaseController.swift in Sources */, 03608A2D22A56465008F08A2 /* HardwareDetection.swift in Sources */, 036A57D923F4747D0009DC02 /* InfoCountdownView.swift in Sources */, FAC36F5E1BE1756D007F2A20 /* CheckCellView.swift in Sources */, @@ -1090,6 +1202,7 @@ 03BF51BD23A26522008AD373 /* LayerManager.swift in Sources */, 03608A1B22A55B9A008F08A2 /* PWC+Time.swift in Sources */, FA6F81DD1D939455007975FE /* Preferences.swift in Sources */, + 034116D423F9BD3100CD7674 /* PrefsUpdates.swift in Sources */, FAF450221BE2B45D00C1F98A /* VideoLoader.swift in Sources */, 036A57DC23F5828E0009DC02 /* CountdownLayer.swift in Sources */, 0313F9EA2294338300B074BB /* CustomVideoController.swift in Sources */, @@ -1127,6 +1240,7 @@ F00864B723AAE8E9003210EF /* NightShift.swift in Sources */, 03608A1A22A55B9A008F08A2 /* PWC+Time.swift in Sources */, FAC36F5D1BE1756D007F2A20 /* CheckCellView.swift in Sources */, + 034116D323F9BD3100CD7674 /* PrefsUpdates.swift in Sources */, FAC36F5B1BE1756D007F2A20 /* AerialView.swift in Sources */, 0393857A2175D4B80040B850 /* AVPlayerViewExtension.swift in Sources */, 03E8730F216501ED002B469B /* AsynchronousOperation.swift in Sources */, @@ -1156,6 +1270,7 @@ 03608A2322A55BF1008F08A2 /* PWC+Updates.swift in Sources */, AA7E2E5E1FC62E8B00E5F320 /* AerialPlayerItem.swift in Sources */, 03608A2C22A56465008F08A2 /* HardwareDetection.swift in Sources */, + 034116DC23FADEDA00CD7674 /* UpdateReleaseController.swift in Sources */, 03608A1022A54887008F08A2 /* PWC+Videos.swift in Sources */, 03A596D323AA750F0097EA66 /* InfoMessageView.swift in Sources */, 03608A2022A55BC2008F08A2 /* PWC+Cache.swift in Sources */, @@ -1214,18 +1329,18 @@ /* Begin XCBuildConfiguration section */ FA143CE11BDA3E880041A82B /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 0C8FC8BFBDB12119C417B384 /* Pods-AerialApp.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "Mac Developer"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; + CURRENT_PROJECT_VERSION = 1.8.0; DEVELOPMENT_TEAM = 3L54M5L5KK; ENABLE_TESTABILITY = YES; INFOPLIST_FILE = Aerial/App/Resources/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 10.9; - MARKETING_VERSION = 1.6.5; + MACOSX_DEPLOYMENT_TARGET = 10.12; + MARKETING_VERSION = 1.8.0; PRODUCT_BUNDLE_IDENTIFIER = "com.johncoates.Aerial-Test"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -1237,18 +1352,18 @@ }; FA143CE21BDA3E880041A82B /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = E783122BE370B662D207D98F /* Pods-AerialApp.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "Mac Developer"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; + CURRENT_PROJECT_VERSION = 1.8.0; DEVELOPMENT_TEAM = 3L54M5L5KK; ENABLE_TESTABILITY = YES; INFOPLIST_FILE = Aerial/App/Resources/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 10.9; - MARKETING_VERSION = 1.6.5; + MACOSX_DEPLOYMENT_TARGET = 10.12; + MARKETING_VERSION = 1.8.0; PRODUCT_BUNDLE_IDENTIFIER = "com.johncoates.Aerial-Test"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -1260,7 +1375,6 @@ }; FA7199761D94EC5A00FBC99B /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 6F861C9769B40A0B8FBDC0E6 /* Pods-Aerial Tests.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CLANG_ANALYZER_NONNULL = YES; @@ -1282,7 +1396,6 @@ }; FA7199771D94EC5A00FBC99B /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = C2789CB51C64430F9CDEABF1 /* Pods-Aerial Tests.release.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CLANG_ANALYZER_NONNULL = YES; @@ -1346,7 +1459,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.9; + MACOSX_DEPLOYMENT_TARGET = 10.12; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; OTHER_CODE_SIGN_FLAGS = "--timestamp"; @@ -1396,7 +1509,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.9; + MACOSX_DEPLOYMENT_TARGET = 10.12; MTL_ENABLE_DEBUG_INFO = NO; OTHER_CODE_SIGN_FLAGS = "--timestamp"; SDKROOT = macosx; @@ -1407,7 +1520,6 @@ }; FACAF1B01BD9FC6000E539DC /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 16D0EAF0612223CDB1E938A3 /* Pods-Aerial.debug.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = NO; @@ -1415,15 +1527,15 @@ CODE_SIGN_IDENTITY = "Developer ID Application: Guillaume Louel (3L54M5L5KK)"; CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 1.7.2beta1; + CURRENT_PROJECT_VERSION = 1.8.0; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 3L54M5L5KK; ENABLE_HARDENED_RUNTIME = YES; INFOPLIST_FILE = "$(SRCROOT)/Resources/Info.plist"; INSTALL_PATH = "$(HOME)/Library/Screen Savers"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 10.9; - MARKETING_VERSION = 1.7.2beta1; + MACOSX_DEPLOYMENT_TARGET = 10.12; + MARKETING_VERSION = 1.8.0; PRODUCT_BUNDLE_IDENTIFIER = com.johncoates.Aerial; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -1436,7 +1548,6 @@ }; FACAF1B11BD9FC6000E539DC /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 431164E9C62B702ED573DE22 /* Pods-Aerial.release.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = NO; @@ -1444,15 +1555,15 @@ CODE_SIGN_IDENTITY = "Developer ID Application: Guillaume Louel (3L54M5L5KK)"; CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 1.7.2beta1; + CURRENT_PROJECT_VERSION = 1.8.0; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 3L54M5L5KK; ENABLE_HARDENED_RUNTIME = YES; INFOPLIST_FILE = "$(SRCROOT)/Resources/Info.plist"; INSTALL_PATH = "$(HOME)/Library/Screen Savers"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 10.9; - MARKETING_VERSION = 1.7.2beta1; + MACOSX_DEPLOYMENT_TARGET = 10.12; + MARKETING_VERSION = 1.8.0; OTHER_CODE_SIGN_FLAGS = "--timestamp"; PRODUCT_BUNDLE_IDENTIFIER = com.johncoates.Aerial; PRODUCT_NAME = "$(TARGET_NAME)"; diff --git a/Aerial/App/Resources/Info.plist b/Aerial/App/Resources/Info.plist index 0ca24a63..ce1ac1c8 100644 --- a/Aerial/App/Resources/Info.plist +++ b/Aerial/App/Resources/Info.plist @@ -21,7 +21,7 @@ CFBundleSignature ???? CFBundleVersion - 1 + $(CURRENT_PROJECT_VERSION) LSApplicationCategoryType public.app-category.utilities LSMinimumSystemVersion diff --git a/Aerial/Source/Controllers/PWC Tabs/PWC+Info.swift b/Aerial/Source/Controllers/PWC Tabs/PWC+Info.swift index 6c050278..34afde86 100644 --- a/Aerial/Source/Controllers/PWC Tabs/PWC+Info.swift +++ b/Aerial/Source/Controllers/PWC Tabs/PWC+Info.swift @@ -17,14 +17,15 @@ extension PreferencesWindowController { PrefsInfo.layers.append(.battery) } - if !PrefsInfo.layers.contains(.updates) { - PrefsInfo.layers.append(.updates) - } - if !PrefsInfo.layers.contains(.countdown) { PrefsInfo.layers.append(.countdown) } + // Annnd for backward compatibility with 1.7.2 betas, remove the updates that was once here ;) + if PrefsInfo.layers.contains(.updates) { + PrefsInfo.layers.remove(at: PrefsInfo.layers.firstIndex(of: .updates)!) + } + infoSource = InfoTableSource() infoSource?.setController(self) infoTableView.dataSource = infoSource diff --git a/Aerial/Source/Controllers/PWC Tabs/PWC+Updates.swift b/Aerial/Source/Controllers/PWC Tabs/PWC+Updates.swift index 1a928e3e..ab0f5656 100644 --- a/Aerial/Source/Controllers/PWC Tabs/PWC+Updates.swift +++ b/Aerial/Source/Controllers/PWC Tabs/PWC+Updates.swift @@ -27,7 +27,7 @@ extension PreferencesWindowController { lastCheckedSparkle.stringValue = "Never checked for update" } - if sparkleUpdater!.automaticallyChecksForUpdates { + if PrefsUpdates.checkForUpdates { automaticallyCheckForUpdatesCheckbox.state = .on } if preferences.updateWhileSaverMode { @@ -37,6 +37,13 @@ extension PreferencesWindowController { allowBetasCheckbox.state = .on betaCheckFrequencyPopup.isEnabled = true } + + sparkleScreenSaverMode.selectItem(at: PrefsUpdates.sparkleUpdateMode.rawValue) + + // We disable silent installs in Catalina + if #available(OSX 10.15, *) { + silentInstallMenuItem.isEnabled = false + } } // MARK: - Update panel @@ -57,7 +64,8 @@ extension PreferencesWindowController { // Sparkle updates @IBAction func automaticallyCheckForUpdatesChange(_ button: NSButton) { let onState = button.state == .on - sparkleUpdater!.automaticallyChecksForUpdates = onState + PrefsUpdates.checkForUpdates = onState + //sparkleUpdater!.automaticallyChecksForUpdates = onState debugLog("UI automaticallyCheckForUpdatesChange: \(onState)") } @@ -67,6 +75,10 @@ extension PreferencesWindowController { debugLog("UI allowScreenSaverModeUpdatesChange: \(onState)") } + @IBAction func sparkleScreenSaverModeChange(_ sender: NSPopUpButton) { + PrefsUpdates.sparkleUpdateMode = UpdateMode(rawValue: sender.indexOfSelectedItem) ?? .notify + } + @IBAction func allowBetasChange(_ button: NSButton) { let onState = button.state == .on preferences.allowBetas = onState @@ -82,11 +94,54 @@ extension PreferencesWindowController { } } - @IBAction func checkForUpdatesButton(_ sender: Any) { - debugLog("check for updates") - sparkleUpdater!.checkForUpdates(self) + @IBAction func checkForUpdatesButton(_ sender: NSButton) { + if #available(OSX 10.15, *) { + debugLog("check for updates (using Catalina probe)") + + let autoUpdates = AutoUpdates.sharedInstance + + if !autoUpdates.didProbeForUpdate { + // Let's probe + autoUpdates.doProbingCheck() + + _ = Timer.scheduledTimer(withTimeInterval: 2.0, repeats: false, block: { (_) in + self.checkForProbeResults(silent: false) + }) + } else { + // If we already probed, show the results ! + checkForProbeResults(silent: false) + } - lastCheckedSparkle.stringValue = "Last checked today" + } else { + debugLog("check for updates (using Sparkle's auto)") + sparkleUpdater!.checkForUpdates(self) + + lastCheckedSparkle.stringValue = "Last checked today" + } + } + + func checkForProbeResults(silent: Bool) { + let autoUpdates = AutoUpdates.sharedInstance + + if !autoUpdates.didProbeForUpdate { + // Try again in 2s + if #available(OSX 10.12, *) { + _ = Timer.scheduledTimer(withTimeInterval: 2.0, repeats: false, block: { (_) in + self.checkForProbeResults(silent: silent) + }) + } else { + // We should only come here in Catalina anyway + errorLog("checkForProbeResults called in macOS < 10.12") + } + } else { + if autoUpdates.isAnUpdateAvailable() { + updateReleaseController.show(sender: self.versionButton, controller: self) + } else { + if !silent { + updateReleaseController.showNoUpdate() + } + } + } } // Json updates diff --git a/Aerial/Source/Controllers/PreferencesWindowController.swift b/Aerial/Source/Controllers/PreferencesWindowController.swift index 191ff7ab..78736143 100644 --- a/Aerial/Source/Controllers/PreferencesWindowController.swift +++ b/Aerial/Source/Controllers/PreferencesWindowController.swift @@ -18,6 +18,7 @@ import Sparkle final class PreferencesWindowController: NSWindowController, NSOutlineViewDataSource, NSOutlineViewDelegate { lazy var customVideosController: CustomVideoController = CustomVideoController() + lazy var updateReleaseController: UpdateReleaseController = UpdateReleaseController() // Main UI @IBOutlet weak var prefTabView: NSTabView! @@ -98,13 +99,6 @@ final class PreferencesWindowController: NSWindowController, NSOutlineViewDataSo @IBOutlet var infoCountdownView: InfoCountdownView! - // Todo remap those - - @IBOutlet var secondaryMarginHorizontalTextfield: NSTextField! - @IBOutlet var secondaryMarginVerticalTextfield: NSTextField! - @IBOutlet var editMarginsPanel: NSPanel! - @IBOutlet var editExtraMessagePanel: NSPanel! - // Time Tab @IBOutlet var iconTime1: NSImageCell! @IBOutlet var iconTime2: NSImageCell! @@ -168,10 +162,12 @@ final class PreferencesWindowController: NSWindowController, NSOutlineViewDataSo @IBOutlet var automaticallyCheckForUpdatesCheckbox: NSButton! @IBOutlet var allowScreenSaverModeUpdateCheckbox: NSButton! + @IBOutlet var sparkleScreenSaverMode: NSPopUpButton! @IBOutlet var allowBetasCheckbox: NSButton! @IBOutlet var betaCheckFrequencyPopup: NSPopUpButton! @IBOutlet var lastCheckedSparkle: NSTextField! + @IBOutlet var silentInstallMenuItem: NSMenuItem! // Advanced Tab @IBOutlet weak var debugModeCheckbox: NSButton! @IBOutlet weak var showLogBottomClick: NSButton! @@ -279,11 +275,36 @@ final class PreferencesWindowController: NSWindowController, NSOutlineViewDataSo name: Notification.Name.SUUpdaterWillRestart, object: nil) - // Starting the Sparkle update system - sparkleUpdater = SUUpdater.init(for: Bundle(for: PreferencesWindowController.self)) - // We override the feeds for betas - if preferences.allowBetas { - sparkleUpdater?.feedURL = URL(string: "https://raw.githubusercontent.com/JohnCoates/Aerial/master/beta-appcast.xml") + if PrefsUpdates.checkForUpdates { + // Starting the Sparkle update system + sparkleUpdater = SUUpdater.init(for: Bundle(for: PreferencesWindowController.self)) + + // We override the feeds for betas + if preferences.allowBetas { + sparkleUpdater?.feedURL = URL(string: "https://raw.githubusercontent.com/JohnCoates/Aerial/master/beta-appcast.xml") + } + + // On macOS 10.15, we simply disable the auto update check + if #available(OSX 10.15, *) { + sparkleUpdater!.automaticallyChecksForUpdates = false + + // And we start our own probe thing + let autoUpdates = AutoUpdates.sharedInstance + + // We make sure the required delay has elapsed + if autoUpdates.shouldCheckForUpdates(sparkleUpdater!) { + autoUpdates.doProbingCheck() + + _ = Timer.scheduledTimer(withTimeInterval: 5.0, repeats: false, block: { (_) in + self.checkForProbeResults(silent: true) + }) + } + + } else { + sparkleUpdater!.automaticallyChecksForUpdates = true + } + } else { + sparkleUpdater!.automaticallyChecksForUpdates = false } // Setup the updates for the Logs @@ -328,13 +349,8 @@ final class PreferencesWindowController: NSWindowController, NSOutlineViewDataSo // To workaround our High Sierra issues with textfields, we have separate panels // that replicate the features and are editable. They are hidden unless needed. if #available(OSX 10.14, *) { - //editMarginButton.isHidden = true - //editExtraMessageButton.isHidden = true enterCoordinatesButton.isHidden = true } else { - //marginHorizontalTextfield.isEnabled = false - //marginVerticalTextfield.isEnabled = false - // extraMessageTextField.isEnabled = false latitudeTextField.isEnabled = false longitudeTextField.isEnabled = false } @@ -347,6 +363,14 @@ final class PreferencesWindowController: NSWindowController, NSOutlineViewDataSo topLevelObjects: &topLevelObjects) { errorLog("Could not load nib for CustomVideos, please report") } + + // And our new, hopefully temporary, updater + topLevelObjects = NSArray() + if !bundle.loadNibNamed(NSNib.Name("UpdateReleaseWindow"), + owner: updateReleaseController, + topLevelObjects: &topLevelObjects) { + errorLog("Could not load nib for UpdateReleaseWindow, please report") + } } override func windowDidLoad() { diff --git a/Aerial/Source/Controllers/UpdateReleaseController.swift b/Aerial/Source/Controllers/UpdateReleaseController.swift new file mode 100644 index 00000000..99880efe --- /dev/null +++ b/Aerial/Source/Controllers/UpdateReleaseController.swift @@ -0,0 +1,70 @@ +// +// UpdateReleaseController.swift +// Aerial +// +// Created by Guillaume Louel on 17/02/2020. +// Copyright © 2020 Guillaume Louel. All rights reserved. +// + +import Foundation +import AppKit +import WebKit + +class UpdateReleaseController: NSWindowController { + var controller: PreferencesWindowController? + + @IBOutlet var updateWindow: NSWindow! + + @IBOutlet var noUpdateWindow: NSWindow! + + @IBOutlet var versionTextField: NSTextField! + @IBOutlet var releaseNotesWKWebView: WKWebView! + + @IBOutlet var helpPopover: NSPopover! + + // MARK: - Update available + func show(sender: NSButton, controller: PreferencesWindowController) { + self.controller = controller + + if !updateWindow.isVisible { + let autoUpdates = AutoUpdates.sharedInstance + + updateWindow.makeKeyAndOrderFront(nil) + versionTextField.stringValue = autoUpdates.getVersion() + + releaseNotesWKWebView.configuration.preferences.javaScriptEnabled = false + let html = "\(autoUpdates.getReleaseNotes())" + releaseNotesWKWebView.loadHTMLString(html, baseURL: nil) + } + } + + @IBAction func visitReleasePageClick(_ sender: NSButton) { + let workspace = NSWorkspace.shared + let autoUpdates = AutoUpdates.sharedInstance + + // We construct the URL this way... This is not great ! + let url = URL(string: "https://github.com/JohnCoates/Aerial/releases/tag/v\(autoUpdates.getVersion())")! + workspace.open(url) + + updateWindow.close() + } + + @IBAction func helpButtonClick(_ sender: NSButton) { + helpPopover.show(relativeTo: sender.preparedContentRect, of: sender, preferredEdge: .maxY) + } + + @IBAction func closeClick(_ sender: NSButton) { + updateWindow.close() + } + + // MARK: - No update available + func showNoUpdate() { + if !noUpdateWindow.isVisible { + noUpdateWindow.makeKeyAndOrderFront(nil) + } + } + + @IBAction func noUpdateCloseClick(_ sender: Any) { + noUpdateWindow.close() + } +} diff --git a/Aerial/Source/Models/AerialVideo.swift b/Aerial/Source/Models/AerialVideo.swift index 73ee469f..a5060cd1 100644 --- a/Aerial/Source/Models/AerialVideo.swift +++ b/Aerial/Source/Models/AerialVideo.swift @@ -46,18 +46,18 @@ private let spaceVideos = [ ] private let seaVideos = [ - "83C65C90-270C-4490-9C69-F51FE03D7F06", // Seals - "BA4ECA11-592F-4727-9221-D2A32A16EB28", // Palau Jellies + "83C65C90-270C-4490-9C69-F51FE03D7F06", // Seals (outdated) + "BA4ECA11-592F-4727-9221-D2A32A16EB28", // Palau Jellies * "F07CC61B-30FC-4614-BDAD-3240B61F6793", // Palau Coral "6143116D-03BB-485E-864E-A8CF58ACF6F1", // Kelp "2B30E324-E4FF-4CC1-BA45-A958C2D2B2EC", // Barracuda - "E580E5A5-0888-4BE8-A4CA-F74A18A643C3", // Palau Jellies - "EC3DC957-D4C2-4732-AACE-7D0C0F390EC8", // Palau Jellies + "E580E5A5-0888-4BE8-A4CA-F74A18A643C3", // Palau Jellies * + "EC3DC957-D4C2-4732-AACE-7D0C0F390EC8", // Palau Jellies * "581A4F1A-2B6D-468C-A1BE-6F473F06D10B", // Sea Stars "687D03A2-18A5-4181-8E85-38F3A13409B9", // Bumpheads "537A4DAB-83B0-4B66-BCD1-05E5DBB4A268", // Jacks - "C7AD3D0A-7EDF-412C-A237-B3C9D27381A1", // Alaskan Jellies - "C6DC4E54-1130-44F8-AF6F-A551D8E8A181", // Alaskan Jellies + "C7AD3D0A-7EDF-412C-A237-B3C9D27381A1", // Alaskan Jellies * + "C6DC4E54-1130-44F8-AF6F-A551D8E8A181", // Alaskan Jellies * "27A37B0F-738D-4644-A7A4-E33E7A6C1175", // California Dolphins "EB3F48E7-D30F-4079-858F-1A61331D5026", // California Kelp Forest "CE9B5D5B-B6E7-47C5-8C04-59BF182E98FB", // Costa Rica Dolphins @@ -65,8 +65,9 @@ private let seaVideos = [ "3716DD4B-01C0-4F5B-8DD6-DB771EC472FB", // Gray Reef Sharks "DD47D8E1-CB66-4C12-BFEA-2ADB0D8D1E2E", // Humpback Whale "82175C1F-153C-4EC8-AE37-2860EA828004", // Red Sea Coral - "149E7795-DBDA-4F5D-B39A-14712F841118", // Tahiti Waves - "8C31B06F-91A4-4F7C-93ED-56146D7F48B9", // Tahiti Waves, + "149E7795-DBDA-4F5D-B39A-14712F841118", // Tahiti Waves * + "8C31B06F-91A4-4F7C-93ED-56146D7F48B9", // Tahiti Waves * + "391BDF6E-3279-4CE1-9CA5-0F82811452D7", // Seals (new version) ] private let timeInformation = [ diff --git a/Aerial/Source/Models/AutoUpdates.swift b/Aerial/Source/Models/AutoUpdates.swift index bd4c3c49..7261ec84 100644 --- a/Aerial/Source/Models/AutoUpdates.swift +++ b/Aerial/Source/Models/AutoUpdates.swift @@ -15,6 +15,7 @@ class AutoUpdates: NSObject, SUUpdaterDelegate { var didProbeForUpdate = false private var updateAvailable = false private var updateVersion: String = "" + private var updateDescription: String = "" // This is what we use to look for updates while the screensaver is running // This code is not active in Catalina+ @@ -59,6 +60,37 @@ class AutoUpdates: NSObject, SUUpdaterDelegate { } } + func shouldCheckForUpdates(_ updater: SUUpdater) -> Bool { + let preferences = Preferences.sharedInstance + + // We manually ensure the correct amount of time passed since last check + var distance = -86400 // 1 day + + // On betas, we may have a shorter time check + if preferences.allowBetas { + if preferences.betaCheckFrequency == 0 { + distance = -3600 // 1 hour + } else if preferences.betaCheckFrequency == 1 { + distance = -43200 // 12 hours + } + } + + // If we never went into System Preferences, we may not have a lastUpdateCheckDate + if updater.lastUpdateCheckDate != nil { + print("/*/*/*/*/*/*/*/*/*") + print(updater.lastUpdateCheckDate.timeIntervalSinceNow.distance(to: Double(distance))) + + if updater.lastUpdateCheckDate.timeIntervalSinceNow.distance(to: Double(distance)) > 0 { + // Then force check/install udpates + debugLog("Update check time elapsed") + + return true + } + } + + return false + } + // Probing update check func doProbingCheck() { let preferences = Preferences.sharedInstance @@ -76,9 +108,11 @@ class AutoUpdates: NSObject, SUUpdaterDelegate { suu.feedURL = URL(string: "https://raw.githubusercontent.com/JohnCoates/Aerial/master/beta-appcast.xml") } - // Then force check/install udpates + // Then we probe ! debugLog("Checking for update (probe mode)") suu.checkForUpdateInformation() + + // Note: The result is asynchronously available later } } @@ -90,10 +124,6 @@ class AutoUpdates: NSObject, SUUpdaterDelegate { } } - func isAnUpdateAvailable() -> Bool { - return updateAvailable - } - func updaterDidNotFindUpdate(_ updater: SUUpdater) { debugLog("//////// No update is available !") didProbeForUpdate = true @@ -108,5 +138,20 @@ class AutoUpdates: NSObject, SUUpdaterDelegate { if let versionString = item.displayVersionString { self.updateVersion = versionString } + + // And the description + self.updateDescription = item.itemDescription + } + + func isAnUpdateAvailable() -> Bool { + return updateAvailable + } + + func getVersion() -> String { + return updateVersion + } + + func getReleaseNotes() -> String { + return updateDescription } } diff --git a/Aerial/Source/Models/Cache/PoiStringProvider.swift b/Aerial/Source/Models/Cache/PoiStringProvider.swift index 90ea84c6..068e7265 100644 --- a/Aerial/Source/Models/Cache/PoiStringProvider.swift +++ b/Aerial/Source/Models/Cache/PoiStringProvider.swift @@ -38,15 +38,33 @@ final class PoiStringProvider { } // MARK: - Bundle management + private func getBundleLanguages() -> [String] { + // Might want to improve that... + // This is a static list of what's supposed to be in the bundle + // swiftlint:disable:next line_length + return ["de", "he", "en_AU", "ar", "el", "ja", "en", "uk", "es_419", "zh_CN", "es", "pt_BR", "da", "it", "sk", "pt_PT", "ms", "sv", "cs", "ko", "no", "hu", "zh_HK", "tr", "pl", "zh_TW", "en_GB", "vi", "ru", "fr_CA", "fr", "fi", "id", "nl", "th", "pt", "ro", "hr", "hi", "ca"] + } + private func loadBundle() { // Idle string bundle let preferences = Preferences.sharedInstance - var bundlePath = VideoCache.appSupportDirectory! if preferences.ciOverrideLanguage == "" { - // We load the bundle and let system grab the closest available preferred language - bundlePath.append(contentsOf: "/TVIdleScreenStrings13.bundle") + debugLog("Preferred languages : \(Locale.preferredLanguages)") + + let bestMatchedLanguage = Bundle.preferredLocalizations(from: getBundleLanguages(), forPreferences: Locale.preferredLanguages).first + if let match = bestMatchedLanguage { + debugLog("Best matched language : \(match)") + bundlePath.append(contentsOf: "/TVIdleScreenStrings13.bundle/" + match + ".lproj/") + } else { + debugLog("No match, reverting to english") + // We load the bundle and let system grab the closest available preferred language + // This no longer works in Catalina and defaults back to english + // as legacyScreenSaver.appex, our new "mainbundle" is english only + bundlePath.append(contentsOf: "/TVIdleScreenStrings13.bundle") + } } else { + debugLog("Language overriden to \(preferences.ciOverrideLanguage)") // Or we load the overriden one bundlePath.append(contentsOf: "/TVIdleScreenStrings13.bundle/" + preferences.ciOverrideLanguage! + ".lproj/") } diff --git a/Aerial/Source/Models/Hardware/Battery.swift b/Aerial/Source/Models/Hardware/Battery.swift index 62e0bc9a..7d3b90ae 100644 --- a/Aerial/Source/Models/Hardware/Battery.swift +++ b/Aerial/Source/Models/Hardware/Battery.swift @@ -25,7 +25,14 @@ struct Battery { } static func isLow() -> Bool { - return getRemainingPercent() < 20 + let batteryLevel = getRemainingPercent() + + // If we have no battery, we'll get 0, so in that case we're NOT low + if batteryLevel == 0 { + return false + } + + return batteryLevel < 20 } static func getRemainingPercent() -> Int { diff --git a/Aerial/Source/Models/Prefs/PrefsInfo.swift b/Aerial/Source/Models/Prefs/PrefsInfo.swift index d3344792..8549f3f3 100644 --- a/Aerial/Source/Models/Prefs/PrefsInfo.swift +++ b/Aerial/Source/Models/Prefs/PrefsInfo.swift @@ -19,7 +19,7 @@ protocol CommonInfo { // Helper Enums for the common infos enum InfoCorner: Int, Codable { - case topLeft, topCenter, topRight, bottomLeft, bottomCenter, bottomRight, screenCenter, random + case topLeft, topCenter, topRight, bottomLeft, bottomCenter, bottomRight, screenCenter, random, absTopRight } enum InfoDisplays: Int, Codable { @@ -87,6 +87,7 @@ struct PrefsInfo { var fontSize: Double var corner: InfoCorner var displays: InfoDisplays + var betaReset: Bool // This is useless, just to reload default settings for users of 1.7.2 early betas } struct Countdown: CommonInfo, Codable { @@ -134,7 +135,7 @@ struct PrefsInfo { static var clock: Clock // Battery - @Storage(key: "LayerBattery", defaultValue: Battery(isEnabled: true, + @Storage(key: "LayerBattery", defaultValue: Battery(isEnabled: false, fontName: "Helvetica Neue Medium", fontSize: 20, corner: .topRight, @@ -147,7 +148,8 @@ struct PrefsInfo { fontName: "Helvetica Neue Medium", fontSize: 20, corner: .topRight, - displays: .allDisplays)) + displays: .allDisplays, + betaReset: true)) static var updates: Updates // Countdown @@ -189,9 +191,16 @@ struct PrefsInfo { @SimpleStorage(key: "marginY", defaultValue: 50) static var marginY: Int - // Shadow radius (common) - @SimpleStorage(key: "shadowRadius", defaultValue: 20) + // MARK: - Shadows + // Shadow radius + @SimpleStorage(key: "shadowRadius", defaultValue: 2) static var shadowRadius: Int + @SimpleStorage(key: "shadowOpacity", defaultValue: 1.0) + static var shadowOpacity: Float + @SimpleStorage(key: "shadowOffsetX", defaultValue: 0.0) + static var shadowOffsetX: CGFloat + @SimpleStorage(key: "shadowOffsetY", defaultValue: -3.0) + static var shadowOffsetY: CGFloat // MARK: - Helpers // Helper to quickly access a given struct (read-only as we return a copy of the struct) diff --git a/Aerial/Source/Models/Prefs/PrefsUpdates.swift b/Aerial/Source/Models/Prefs/PrefsUpdates.swift new file mode 100644 index 00000000..108325bd --- /dev/null +++ b/Aerial/Source/Models/Prefs/PrefsUpdates.swift @@ -0,0 +1,43 @@ +// +// PrefsUpdates.swift +// Aerial +// +// Created by Guillaume Louel on 16/02/2020. +// Copyright © 2020 Guillaume Louel. All rights reserved. +// + +import Foundation + +enum UpdateMode: Int { + case notify, install +} + +struct PrefsUpdates { + // Update Mode when the screensaver runs (notify or install) + @SimpleStorage(key: "checkForUpdates", defaultValue: true) + static var checkForUpdates: Bool + + // Update Mode when the screensaver runs (notify or install) + @SimpleStorage(key: "sparkleUpdateMode", defaultValue: getDefaultUpdateMode()) + static var intSparkleUpdateMode: Int + + // We wrap in a separate value, as we can't store an enum as a Codable in + // macOS < 10.15 + static var sparkleUpdateMode: UpdateMode { + get { + return UpdateMode(rawValue: intSparkleUpdateMode)! + } + set(value) { + intSparkleUpdateMode = value.rawValue + } + } + + // On Catalina, we notify by default, on previous OSes we install by default + static func getDefaultUpdateMode() -> Int { + if #available(OSX 10.15, *) { + return UpdateMode.notify.rawValue + } else { + return UpdateMode.install.rawValue + } + } +} diff --git a/Aerial/Source/Views/AerialView.swift b/Aerial/Source/Views/AerialView.swift index 8898a71c..8374f37c 100644 --- a/Aerial/Source/Views/AerialView.swift +++ b/Aerial/Source/Views/AerialView.swift @@ -184,21 +184,26 @@ final class AerialView: ScreenSaverView, CAAnimationDelegate { // Run Sparkle updater if enabled if !isPreview { if preferences.updateWhileSaverMode { - au.doForcedUpdate() + if PrefsUpdates.sparkleUpdateMode == .notify { + // Run the probing check + au.doProbingCheck() + } else { + // Run the forced update + au.doForcedUpdate() + } } } - // Run the probing check - au.doProbingCheck() - // Check early if we need to enable power saver mode, // black screen with minimal brightness - // swiftlint:disable:next line_length - if (PrefsVideos.onBatteryMode == .alwaysDisabled && Battery.isUnplugged() && !isPreview) || (PrefsVideos.onBatteryMode == .disableOnLow && Battery.isLow()) { - debugLog("Engaging power saving mode") - isDisabled = true - Brightness.set(level: 0.0) - return + if !isPreview { + if (PrefsVideos.onBatteryMode == .alwaysDisabled && Battery.isUnplugged()) + || (PrefsVideos.onBatteryMode == .disableOnLow && Battery.isLow()) { + debugLog("Engaging power saving mode") + isDisabled = true + Brightness.set(level: 0.0) + return + } } // We may need to set timers to progressively dim the screen diff --git a/Aerial/Source/Views/Layers/AnimationLayer.swift b/Aerial/Source/Views/Layers/AnimationLayer.swift index 4e1f4b69..fd961e1e 100644 --- a/Aerial/Source/Views/Layers/AnimationLayer.swift +++ b/Aerial/Source/Views/Layers/AnimationLayer.swift @@ -48,7 +48,10 @@ class AnimationLayer: CATextLayer { // Starts hidden, with a bit of shadow for text separation self.opacity = 0 self.shadowRadius = CGFloat(PrefsInfo.shadowRadius) - self.shadowOpacity = 1.0 + self.shadowOpacity = PrefsInfo.shadowOpacity + self.shadowOffset = CGSize(width: PrefsInfo.shadowOffsetX, + height: PrefsInfo.shadowOffsetY) + self.shadowColor = CGColor.black } @@ -88,6 +91,7 @@ class AnimationLayer: CATextLayer { } // Move to a corner, this may need to force the redraw of a whole corner + // swiftlint:disable:next cyclomatic_complexity func move(toCorner: InfoCorner, fullRedraw: Bool) { if let currCorner = currentCorner, !fullRedraw { // Are we on the same corner ? @@ -133,13 +137,11 @@ class AnimationLayer: CATextLayer { newPos = CGPoint(x: baseLayer.bounds.width-mx, y: baseLayer.bounds.height-my) alignmentMode = .right - case .screenCenter: anchorPoint = CGPoint(x: 0.5, y: 0) newPos = CGPoint(x: baseLayer.bounds.width/2, y: baseLayer.bounds.height/2 - my + 20) alignmentMode = .center - case .bottomLeft: anchorPoint = CGPoint(x: 0, y: 0) newPos = CGPoint(x: mx, y: my) @@ -148,6 +150,11 @@ class AnimationLayer: CATextLayer { anchorPoint = CGPoint(x: 0.5, y: 0) newPos = CGPoint(x: baseLayer.bounds.width/2, y: my) alignmentMode = .center + case .absTopRight: + anchorPoint = CGPoint(x: 1, y: 1) + newPos = CGPoint(x: baseLayer.bounds.width-mx, + y: baseLayer.bounds.height-10) + alignmentMode = .right default: // bottomRight anchorPoint = CGPoint(x: 1, y: 0) newPos = CGPoint(x: baseLayer.bounds.width-mx, y: my) diff --git a/Aerial/Source/Views/Layers/LayerManager.swift b/Aerial/Source/Views/Layers/LayerManager.swift index f5fa217a..c92661b2 100644 --- a/Aerial/Source/Views/Layers/LayerManager.swift +++ b/Aerial/Source/Views/Layers/LayerManager.swift @@ -44,6 +44,16 @@ class LayerManager { addLayerForType(layerType, layer: layer) } + // Then we may need to add our special update layer + // It doesn't show in the main UI, it's linked to + // options in the Updates tab + let preferences = Preferences.sharedInstance + + if preferences.updateWhileSaverMode && PrefsUpdates.sparkleUpdateMode == .notify { + print(">>> add update layer") + addLayerForType(.updates, layer: layer) + } + // And reversed bottomRow for layerType in bottomRow.reversed() { addLayerForType(layerType, layer: layer) diff --git a/Aerial/Source/Views/Layers/LayerOffsets.swift b/Aerial/Source/Views/Layers/LayerOffsets.swift index bd8ae475..e4e5a5e2 100644 --- a/Aerial/Source/Views/Layers/LayerOffsets.swift +++ b/Aerial/Source/Views/Layers/LayerOffsets.swift @@ -19,5 +19,6 @@ class LayerOffsets { corner[.bottomCenter] = 0 corner[.bottomRight] = 0 corner[.screenCenter] = 0 + corner[.absTopRight] = 0 } } diff --git a/Aerial/Source/Views/Layers/UpdatesLayer.swift b/Aerial/Source/Views/Layers/UpdatesLayer.swift index 612bb8bb..64cd8fff 100644 --- a/Aerial/Source/Views/Layers/UpdatesLayer.swift +++ b/Aerial/Source/Views/Layers/UpdatesLayer.swift @@ -37,7 +37,7 @@ class UpdatesLayer: AnimationLayer { // Set our layer's font & corner now (self.font, self.fontSize) = getFont(name: config.fontName, size: config.fontSize) - self.corner = config.corner + self.corner = .absTopRight } override func setupForVideo(video: AerialVideo, player: AVPlayer) { @@ -65,6 +65,5 @@ class UpdatesLayer: AnimationLayer { }) } } - } } diff --git a/Aerial/Source/Views/PrefPanel/InfoCommonView.swift b/Aerial/Source/Views/PrefPanel/InfoCommonView.swift index 2af91964..88a03490 100644 --- a/Aerial/Source/Views/PrefPanel/InfoCommonView.swift +++ b/Aerial/Source/Views/PrefPanel/InfoCommonView.swift @@ -84,6 +84,8 @@ class InfoCommonView: NSView { posScreenCenter.state = .on case .random: posRandom.state = .on + case .absTopRight: + posTopRight.state = .on } } diff --git a/Aerial/Source/Views/PrefPanel/InfoMessageView.swift b/Aerial/Source/Views/PrefPanel/InfoMessageView.swift index 37848e2c..f052ae36 100644 --- a/Aerial/Source/Views/PrefPanel/InfoMessageView.swift +++ b/Aerial/Source/Views/PrefPanel/InfoMessageView.swift @@ -12,16 +12,41 @@ class InfoMessageView: NSView { @IBOutlet var messageTextField: NSTextField! @IBOutlet var messageExtraButton: NSButton! + @IBOutlet var editExtraMessagePanel: NSPanel! + @IBOutlet var secondaryExtraMessageTextField: NSTextField! + func setStates() { messageTextField.stringValue = PrefsInfo.message.message + secondaryExtraMessageTextField.stringValue = PrefsInfo.message.message + + // Workaround for textfield bug in High sierra and earlier + if #available(OSX 10.14, *) { + messageExtraButton.isHidden = true + } else { + messageTextField.isEnabled = false + } } @IBAction func messageChange(_ sender: NSTextField) { + if sender == secondaryExtraMessageTextField { + messageTextField.stringValue = sender.stringValue + } PrefsInfo.message.message = sender.stringValue } - @IBAction func messageExtraClick(_ sender: Any) { - // TODO + // MARK: - High Sierra Workaround for TextFields + @IBAction func openExtraMessagePanelClick(_ sender: Any) { + if editExtraMessagePanel.isVisible { + editExtraMessagePanel.close() + } else { + editExtraMessagePanel.makeKeyAndOrderFront(sender) + } } + @IBAction func closeExtraMessagePanelClick(_ sender: Any) { + // On close we apply what's in the textfield + messageTextField.stringValue = secondaryExtraMessageTextField.stringValue + PrefsInfo.message.message = secondaryExtraMessageTextField.stringValue + editExtraMessagePanel.close() + } } diff --git a/Aerial/Source/Views/PrefPanel/InfoSettingsView.swift b/Aerial/Source/Views/PrefPanel/InfoSettingsView.swift index 6e3b31af..65f5471f 100644 --- a/Aerial/Source/Views/PrefPanel/InfoSettingsView.swift +++ b/Aerial/Source/Views/PrefPanel/InfoSettingsView.swift @@ -14,10 +14,23 @@ class InfoSettingsView: NSView { @IBOutlet var changeCornerMargins: NSButton! @IBOutlet var marginHorizontalTextfield: NSTextField! @IBOutlet var marginVerticalTextfield: NSTextField! - @IBOutlet var editMarginButton: NSButton! + // Shadows @IBOutlet var shadowRadiusTextField: NSTextField! @IBOutlet var shadowRadiusFormatter: NumberFormatter! + @IBOutlet var shadowOpacitySlider: NSSlider! + @IBOutlet var shadowOffsetXTextfield: NSTextField! + @IBOutlet var shadowOffsetYTextfield: NSTextField! + + @IBOutlet var shadowOffsetXFormatter: NumberFormatter! + @IBOutlet var shadowOffsetYFormatter: NumberFormatter! + + // High Sierra workarounds + @IBOutlet var editMarginsPanel: NSPanel! + + @IBOutlet var editMarginButton: NSButton! + @IBOutlet var secondaryMarginHorizontalTextfield: NSTextField! + @IBOutlet var secondaryMarginVerticalTextfield: NSTextField! func setStates() { //messageTextField.stringValue = PrefsInfo.message.message @@ -31,11 +44,28 @@ class InfoSettingsView: NSView { marginHorizontalTextfield.stringValue = String(PrefsInfo.marginX) marginVerticalTextfield.stringValue = String(PrefsInfo.marginY) + secondaryMarginHorizontalTextfield.stringValue = String(PrefsInfo.marginX) + secondaryMarginVerticalTextfield.stringValue = String(PrefsInfo.marginY) fadeInOutTextModePopup.selectItem(at: PrefsInfo.fadeModeText.rawValue) shadowRadiusFormatter.allowsFloats = false shadowRadiusTextField.stringValue = String(PrefsInfo.shadowRadius) + +// shadowOffsetXFormatter.allowsFloats = true +// shadowOffsetYFormatter.allowsFloats = true + + shadowOpacitySlider.doubleValue = Double(PrefsInfo.shadowOpacity * 100) + shadowOffsetXTextfield.doubleValue = Double(PrefsInfo.shadowOffsetX) + shadowOffsetYTextfield.doubleValue = Double(PrefsInfo.shadowOffsetY) + + // Workaround for textfield bug in High sierra and earlier + if #available(OSX 10.14, *) { + editMarginButton.isHidden = true + } else { + marginHorizontalTextfield.isEnabled = false + marginVerticalTextfield.isEnabled = false + } } // MARK: - Shadows @@ -43,11 +73,21 @@ class InfoSettingsView: NSView { PrefsInfo.shadowRadius = Int(sender.intValue) } + @IBAction func shadowOpacityChange(_ sender: NSSlider) { + PrefsInfo.shadowOpacity = Float(sender.intValue)/100 + } + + @IBAction func shadowOffsetXChange(_ sender: NSTextField) { + PrefsInfo.shadowOffsetX = CGFloat(sender.doubleValue) + } + + @IBAction func shadowOffsetYChange(_ sender: NSTextField) { + PrefsInfo.shadowOffsetY = CGFloat(sender.doubleValue) + } // MARK: - Fades @IBAction func fadeInOutTextModePopupChange(_ sender: NSPopUpButton) { debugLog("UI fadeInOutTextMode: \(sender.indexOfSelectedItem)") -// preferences.fadeModeText = sender.indexOfSelectedItem -// preferences.synchronize() + PrefsInfo.fadeModeText = FadeMode(rawValue: sender.indexOfSelectedItem)! } @@ -60,24 +100,44 @@ class InfoSettingsView: NSView { marginHorizontalTextfield.isEnabled = onState marginVerticalTextfield.isEnabled = onState PrefsInfo.overrideMargins = onState -// preferences.overrideMargins = onState } @IBAction func marginXChange(_ sender: NSTextField) { PrefsInfo.marginX = Int(sender.stringValue) ?? 50 -// if sender == secondaryMarginHorizontalTextfield { -// marginHorizontalTextfield.stringValue = sender.stringValue -// } + if sender == secondaryMarginHorizontalTextfield { + marginHorizontalTextfield.stringValue = sender.stringValue + } debugLog("UI marginXChange: \(sender.stringValue)") } @IBAction func marginYChange(_ sender: NSTextField) { PrefsInfo.marginY = Int(sender.stringValue) ?? 50 -// if sender == secondaryMarginVerticalTextfield { -// marginVerticalTextfield.stringValue = sender.stringValue -// } + if sender == secondaryMarginVerticalTextfield { + marginVerticalTextfield.stringValue = sender.stringValue + } debugLog("UI marginYChange: \(sender.stringValue)") } + + // MARK: - High Sierra Workaround for TextFields + @IBAction func openExtraMarginPanelClick(_ sender: Any) { + if editMarginsPanel.isVisible { + editMarginsPanel.close() + } else { + editMarginsPanel.makeKeyAndOrderFront(sender) + } + } + + @IBAction func closeExtraMarginPanelClick(_ sender: Any) { + // On close we apply what's in the textfields + marginHorizontalTextfield.stringValue = secondaryMarginHorizontalTextfield.stringValue + PrefsInfo.marginX = Int(secondaryMarginHorizontalTextfield.stringValue) ?? 50 + + marginVerticalTextfield.stringValue = secondaryMarginVerticalTextfield.stringValue + PrefsInfo.marginY = Int(secondaryMarginVerticalTextfield.stringValue) ?? 50 + + editMarginsPanel.close() + } + } diff --git a/Documentation/Contribute.md b/Documentation/Contribute.md index 774500dd..e7dd3e39 100644 --- a/Documentation/Contribute.md +++ b/Documentation/Contribute.md @@ -8,11 +8,22 @@ Feel free to directly submit a PR for small changes or quick bug fixes, so we ca If you want to implement something more substantial, it might be a good idea to open an issue first to discuss what you want to do, so we can coordinate efforts and help you get around the existing codebase and it's various pitfalls. +# Warning if you setup your repo prior to 1.7.2 + +Starting with version 1.7.2, we've removed the cocoapods dependency to Sparkle, and replaced it with a git submodule reference in /Extern). You can either pull anew, or if you want to fix your repo you can do : + +``` +pod deintegrate +``` + +From your main repo folder. + + # How to compile Aerial - Grab the repository -- In terminal in the root of the repository, run `pod update` to bring Sparkle -- Open the `Aerial.xcworkspace` in Xcode (you need at least Xcode 10.2, or Xcode 11 beta). You must open the `xcworkspace`, not the `xcodeproj`. +- In terminal in the root of the repository, run `git submodule update --init --recursive` to bring Sparkle and it's dependencies +- Open the `Aerial.xcodeproj` in Xcode - Top left of the screen, pick the "AerialApp" scheme : ![Capture d’écran 2019-06-27 à 12 56 42](https://user-images.githubusercontent.com/37544189/60261086-569e8580-98db-11e9-8fd2-e579786f628d.jpg) - Build and run. diff --git a/Resources/Community/en.json b/Resources/Community/en.json index ef9fa411..a7f2d80d 100644 --- a/Resources/Community/en.json +++ b/Resources/Community/en.json @@ -346,5 +346,83 @@ }, "E556BBC5-D0A0-4DB1-AC77-BC76E4A526F4": { "name": "Sahara and Italy" + }, + "64D11DAB-3B57-4F14-AD2F-E59A9282FA44": { + "name": "Atlantic Ocean to Spain and France" + }, + "81337355-E156-4242-AAF4-711768D30A54": { + "name": "Australia" + }, + "1088217C-1410-4CF7-BDE9-8F573A4DBCD9": { + "name": "Caribbean to Central America" + }, + "3C4678E4-4D3D-4A40-8817-77752AEA62EB": { + "name": "Nile Delta" + }, + "87060EC2-D006-4102-98CC-3005C68BB343": { + "name": "South Africa to North Asia" + }, + "F07CC61B-30FC-4614-BDAD-3240B61F6793": { + "name": "Palau Coral" + }, + "6143116D-03BB-485E-864E-A8CF58ACF6F1": { + "name": "South African Kelp" + }, + "2B30E324-E4FF-4CC1-BA45-A958C2D2B2EC": { + "name": "Barracuda" + }, + "581A4F1A-2B6D-468C-A1BE-6F473F06D10B": { + "name": "Sea Stars" + }, + "687D03A2-18A5-4181-8E85-38F3A13409B9": { + "name": "Bumpheads" + }, + "537A4DAB-83B0-4B66-BCD1-05E5DBB4A268": { + "name": "Jacks" + }, + "27A37B0F-738D-4644-A7A4-E33E7A6C1175": { + "name": "California Dolphins" + }, + "EB3F48E7-D30F-4079-858F-1A61331D5026": { + "name": "California Kelp Forest" + }, + "CE9B5D5B-B6E7-47C5-8C04-59BF182E98FB": { + "name": "Costa Rica Dolphins" + }, + "58C75C62-3290-47B8-849C-56A583173570": { + "name": "Cownose Rays" + }, + "3716DD4B-01C0-4F5B-8DD6-DB771EC472FB": { + "name": "Gray Reef Sharks" + }, + "DD47D8E1-CB66-4C12-BFEA-2ADB0D8D1E2E": { + "name": "Humpback Whale" + }, + "82175C1F-153C-4EC8-AE37-2860EA828004": { + "name": "Red Sea Coral" + }, + "391BDF6E-3279-4CE1-9CA5-0F82811452D7": { + "name": "Seals" + }, + "BA4ECA11-592F-4727-9221-D2A32A16EB28": { + "name": "Palau Jellies 1" + }, + "E580E5A5-0888-4BE8-A4CA-F74A18A643C3": { + "name": "Palau Jellies 2" + }, + "EC3DC957-D4C2-4732-AACE-7D0C0F390EC8": { + "name": "Palau Jellies 3" + }, + "C7AD3D0A-7EDF-412C-A237-B3C9D27381A1": { + "name": "Alaskan Jellies 1" + }, + "C6DC4E54-1130-44F8-AF6F-A551D8E8A181": { + "name": "Alaskan Jellies 2" + }, + "149E7795-DBDA-4F5D-B39A-14712F841118": { + "name": "Tahiti Waves 1" + }, + "8C31B06F-91A4-4F7C-93ED-56146D7F48B9": { + "name": "Tahiti Waves 2" } } \ No newline at end of file diff --git a/Resources/Community/fr.json b/Resources/Community/fr.json index 5bca6c77..a794c7a9 100644 --- a/Resources/Community/fr.json +++ b/Resources/Community/fr.json @@ -346,5 +346,83 @@ }, "E556BBC5-D0A0-4DB1-AC77-BC76E4A526F4": { "name": "Sahara et Italie" + }, + "64D11DAB-3B57-4F14-AD2F-E59A9282FA44": { + "name": "Océan Atlantique vers l'Espagne et la France" + }, + "81337355-E156-4242-AAF4-711768D30A54": { + "name": "Australie" + }, + "1088217C-1410-4CF7-BDE9-8F573A4DBCD9": { + "name": "Caraïbes et Amérique Centrale" + }, + "3C4678E4-4D3D-4A40-8817-77752AEA62EB": { + "name": "Delta du Nil" + }, + "87060EC2-D006-4102-98CC-3005C68BB343": { + "name": "Afrique du Sud vers Asie du Nord" + }, + "F07CC61B-30FC-4614-BDAD-3240B61F6793": { + "name": "Corail de Palaos" + }, + "6143116D-03BB-485E-864E-A8CF58ACF6F1": { + "name": "Macroalgues en Afrique du Sud" + }, + "2B30E324-E4FF-4CC1-BA45-A958C2D2B2EC": { + "name": "Barracuda" + }, + "581A4F1A-2B6D-468C-A1BE-6F473F06D10B": { + "name": "Étoiles de mer" + }, + "687D03A2-18A5-4181-8E85-38F3A13409B9": { + "name": "Poissons-perroquets à bosse" + }, + "537A4DAB-83B0-4B66-BCD1-05E5DBB4A268": { + "name": "Carangues à gros yeux" + }, + "27A37B0F-738D-4644-A7A4-E33E7A6C1175": { + "name": "Dauphins en Californie" + }, + "EB3F48E7-D30F-4079-858F-1A61331D5026": { + "name": "Forêt de macroalgues en Californie" + }, + "CE9B5D5B-B6E7-47C5-8C04-59BF182E98FB": { + "name": "Dauphins au Costa Rica" + }, + "58C75C62-3290-47B8-849C-56A583173570": { + "name": "Mourines du Pacifique" + }, + "3716DD4B-01C0-4F5B-8DD6-DB771EC472FB": { + "name": "Requins gris de récif" + }, + "DD47D8E1-CB66-4C12-BFEA-2ADB0D8D1E2E": { + "name": "Baleine à bosse" + }, + "82175C1F-153C-4EC8-AE37-2860EA828004": { + "name": "Corail de la mer Rouge" + }, + "391BDF6E-3279-4CE1-9CA5-0F82811452D7": { + "name": "Otaries à fourrure" + }, + "BA4ECA11-592F-4727-9221-D2A32A16EB28": { + "name": "Méduses dorées de Palaos 1" + }, + "E580E5A5-0888-4BE8-A4CA-F74A18A643C3": { + "name": "Méduses dorées de Palaos 2" + }, + "EC3DC957-D4C2-4732-AACE-7D0C0F390EC8": { + "name": "Méduses dorées de Palaos 3" + }, + "C7AD3D0A-7EDF-412C-A237-B3C9D27381A1": { + "name": "Méduses lune de l'Alaska 1" + }, + "C6DC4E54-1130-44F8-AF6F-A551D8E8A181": { + "name": "Méduses lune de l'Alaska 2" + }, + "149E7795-DBDA-4F5D-B39A-14712F841118": { + "name": "Vagues à Tahiti 1" + }, + "8C31B06F-91A4-4F7C-93ED-56146D7F48B9": { + "name": "Vagues à Tahiti 2" } } \ No newline at end of file diff --git a/Resources/PreferencesWindow.xib b/Resources/PreferencesWindow.xib index 752f2894..02833bff 100644 --- a/Resources/PreferencesWindow.xib +++ b/Resources/PreferencesWindow.xib @@ -25,13 +25,10 @@ - - - @@ -49,8 +46,6 @@ - - @@ -58,7 +53,6 @@ - @@ -76,7 +70,6 @@ - @@ -88,8 +81,6 @@ - - @@ -123,12 +114,11 @@ - - - + + @@ -144,7 +134,6 @@ - @@ -465,7 +454,7 @@ is disabled - + @@ -487,7 +476,7 @@ is disabled - + @@ -660,24 +649,15 @@ is disabled - - + + - + - - - - - - - - - - + @@ -690,7 +670,7 @@ is disabled - + @@ -699,7 +679,7 @@ is disabled - + @@ -708,7 +688,7 @@ is disabled - + @@ -721,7 +701,7 @@ is disabled - + @@ -730,7 +710,7 @@ is disabled - + @@ -785,7 +765,7 @@ is disabled - + @@ -889,10 +869,10 @@ is disabled - + - + @@ -913,7 +893,7 @@ is disabled - + @@ -958,11 +938,11 @@ is disabled - + - + @@ -993,7 +973,7 @@ is disabled - + @@ -1020,7 +1000,7 @@ is disabled - + @@ -1029,7 +1009,7 @@ is disabled - + @@ -1045,7 +1025,7 @@ is disabled - + @@ -1054,22 +1034,22 @@ is disabled - + - + - + - + @@ -1078,7 +1058,7 @@ is disabled - + @@ -1102,7 +1082,7 @@ is disabled - + @@ -1111,12 +1091,12 @@ is disabled - + - + @@ -1140,7 +1120,7 @@ is disabled - + @@ -1153,7 +1133,7 @@ is disabled - + @@ -1186,7 +1166,7 @@ Shift, but macOS 10.12.4 or above and a compatible Mac are required) - + @@ -1202,7 +1182,7 @@ Shift, but macOS 10.12.4 or above and a compatible Mac are required) - + @@ -1420,7 +1400,7 @@ Shift, but macOS 10.12.4 or above and a compatible Mac are required) - + - + - + @@ -1459,7 +1439,7 @@ Shift, but macOS 10.12.4 or above and a compatible Mac are required) - + @@ -1541,7 +1521,7 @@ Shift, but macOS 10.12.4 or above and a compatible Mac are required) - - + @@ -1738,11 +1698,39 @@ Shift, but macOS 10.12.4 or above and a compatible Mac are required) - - + + + + + + + + + + + + + + + + + + + + - - + + @@ -1946,7 +1934,7 @@ Gw - + @@ -2285,10 +2273,10 @@ You can still decide to disable Aerial when running on battery, or if your batte - + - + @@ -2303,7 +2291,7 @@ You can still decide to disable Aerial when running on battery, or if your batte - + @@ -2318,7 +2306,7 @@ You can still decide to disable Aerial when running on battery, or if your batte - + @@ -2347,12 +2335,30 @@ You can still decide to disable Aerial when running on battery, or if your batte - + + + + + + + + + + + + + + + + + + + - + @@ -2364,7 +2370,7 @@ You can still decide to disable Aerial when running on battery, or if your batte - + @@ -2372,7 +2378,7 @@ You can still decide to disable Aerial when running on battery, or if your batte - + @@ -2392,12 +2398,12 @@ You can still decide to disable Aerial when running on battery, or if your batte - + - + @@ -2686,27 +2692,27 @@ Gw - + - + Automatic Updates -If you uncheck this box, Aerial will only check for updates when you are running this control panel. +In macOS Catalina, screen savers are no longer able to update themselves. -When checked, Aerial will also look when appropriate for a new version while the screen saver is running. As a side effect, when a new update is available, it will wake up from the screen saver to install the new version (your Mac will eventually go to sleep afterwards). +By default, Aerial will now notify you when a new version is available, but won't auto update. You can then launch this control panel, use the Check Now button to get a link to the latest release. -Unless you want to manually manage your updates, we highly recommand you leave this box checked! +On macOS version prior to Catalina, you can also choose to silently update Aerial. As a side effect, when a new update is available, it will wake up from the screen saver to install the new version (your Mac will eventually go to sleep afterwards). - + @@ -3076,9 +3082,7 @@ After changing the folder, please close System Preferences for this to be taken - - @@ -3109,18 +3113,20 @@ After changing the folder, please close System Preferences for this to be taken + + @@ -3180,9 +3186,6 @@ After changing the folder, please close System Preferences for this to be taken - - - - + @@ -3235,7 +3237,7 @@ After changing the folder, please close System Preferences for this to be taken - + @@ -3261,7 +3263,7 @@ After changing the folder, please close System Preferences for this to be taken - + @@ -3276,7 +3278,7 @@ After changing the folder, please close System Preferences for this to be taken - + @@ -3285,7 +3287,7 @@ After changing the folder, please close System Preferences for this to be taken - + @@ -3293,17 +3295,61 @@ After changing the folder, please close System Preferences for this to be taken + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + @@ -3318,33 +3364,129 @@ After changing the folder, please close System Preferences for this to be taken + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + @@ -3355,7 +3497,6 @@ After changing the folder, please close System Preferences for this to be taken - diff --git a/Resources/UpdateReleaseWindow.xib b/Resources/UpdateReleaseWindow.xib new file mode 100644 index 00000000..800c5184 --- /dev/null +++ b/Resources/UpdateReleaseWindow.xib @@ -0,0 +1,183 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Starting with macOS Catalina, Apple has changed how screen savers can operate. Screen savers are now ran in a sandbox which no longer allows screen savers to auto update themselves, because of security restrictions. + +As a compromise, and while we wait for a possible new API from Apple that would solve this issue, Aerial will only check for updates on Catalina, and direct you to the website to download and install new versions. + +We apologize for the inconvenience. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +