diff --git a/.github/workflows/core_data_tests.yml b/.github/workflows/core_data_tests.yml index a27ab670d..59d87b3ff 100644 --- a/.github/workflows/core_data_tests.yml +++ b/.github/workflows/core_data_tests.yml @@ -42,6 +42,7 @@ jobs: run: | sh ./bootstrap.sh pod install + bundle update fastlane - name: Run code validation uses: actions/checkout@v1 with: diff --git a/7.0.0 b/7.0.0 new file mode 100644 index 000000000..e69de29bb diff --git a/CoreData_Models/CommentModel+CoreDataProperties.swift b/CoreData_Models/CommentModel+CoreDataProperties.swift index 4a7f6e717..bb59d53aa 100644 --- a/CoreData_Models/CommentModel+CoreDataProperties.swift +++ b/CoreData_Models/CommentModel+CoreDataProperties.swift @@ -18,6 +18,7 @@ extension CommentModel { @NSManaged public var approvedBy: String? @NSManaged public var author: String + @NSManaged public var authorProfileImage: String? @NSManaged public var awardsJSON: String? @NSManaged public var controversality: Int64 @NSManaged public var created: Date diff --git a/CoreData_Models/Reddit.xcdatamodeld/Reddit.xcdatamodel/contents b/CoreData_Models/Reddit.xcdatamodeld/Reddit.xcdatamodel/contents index 9dc813230..d00fb1330 100644 --- a/CoreData_Models/Reddit.xcdatamodeld/Reddit.xcdatamodel/contents +++ b/CoreData_Models/Reddit.xcdatamodeld/Reddit.xcdatamodel/contents @@ -1,8 +1,9 @@ - + + @@ -150,7 +151,7 @@ - + diff --git a/Podfile b/Podfile index d7de4440a..cd5180336 100644 --- a/Podfile +++ b/Podfile @@ -19,7 +19,6 @@ target 'Slide for Reddit' do pod 'SwiftLinkPreview', '~> 3.0.1' pod 'DTCoreText', :git => 'https://github.com/Cocoanetics/DTCoreText' pod 'RLBAlertsPickers', :git => 'https://github.com/ccrama/Alerts-Pickers' - pod 'Alamofire', '~> 4.3' pod 'SwiftyJSON', :git => 'https://github.com/ccrama/SwiftyJSON.git', :branch => 'hotfix-xcode12' pod "YoutubePlayer-in-WKWebView", "~> 0.3.0" pod 'TGPControls' @@ -35,6 +34,15 @@ target 'Slide for Reddit' do end post_install do |installer| + installer.pods_project.targets.each do |target| + # Fix bundle targets' 'Signing Certificate' to 'Sign to Run Locally' + if target.respond_to?(:product_type) and target.product_type == "com.apple.product-type.bundle" + target.build_configurations.each do |config| + config.build_settings['CODE_SIGN_IDENTITY[sdk=macosx*]'] = '-' + end + end + end + installer.pods_project.targets.each do |target| target.build_configurations.each do |config| config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '11' diff --git a/Podfile.lock b/Podfile.lock index b69f9fba7..be601ea76 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -1,5 +1,4 @@ PODS: - - Alamofire (4.9.1) - DTCoreText (1.6.26): - DTCoreText/Core (= 1.6.26) - DTFoundation/Core (~> 1.7.5) @@ -19,24 +18,24 @@ PODS: - DTFoundation/Core - HTMLSpecialCharacters (1.3.6) - LicensesViewController (0.7.0) - - MaterialComponents/ActivityIndicator (119.5.0): + - MaterialComponents/ActivityIndicator (124.1.1): - MaterialComponents/Palettes - MaterialComponents/private/Application - MDFInternationalization - - MotionAnimator (~> 2.0) - - MaterialComponents/Palettes (119.5.0) - - MaterialComponents/private/Application (119.5.0) - - MaterialComponents/private/Math (119.5.0) - - MaterialComponents/ProgressView (119.5.0): + - MotionAnimator (~> 4.0) + - MaterialComponents/Palettes (124.1.1) + - MaterialComponents/private/Application (124.1.1) + - MaterialComponents/private/Math (124.1.1) + - MaterialComponents/ProgressView (124.1.1): - MaterialComponents/Palettes - MaterialComponents/private/Math - MDFInternationalization - MDFInternationalization (2.0.0) - MiniKeychain (1.0.8) - MKColorPicker (1.2) - - MotionAnimator (2.8.1): - - MotionInterchange (~> 1.6) - - MotionInterchange (1.6.0) + - MotionAnimator (4.0.1): + - MotionInterchange (~> 3.0) + - MotionInterchange (3.0.0) - MTColorDistance (0.0.3) - OpalImagePicker (3.0.0) - QuickLayout (3.0.0) @@ -49,13 +48,12 @@ PODS: - SwiftEntryKit (1.2.1): - QuickLayout (= 3.0.0) - SwiftLinkPreview (3.0.1) - - SwiftLint (0.42.0) + - SwiftLint (0.43.1) - SwiftyJSON (5.0.0) - TGPControls (5.1.0) - YoutubePlayer-in-WKWebView (0.3.5) DEPENDENCIES: - - Alamofire (~> 4.3) - DTCoreText (from `https://github.com/Cocoanetics/DTCoreText`) - LicensesViewController (~> 0.7.0) - MaterialComponents/ActivityIndicator @@ -76,7 +74,6 @@ DEPENDENCIES: SPEC REPOS: trunk: - - Alamofire - DTFoundation - HTMLSpecialCharacters - LicensesViewController @@ -113,13 +110,13 @@ EXTERNAL SOURCES: CHECKOUT OPTIONS: DTCoreText: - :commit: 24823e50ec7496b80bd9dd346459136511cfa9d5 + :commit: c4cb9c9aa8bf245bcbf270335f02ac440a3f72a3 :git: https://github.com/Cocoanetics/DTCoreText MKColorPicker: :commit: e76cd225ff60f12f8ec0052e39e5e307a32c0762 :git: https://github.com/ccrama/MKColorPicker reddift: - :commit: 79d54d0d00a3b888f766d413ef4a191c4e4c99f7 + :commit: bb77a789b94731d0291f1a673f343cbcab13e02c :git: https://github.com/ccrama/reddift RLBAlertsPickers: :commit: a22003f93a803c2e14b193f636669c21358fb1d7 @@ -135,17 +132,16 @@ CHECKOUT OPTIONS: :git: https://github.com/ccrama/SwiftyJSON.git SPEC CHECKSUMS: - Alamofire: 85e8a02c69d6020a0d734f6054870d7ecb75cf18 DTCoreText: ec749e013f2e1f76de5e7c7634642e600a7467ce DTFoundation: e7781d9fd2f202bfd451fbbf8cab71ce83b46498 HTMLSpecialCharacters: edc707cc4bcdc92eb3b9551de8cff94c1e6f9a19 LicensesViewController: 2f7bba13b3cec7516d4990e41df297720fdbaaab - MaterialComponents: 2cdc12c16528ed7e6f1d5bd6d6927c47f9f4e90f + MaterialComponents: b9f58f24bf74588a83b2dce05802a11aaed5257d MDFInternationalization: 010097556d6b09d2c4ea38e0820ea6d37be6a314 MiniKeychain: 5d424fcd50fb8ab4cc946db2c3415dc391ffffdc MKColorPicker: 8998b2ab977e4f240fdf254db27a18b810da3cfc - MotionAnimator: ee16aa30567c5bae0fb2750c132915829cfaaf8a - MotionInterchange: ead0e3ae1f3a5fb539e289debbc7ae036160a10d + MotionAnimator: 5f99d7c9592928c0f28a66283eda9c3b657dc480 + MotionInterchange: 13adae439b377e31d1674cc165539d50e1d1566a MTColorDistance: 5ab8708eb88bc22d4d88e309d09eb912f3a6e27b OpalImagePicker: 38e772dd93a54431fc516b33e1f337c50f745834 QuickLayout: 07b45a72b10083fee3f095990cfed1c1e7b27f0a @@ -155,11 +151,11 @@ SPEC CHECKSUMS: SubtleVolume: 101038d203018736bcd1df3ac95bcc0f6b8640ce SwiftEntryKit: 1661b766dd22b07679e6ebb326ccfbd81ceb0a20 SwiftLinkPreview: 7524438c43bf63a5041615713777c3d8f19a9a31 - SwiftLint: 4fa9579c63416865179bc416f0a92d55f009600d + SwiftLint: 99f82d07b837b942dd563c668de129a03fc3fb52 SwiftyJSON: f0574c07d8ca1644050db687067209e3033a89a0 TGPControls: 52c0770bee9c9aee364f1559cc627fc01ea5e8b2 YoutubePlayer-in-WKWebView: cfbf46da51d7370662a695a8f351e5fa1d3e1008 -PODFILE CHECKSUM: 921cd225b4120efa1cb2e0c32101c3932f6ceb0c +PODFILE CHECKSUM: 11d5327e7fce051cd3b3ec699136a01fb7ad5b71 COCOAPODS: 1.10.0 diff --git a/Slide Widgets/Slide Widgets.entitlements b/Slide Widgets/Slide Widgets.entitlements index 23b6b4cc6..41aeeed9d 100644 --- a/Slide Widgets/Slide Widgets.entitlements +++ b/Slide Widgets/Slide Widgets.entitlements @@ -2,9 +2,13 @@ + com.apple.security.app-sandbox + com.apple.security.application-groups group.$(USR_DOMAIN).redditslide.prefs + com.apple.security.network.client + diff --git a/Slide for Apple Watch Extension/SubmissionRowController.swift b/Slide for Apple Watch Extension/SubmissionRowController.swift index 498725c33..52d01aaed 100644 --- a/Slide for Apple Watch Extension/SubmissionRowController.swift +++ b/Slide for Apple Watch Extension/SubmissionRowController.swift @@ -100,7 +100,7 @@ public class SubmissionRowController: NSObject { // endString.append(tagString) // } // - let boldString = NSMutableAttributedString(string: "r/\(dictionary["subreddit"] ?? "")", attributes: attrs) + let boldString = NSMutableAttributedString(string: (dictionary["subreddit"] as? String ?? "").getSubredditFormatted(), attributes: attrs) boldString.addAttribute(NSAttributedString.Key.foregroundColor, value: color, range: NSRange.init(location: 0, length: boldString.length)) @@ -240,3 +240,25 @@ public class SubmissionRowController: NSObject { self.imageGroup.setCornerRadius(10) } } + +extension String { + func getSubredditFormatted() -> String { + if self.hasPrefix("/m/") { + return self.replacingOccurrences(of: "/m/", with: "m/") + } + + if self.hasPrefix("u_") { + return self.replacingOccurrences(of: "u_", with: "u/") + } + + if self.hasPrefix("/r/") { + return self.replacingOccurrences(of: "/r/", with: "r/") + } + + if self.hasPrefix("r/") { + return self + } else { + return "r/\(self)" + } + } +} diff --git a/Slide for Reddit.xcodeproj/project.pbxproj b/Slide for Reddit.xcodeproj/project.pbxproj index 05ab1690c..29cbf9323 100644 --- a/Slide for Reddit.xcodeproj/project.pbxproj +++ b/Slide for Reddit.xcodeproj/project.pbxproj @@ -50,13 +50,13 @@ B49EFE382511A18F002D6AEE /* HotPostsWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = B49EFE372511A18F002D6AEE /* HotPostsWidget.swift */; }; B49EFE482511A1D1002D6AEE /* FavoriteSubredditsWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = B49EFE472511A1D1002D6AEE /* FavoriteSubredditsWidget.swift */; }; B49EFE522511A221002D6AEE /* UIImage+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = B49EFE512511A221002D6AEE /* UIImage+Extensions.swift */; }; - B4F333E1251273AF0032BB64 /* BuildFile in Frameworks */ = {isa = PBXBuildFile; productRef = B4F333E0251273AF0032BB64 /* SwiftPackageProductDependency */; }; - B4F333EB251274050032BB64 /* BuildFile in Frameworks */ = {isa = PBXBuildFile; productRef = B4F333EA251274050032BB64 /* SwiftPackageProductDependency */; }; - B4F333F52512742E0032BB64 /* BuildFile in Frameworks */ = {isa = PBXBuildFile; productRef = B4F333F42512742E0032BB64 /* SwiftPackageProductDependency */; }; - B4F3348B2512770F0032BB64 /* BuildFile in Frameworks */ = {isa = PBXBuildFile; productRef = B4F3348A2512770F0032BB64 /* SwiftPackageProductDependency */; }; - B4F3349F251277B80032BB64 /* BuildFile in Frameworks */ = {isa = PBXBuildFile; productRef = B4F3349E251277B80032BB64 /* SwiftPackageProductDependency */; }; - B4F3354C25127BAB0032BB64 /* BuildFile in Frameworks */ = {isa = PBXBuildFile; productRef = B4F3354B25127BAB0032BB64 /* SwiftPackageProductDependency */; }; - B4F3355625127BD20032BB64 /* BuildFile in Frameworks */ = {isa = PBXBuildFile; productRef = B4F3355525127BD20032BB64 /* SwiftPackageProductDependency */; }; + B4F333E1251273AF0032BB64 /* SDWebImage in Frameworks */ = {isa = PBXBuildFile; productRef = B4F333E0251273AF0032BB64 /* SDWebImage */; }; + B4F333EB251274050032BB64 /* BadgeSwift in Frameworks */ = {isa = PBXBuildFile; productRef = B4F333EA251274050032BB64 /* BadgeSwift */; }; + B4F333F52512742E0032BB64 /* BiometricAuthentication in Frameworks */ = {isa = PBXBuildFile; productRef = B4F333F42512742E0032BB64 /* BiometricAuthentication */; }; + B4F3348B2512770F0032BB64 /* Embassy in Frameworks */ = {isa = PBXBuildFile; productRef = B4F3348A2512770F0032BB64 /* Embassy */; }; + B4F3349F251277B80032BB64 /* Starscream in Frameworks */ = {isa = PBXBuildFile; productRef = B4F3349E251277B80032BB64 /* Starscream */; }; + B4F3354C25127BAB0032BB64 /* Anchorage in Frameworks */ = {isa = PBXBuildFile; productRef = B4F3354B25127BAB0032BB64 /* Anchorage */; }; + B4F3355625127BD20032BB64 /* Then in Frameworks */ = {isa = PBXBuildFile; productRef = B4F3355525127BD20032BB64 /* Then */; }; B776B17D5CA92860424F37C0 /* ModQueueContributionLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = B776BA7C2B7217C3875F3BEC /* ModQueueContributionLoader.swift */; }; B776B1DF80711B443ED76B61 /* SettingsPro.swift in Sources */ = {isa = PBXBuildFile; fileRef = B776B2AEE4A2438F5803329C /* SettingsPro.swift */; }; B776B1E23F4DEC18069F1579 /* MediaViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B776BC65995FE8D1EE75E2AB /* MediaViewController.swift */; }; @@ -78,7 +78,7 @@ BE02B253240C9F5400C457BC /* CommentsRowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE02B252240C9F5400C457BC /* CommentsRowController.swift */; }; BE02B255240CAC5D00C457BC /* CommentRepliesController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE02B254240CAC5D00C457BC /* CommentRepliesController.swift */; }; BE0334AF25294B8400B8C6B6 /* IntentHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE0334AE25294B8400B8C6B6 /* IntentHandler.swift */; }; - BE0334B325294B8400B8C6B6 /* WidgetConfigIntent.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = BE0334AC25294B8400B8C6B6 /* WidgetConfigIntent.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + BE0334B325294B8400B8C6B6 /* WidgetConfigIntent.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = BE0334AC25294B8400B8C6B6 /* WidgetConfigIntent.appex */; platformFilter = ios; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; BE0334CF25294C0700B8C6B6 /* TimelineSubreddit.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = BED90FF4250C1FB300090DF5 /* TimelineSubreddit.intentdefinition */; }; BE03351225294CEE00B8C6B6 /* IntentHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE0334AE25294B8400B8C6B6 /* IntentHandler.swift */; }; BE03356725295AB500B8C6B6 /* SettingsWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE03356625295AB500B8C6B6 /* SettingsWidget.swift */; }; @@ -169,7 +169,7 @@ BE20852521588F3B00D8F33C /* ExtensionDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE20852421588F3B00D8F33C /* ExtensionDelegate.swift */; }; BE20852721588F3B00D8F33C /* NotificationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE20852621588F3B00D8F33C /* NotificationController.swift */; }; BE20852921588F3B00D8F33C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = BE20852821588F3B00D8F33C /* Assets.xcassets */; }; - BE20852E21588F3B00D8F33C /* Slide for Apple Watch.app in Embed Watch Content */ = {isa = PBXBuildFile; fileRef = BE20851121588F3900D8F33C /* Slide for Apple Watch.app */; }; + BE20852E21588F3B00D8F33C /* Slide for Apple Watch.app in Embed Watch Content */ = {isa = PBXBuildFile; fileRef = BE20851121588F3900D8F33C /* Slide for Apple Watch.app */; platformFilter = ios; }; BE20853A21589FD600D8F33C /* SubmissionRowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE20853921589FD600D8F33C /* SubmissionRowController.swift */; }; BE232695222DE429005CA83A /* ic_ghost@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = BE232693222DE428005CA83A /* ic_ghost@2x.png */; }; BE232696222DE429005CA83A /* ic_ghost@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = BE232694222DE428005CA83A /* ic_ghost@3x.png */; }; @@ -178,7 +178,7 @@ BE257A6E21F64AA30082A47E /* Media.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = BE257A6D21F64AA30082A47E /* Media.xcassets */; }; BE257A7021F64AA30082A47E /* ActionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE257A6F21F64AA30082A47E /* ActionViewController.swift */; }; BE257A7321F64AA30082A47E /* MainInterface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = BE257A7121F64AA30082A47E /* MainInterface.storyboard */; }; - BE257A7721F64AA30082A47E /* Open in Slide.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = BE257A6B21F64AA30082A47E /* Open in Slide.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + BE257A7721F64AA30082A47E /* Open in Slide.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = BE257A6B21F64AA30082A47E /* Open in Slide.appex */; platformFilter = ios; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; BE257A7D21F8D9710082A47E /* SettingsThemeChooser.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE257A7C21F8D9710082A47E /* SettingsThemeChooser.swift */; }; BE25CAD424C3A28300736CA5 /* SwipeForwardNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE25CAD324C3A28300736CA5 /* SwipeForwardNavigationController.swift */; }; BE25CAD624C3A65400736CA5 /* SwipeForwardAnimatedTransitioning.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE25CAD524C3A65400736CA5 /* SwipeForwardAnimatedTransitioning.swift */; }; @@ -202,7 +202,7 @@ BE2F3F5D1EF96877003C1B28 /* SettingsContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE2F3F5C1EF96877003C1B28 /* SettingsContent.swift */; }; BE3144FF25663674004A908C /* AsyncTextAttachment.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE3144FE25663674004A908C /* AsyncTextAttachment.swift */; }; BE314509256738FF004A908C /* TitleUITextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE314508256738FF004A908C /* TitleUITextView.swift */; }; - BE31454625674E03004A908C /* BuildFile in Frameworks */ = {isa = PBXBuildFile; productRef = BE31454525674E03004A908C /* SwiftPackageProductDependency */; }; + BE31454625674E03004A908C /* Proton in Frameworks */ = {isa = PBXBuildFile; productRef = BE31454525674E03004A908C /* Proton */; }; BE325C66257EF04600BD2468 /* RedditObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE325C65257EF04600BD2468 /* RedditObject.swift */; }; BE325C70257EF06A00BD2468 /* SubmissionObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE325C6F257EF06A00BD2468 /* SubmissionObject.swift */; }; BE325C7C257EF33900BD2468 /* CommentObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE325C7B257EF33900BD2468 /* CommentObject.swift */; }; @@ -314,6 +314,7 @@ BE8AE94321F9225000E1C0D1 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = BE8AE94221F9225000E1C0D1 /* Main.storyboard */; }; BE8AE94721F922F400E1C0D1 /* ColorPickerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE8AE94621F922F400E1C0D1 /* ColorPickerViewController.swift */; }; BE8C29211EDE8001004D7514 /* MarginedTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE8C29201EDE8001004D7514 /* MarginedTableViewCell.swift */; }; + BE8CDDCD25C261D1002BBFF4 /* Alamofire in Frameworks */ = {isa = PBXBuildFile; productRef = BE8CDDCC25C261D1002BBFF4 /* Alamofire */; }; BE8EA67325A80F4B0094718E /* SubredditToolbarSearchViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE8EA67225A80F4B0094718E /* SubredditToolbarSearchViewController.swift */; }; BE8FCA081E0C46090063B8EF /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE8FCA071E0C46090063B8EF /* AppDelegate.swift */; }; BE8FCA0A1E0C46090063B8EF /* SingleSubredditViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE8FCA091E0C46090063B8EF /* SingleSubredditViewController.swift */; }; @@ -364,7 +365,7 @@ BEBF45DB1E23383D00764BB8 /* seen.plist in Resources */ = {isa = PBXBuildFile; fileRef = BEBF45DA1E23383D00764BB8 /* seen.plist */; }; BEBF45DD1E23384500764BB8 /* comments.plist in Resources */ = {isa = PBXBuildFile; fileRef = BEBF45DC1E23384500764BB8 /* comments.plist */; }; BEBF45E11E23EED800764BB8 /* SettingValues.swift in Sources */ = {isa = PBXBuildFile; fileRef = BEBF45E01E23EED800764BB8 /* SettingValues.swift */; }; - BEC2AB3A250D8D2C00AD5BEA /* WidgetKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BED90FE0250BF71600090DF5 /* WidgetKit.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; + BEC2AB3A250D8D2C00AD5BEA /* WidgetKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BED90FE0250BF71600090DF5 /* WidgetKit.framework */; platformFilter = ios; settings = {ATTRIBUTES = (Weak, ); }; }; BEC2FE19235BA2B100374013 /* adaway.json in Resources */ = {isa = PBXBuildFile; fileRef = BEC2FE18235BA2B100374013 /* adaway.json */; }; BEC494281E307D57006618F3 /* GalleryTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BEC494271E307D57006618F3 /* GalleryTableViewController.swift */; }; BEC4942A1E307DDA006618F3 /* GalleryCellView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BEC494291E307DDA006618F3 /* GalleryCellView.swift */; }; @@ -392,7 +393,7 @@ BED90FE3250BF71600090DF5 /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BED90FE2250BF71600090DF5 /* SwiftUI.framework */; }; BED90FE6250BF71600090DF5 /* SlideWidgets.swift in Sources */ = {isa = PBXBuildFile; fileRef = BED90FE5250BF71600090DF5 /* SlideWidgets.swift */; }; BED90FE8250BF71800090DF5 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = BED90FE7250BF71800090DF5 /* Assets.xcassets */; }; - BED90FEC250BF71800090DF5 /* Slide Widgets.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = BED90FDF250BF71600090DF5 /* Slide Widgets.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + BED90FEC250BF71800090DF5 /* Slide Widgets.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = BED90FDF250BF71600090DF5 /* Slide Widgets.appex */; platformFilter = ios; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; BED90FF5250C1FB300090DF5 /* TimelineSubreddit.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = BED90FF4250C1FB300090DF5 /* TimelineSubreddit.intentdefinition */; }; BED90FF6250C1FB300090DF5 /* TimelineSubreddit.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = BED90FF4250C1FB300090DF5 /* TimelineSubreddit.intentdefinition */; }; BEDDA9911E19AB5D003CD6C3 /* WebsiteViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BEDDA9901E19AB5D003CD6C3 /* WebsiteViewController.swift */; }; @@ -831,6 +832,7 @@ BE8AE94221F9225000E1C0D1 /* Main.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = ""; }; BE8AE94621F922F400E1C0D1 /* ColorPickerViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ColorPickerViewController.swift; sourceTree = ""; }; BE8C29201EDE8001004D7514 /* MarginedTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MarginedTableViewCell.swift; sourceTree = ""; }; + BE8CDBB325C259EF002BBFF4 /* Open in Slide.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "Open in Slide.entitlements"; sourceTree = ""; }; BE8EA67225A80F4B0094718E /* SubredditToolbarSearchViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SubredditToolbarSearchViewController.swift; sourceTree = ""; }; BE8FCA041E0C46090063B8EF /* Slide for Reddit.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Slide for Reddit.app"; sourceTree = BUILT_PRODUCTS_DIR; }; BE8FCA071E0C46090063B8EF /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; @@ -972,18 +974,19 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - B4F333F52512742E0032BB64 /* BuildFile in Frameworks */, + B4F333F52512742E0032BB64 /* BiometricAuthentication in Frameworks */, + BE8CDDCD25C261D1002BBFF4 /* Alamofire in Frameworks */, BEC2AB3A250D8D2C00AD5BEA /* WidgetKit.framework in Frameworks */, - B4F3355625127BD20032BB64 /* BuildFile in Frameworks */, - B4F333E1251273AF0032BB64 /* BuildFile in Frameworks */, - B4F333EB251274050032BB64 /* BuildFile in Frameworks */, + B4F3355625127BD20032BB64 /* Then in Frameworks */, + B4F333E1251273AF0032BB64 /* SDWebImage in Frameworks */, + B4F333EB251274050032BB64 /* BadgeSwift in Frameworks */, BE51BE6520C7386A00DFFD8B /* StoreKit.framework in Frameworks */, - B4F3354C25127BAB0032BB64 /* BuildFile in Frameworks */, - B4F3348B2512770F0032BB64 /* BuildFile in Frameworks */, - BE31454625674E03004A908C /* BuildFile in Frameworks */, + B4F3354C25127BAB0032BB64 /* Anchorage in Frameworks */, + B4F3348B2512770F0032BB64 /* Embassy in Frameworks */, + BE31454625674E03004A908C /* Proton in Frameworks */, BE2E9F0823492B4300FE07B4 /* CloudKit.framework in Frameworks */, BE7BFB481F1997BA009CA2E1 /* MapKit.framework in Frameworks */, - B4F3349F251277B80032BB64 /* BuildFile in Frameworks */, + B4F3349F251277B80032BB64 /* Starscream in Frameworks */, 01BBE6AB1AC863FE2E897632 /* Pods_Slide_for_Reddit.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1230,6 +1233,7 @@ BE257A6C21F64AA30082A47E /* Open in Slide */ = { isa = PBXGroup; children = ( + BE8CDBB325C259EF002BBFF4 /* Open in Slide.entitlements */, BE257A6D21F64AA30082A47E /* Media.xcassets */, BE257A6F21F64AA30082A47E /* ActionViewController.swift */, BE257A7121F64AA30082A47E /* MainInterface.storyboard */, @@ -1395,6 +1399,7 @@ BE0C4F7D21BCBE82006C54FF /* ic_tronblue@3x.png */, BE0C4F7821BCBE82006C54FF /* ic_tronteal@2x.png */, BE0C4F7221BCBE81006C54FF /* ic_tronteal@3x.png */, + BEC912AA258B31FF00E65F34 /* ContentViews */, BE0C4F7421BCBE81006C54FF /* ic_yellow@2x.png */, BE0C4F7E21BCBE82006C54FF /* ic_yellow@3x.png */, ); @@ -1530,7 +1535,6 @@ BE3E5C0F1E16BA1300749C0C /* Album */, BE4AB49C21BC4DAE001092C4 /* App Icons */, BE84B1B0257C5DAF00A90C5D /* CoreData */, - BEC912AA258B31FF00E65F34 /* ContentViews */, BE780B671E35276600DAA1EB /* ContentUtilities */, BE1DA3991E26D52500EC0A04 /* ContentViewControllers */, 0965260320E1688400EA53BE /* Extensions */, @@ -1727,6 +1731,7 @@ BEAE6A4A2564CCC100EF0806 /* ModLogCellView.swift */, ); name = ContentViews; + path = ..; sourceTree = ""; }; BED90FE4250BF71600090DF5 /* Slide Widgets */ = { @@ -1841,14 +1846,15 @@ ); name = "Slide for Reddit"; packageProductDependencies = ( - B4F333E0251273AF0032BB64 /* SwiftPackageProductDependency */, - B4F333EA251274050032BB64 /* SwiftPackageProductDependency */, - B4F333F42512742E0032BB64 /* SwiftPackageProductDependency */, - B4F3348A2512770F0032BB64 /* SwiftPackageProductDependency */, - B4F3349E251277B80032BB64 /* SwiftPackageProductDependency */, - B4F3354B25127BAB0032BB64 /* SwiftPackageProductDependency */, - B4F3355525127BD20032BB64 /* SwiftPackageProductDependency */, - BE31454525674E03004A908C /* SwiftPackageProductDependency */, + B4F333E0251273AF0032BB64 /* SDWebImage */, + B4F333EA251274050032BB64 /* BadgeSwift */, + B4F333F42512742E0032BB64 /* BiometricAuthentication */, + B4F3348A2512770F0032BB64 /* Embassy */, + B4F3349E251277B80032BB64 /* Starscream */, + B4F3354B25127BAB0032BB64 /* Anchorage */, + B4F3355525127BD20032BB64 /* Then */, + BE31454525674E03004A908C /* Proton */, + BE8CDDCC25C261D1002BBFF4 /* Alamofire */, ); productName = "Slide for Reddit"; productReference = BE8FCA041E0C46090063B8EF /* Slide for Reddit.app */; @@ -2012,14 +2018,15 @@ ); mainGroup = BE8FC9FB1E0C46090063B8EF; packageReferences = ( - B4F333DF251273AF0032BB64 /* RemoteSwiftPackageReference */, - B4F333E9251274050032BB64 /* RemoteSwiftPackageReference */, - B4F333F32512742E0032BB64 /* RemoteSwiftPackageReference */, - B4F334892512770F0032BB64 /* RemoteSwiftPackageReference */, - B4F3349D251277B80032BB64 /* RemoteSwiftPackageReference */, - B4F3354A25127BAB0032BB64 /* RemoteSwiftPackageReference */, - B4F3355425127BD20032BB64 /* RemoteSwiftPackageReference */, - BE31454425674E03004A908C /* RemoteSwiftPackageReference */, + B4F333DF251273AF0032BB64 /* XCRemoteSwiftPackageReference "SDWebImage" */, + B4F333E9251274050032BB64 /* XCRemoteSwiftPackageReference "swift-badge" */, + B4F333F32512742E0032BB64 /* XCRemoteSwiftPackageReference "BiometricAuthentication" */, + B4F334892512770F0032BB64 /* XCRemoteSwiftPackageReference "Embassy" */, + B4F3349D251277B80032BB64 /* XCRemoteSwiftPackageReference "Starscream" */, + B4F3354A25127BAB0032BB64 /* XCRemoteSwiftPackageReference "Anchorage" */, + B4F3355425127BD20032BB64 /* XCRemoteSwiftPackageReference "Then" */, + BE31454425674E03004A908C /* XCRemoteSwiftPackageReference "proton" */, + BE8CDDCB25C261D1002BBFF4 /* XCRemoteSwiftPackageReference "Alamofire" */, ); productRefGroup = BE8FCA051E0C46090063B8EF /* Products */; projectDirPath = ""; @@ -2289,7 +2296,6 @@ ); inputPaths = ( "${PODS_ROOT}/Target Support Files/Pods-Slide for Reddit/Pods-Slide for Reddit-frameworks.sh", - "${BUILT_PRODUCTS_DIR}/Alamofire/Alamofire.framework", "${BUILT_PRODUCTS_DIR}/DTCoreText/DTCoreText.framework", "${BUILT_PRODUCTS_DIR}/DTFoundation/DTFoundation.framework", "${BUILT_PRODUCTS_DIR}/HTMLSpecialCharacters/HTMLSpecialCharacters.framework", @@ -2315,7 +2321,6 @@ ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Alamofire.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DTCoreText.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DTFoundation.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/HTMLSpecialCharacters.framework", @@ -2721,6 +2726,7 @@ /* Begin PBXTargetDependency section */ BE0334B225294B8400B8C6B6 /* PBXTargetDependency */ = { isa = PBXTargetDependency; + platformFilter = ios; target = BE0334AB25294B8400B8C6B6 /* WidgetConfigIntent */; targetProxy = BE0334B125294B8400B8C6B6 /* PBXContainerItemProxy */; }; @@ -2731,11 +2737,13 @@ }; BE20852D21588F3B00D8F33C /* PBXTargetDependency */ = { isa = PBXTargetDependency; + platformFilter = ios; target = BE20851021588F3900D8F33C /* Slide for Apple Watch */; targetProxy = BE20852C21588F3B00D8F33C /* PBXContainerItemProxy */; }; BE257A7621F64AA30082A47E /* PBXTargetDependency */ = { isa = PBXTargetDependency; + platformFilter = ios; target = BE257A6A21F64AA30082A47E /* Open in Slide */; targetProxy = BE257A7521F64AA30082A47E /* PBXContainerItemProxy */; }; @@ -2756,6 +2764,7 @@ }; BED90FEB250BF71800090DF5 /* PBXTargetDependency */ = { isa = PBXTargetDependency; + platformFilter = ios; target = BED90FDE250BF71600090DF5 /* Slide Widgets */; targetProxy = BED90FEA250BF71800090DF5 /* PBXContainerItemProxy */; }; @@ -2801,7 +2810,7 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 224; + CURRENT_PROJECT_VERSION = 227; DEVELOPMENT_TEAM = FTT89576VQ; GCC_C_LANGUAGE_STANDARD = gnu11; INFOPLIST_FILE = WidgetConfigIntent/Info.plist; @@ -2811,12 +2820,13 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 7.0.1; + MARKETING_VERSION = 7.1; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = "$(USR_BASE_IDENTIFIER).WidgetConfigIntent"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; + SUPPORTS_MACCATALYST = NO; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; }; @@ -2834,7 +2844,7 @@ CODE_SIGN_IDENTITY = "iPhone Distribution"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 224; + CURRENT_PROJECT_VERSION = 227; DEVELOPMENT_TEAM = FTT89576VQ; GCC_C_LANGUAGE_STANDARD = gnu11; INFOPLIST_FILE = WidgetConfigIntent/Info.plist; @@ -2844,12 +2854,13 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 7.0.1; + MARKETING_VERSION = 7.1; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = ccrama.me.redditslide.bundledwidgetconfigintent; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = "match Development ccrama.me.redditslide.bundledwidgetconfigintent"; SKIP_INSTALL = YES; + SUPPORTS_MACCATALYST = NO; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; }; @@ -2869,7 +2880,7 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 224; + CURRENT_PROJECT_VERSION = 227; DEVELOPMENT_TEAM = FTT89576VQ; GCC_C_LANGUAGE_STANDARD = gnu11; IBSC_MODULE = Slide_for_Apple_Watch_Extension; @@ -2879,7 +2890,7 @@ "@executable_path/../Frameworks", "@loader_path/../Frameworks", ); - MARKETING_VERSION = 7.0.1; + MARKETING_VERSION = 7.1; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = "$(USR_BASE_IDENTIFIER).watchkitapp"; @@ -2910,7 +2921,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 224; + CURRENT_PROJECT_VERSION = 227; DEVELOPMENT_TEAM = FTT89576VQ; GCC_C_LANGUAGE_STANDARD = gnu11; IBSC_MODULE = Slide_for_Apple_Watch_Extension; @@ -2920,7 +2931,7 @@ "@executable_path/../Frameworks", "@loader_path/../Frameworks", ); - MARKETING_VERSION = 7.0.1; + MARKETING_VERSION = 7.1; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = ccrama.me.redditslide.watchkitapp; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -2944,7 +2955,7 @@ CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 224; + CURRENT_PROJECT_VERSION = 227; DEVELOPMENT_TEAM = FTT89576VQ; GCC_C_LANGUAGE_STANDARD = gnu11; INFOPLIST_FILE = "Slide for Apple Watch Extension/Info.plist"; @@ -2953,7 +2964,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 7.0.1; + MARKETING_VERSION = 7.1; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = "$(USR_BASE_IDENTIFIER).watchkitapp.watchkitextension"; @@ -2977,7 +2988,7 @@ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 224; + CURRENT_PROJECT_VERSION = 227; DEVELOPMENT_TEAM = ""; GCC_C_LANGUAGE_STANDARD = gnu11; INFOPLIST_FILE = "Slide for Apple Watch Extension/Info.plist"; @@ -2986,7 +2997,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 7.0.1; + MARKETING_VERSION = 7.1; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = ccrama.me.redditslide.watchkitapp.watchkitextension; PRODUCT_NAME = "${TARGET_NAME}"; @@ -3008,10 +3019,11 @@ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_ENTITLEMENTS = "Open in Slide/Open in Slide.entitlements"; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 224; + CURRENT_PROJECT_VERSION = 227; DEVELOPMENT_TEAM = FTT89576VQ; GCC_C_LANGUAGE_STANDARD = gnu11; INFOPLIST_FILE = "Open in Slide/Info.plist"; @@ -3021,12 +3033,13 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 7.0.1; + MARKETING_VERSION = 7.1; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = "$(USR_BASE_IDENTIFIER).Open-in-Slide"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; + SUPPORTS_MACCATALYST = NO; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; }; @@ -3040,10 +3053,11 @@ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_ENTITLEMENTS = "Open in Slide/Open in Slide.entitlements"; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 224; + CURRENT_PROJECT_VERSION = 227; DEVELOPMENT_TEAM = FTT89576VQ; GCC_C_LANGUAGE_STANDARD = gnu11; INFOPLIST_FILE = "Open in Slide/Info.plist"; @@ -3053,12 +3067,13 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 7.0.1; + MARKETING_VERSION = 7.1; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = "ccrama.me.redditslide.bundledOpen-in-Slide"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = "match Development ccrama.me.redditslide.bundledOpen-in-Slide"; SKIP_INSTALL = YES; + SUPPORTS_MACCATALYST = NO; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; }; @@ -3198,7 +3213,7 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 224; + CURRENT_PROJECT_VERSION = 227; DEVELOPMENT_TEAM = FTT89576VQ; GCC_WARN_UNUSED_PARAMETER = YES; INFOPLIST_FILE = "Slide for Reddit/Info.plist"; @@ -3207,7 +3222,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 7.0.1; + MARKETING_VERSION = 7.1; OTHER_LDFLAGS = ( "$(inherited)", "-framework", @@ -3217,11 +3232,15 @@ PRODUCT_BUNDLE_IDENTIFIER = "$(USR_BASE_IDENTIFIER)"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; + SUPPORTS_MACCATALYST = NO; + SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES; + SWIFT_ENABLE_BATCH_MODE = NO; SWIFT_OBJC_BRIDGING_HEADER = "Slide for Reddit/Slide for Reddit-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; "SWIFT_OPTIMIZATION_LEVEL[arch=*]" = "-Onone"; SWIFT_SWIFT3_OBJC_INFERENCE = Default; SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; }; @@ -3233,10 +3252,10 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = "Slide for Reddit/Slide for Reddit.entitlements"; - CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_IDENTITY = "iPhone Distribution"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 224; + CURRENT_PROJECT_VERSION = 227; DEVELOPMENT_TEAM = FTT89576VQ; GCC_OPTIMIZATION_LEVEL = fast; GCC_WARN_UNUSED_PARAMETER = YES; @@ -3246,7 +3265,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 7.0.1; + MARKETING_VERSION = 7.1; OTHER_LDFLAGS = ( "$(inherited)", "-framework", @@ -3256,9 +3275,13 @@ PRODUCT_BUNDLE_IDENTIFIER = "$(USR_BASE_IDENTIFIER)"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = "match Development ccrama.me.redditslide"; + SUPPORTS_MACCATALYST = NO; + SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES; + SWIFT_ENABLE_BATCH_MODE = NO; SWIFT_OBJC_BRIDGING_HEADER = "Slide for Reddit/Slide for Reddit-Bridging-Header.h"; SWIFT_SWIFT3_OBJC_INFERENCE = Default; SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; }; name = Release; }; @@ -3413,7 +3436,7 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 224; + CURRENT_PROJECT_VERSION = 227; DEVELOPMENT_TEAM = FTT89576VQ; GCC_C_LANGUAGE_STANDARD = gnu11; INFOPLIST_FILE = "Slide Widgets/Info.plist"; @@ -3423,12 +3446,13 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 7.0.1; + MARKETING_VERSION = 7.1; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = "$(USR_BASE_IDENTIFIER).widgets"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; + SUPPORTS_MACCATALYST = NO; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; }; @@ -3448,7 +3472,7 @@ CODE_SIGN_IDENTITY = "iPhone Distribution"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 224; + CURRENT_PROJECT_VERSION = 227; DEVELOPMENT_TEAM = FTT89576VQ; GCC_C_LANGUAGE_STANDARD = gnu11; INFOPLIST_FILE = "Slide Widgets/Info.plist"; @@ -3458,12 +3482,13 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 7.0.1; + MARKETING_VERSION = 7.1; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = ccrama.me.redditslide.bundledwidgets; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = "match Development ccrama.me.redditslide.bundledwidgets 1599951103"; SKIP_INSTALL = YES; + SUPPORTS_MACCATALYST = NO; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; }; @@ -3565,7 +3590,7 @@ /* End XCConfigurationList section */ /* Begin XCRemoteSwiftPackageReference section */ - B4F333DF251273AF0032BB64 /* RemoteSwiftPackageReference */ = { + B4F333DF251273AF0032BB64 /* XCRemoteSwiftPackageReference "SDWebImage" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/SDWebImage/SDWebImage"; requirement = { @@ -3573,7 +3598,7 @@ minimumVersion = 5.9.1; }; }; - B4F333E9251274050032BB64 /* RemoteSwiftPackageReference */ = { + B4F333E9251274050032BB64 /* XCRemoteSwiftPackageReference "swift-badge" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/evgenyneu/swift-badge"; requirement = { @@ -3581,7 +3606,7 @@ minimumVersion = 8.0.2; }; }; - B4F333F32512742E0032BB64 /* RemoteSwiftPackageReference */ = { + B4F333F32512742E0032BB64 /* XCRemoteSwiftPackageReference "BiometricAuthentication" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/rushisangani/BiometricAuthentication"; requirement = { @@ -3589,7 +3614,7 @@ minimumVersion = 3.1.2; }; }; - B4F334892512770F0032BB64 /* RemoteSwiftPackageReference */ = { + B4F334892512770F0032BB64 /* XCRemoteSwiftPackageReference "Embassy" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/envoy/Embassy"; requirement = { @@ -3597,7 +3622,7 @@ minimumVersion = 4.1.1; }; }; - B4F3349D251277B80032BB64 /* RemoteSwiftPackageReference */ = { + B4F3349D251277B80032BB64 /* XCRemoteSwiftPackageReference "Starscream" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/daltoniam/Starscream"; requirement = { @@ -3605,7 +3630,7 @@ version = 3.1.1; }; }; - B4F3354A25127BAB0032BB64 /* RemoteSwiftPackageReference */ = { + B4F3354A25127BAB0032BB64 /* XCRemoteSwiftPackageReference "Anchorage" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/Rightpoint/Anchorage"; requirement = { @@ -3613,7 +3638,7 @@ minimumVersion = 4.5.0; }; }; - B4F3355425127BD20032BB64 /* RemoteSwiftPackageReference */ = { + B4F3355425127BD20032BB64 /* XCRemoteSwiftPackageReference "Then" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/devxoul/Then"; requirement = { @@ -3621,7 +3646,7 @@ minimumVersion = 2.7.0; }; }; - BE31454425674E03004A908C /* RemoteSwiftPackageReference */ = { + BE31454425674E03004A908C /* XCRemoteSwiftPackageReference "proton" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/rajdeep/proton"; requirement = { @@ -3629,49 +3654,62 @@ minimumVersion = 0.5.0; }; }; + BE8CDDCB25C261D1002BBFF4 /* XCRemoteSwiftPackageReference "Alamofire" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/Alamofire/Alamofire.git"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 5.4.1; + }; + }; /* End XCRemoteSwiftPackageReference section */ /* Begin XCSwiftPackageProductDependency section */ - B4F333E0251273AF0032BB64 /* SwiftPackageProductDependency */ = { + B4F333E0251273AF0032BB64 /* SDWebImage */ = { isa = XCSwiftPackageProductDependency; - package = B4F333DF251273AF0032BB64 /* RemoteSwiftPackageReference */; + package = B4F333DF251273AF0032BB64 /* XCRemoteSwiftPackageReference "SDWebImage" */; productName = SDWebImage; }; - B4F333EA251274050032BB64 /* SwiftPackageProductDependency */ = { + B4F333EA251274050032BB64 /* BadgeSwift */ = { isa = XCSwiftPackageProductDependency; - package = B4F333E9251274050032BB64 /* RemoteSwiftPackageReference */; + package = B4F333E9251274050032BB64 /* XCRemoteSwiftPackageReference "swift-badge" */; productName = BadgeSwift; }; - B4F333F42512742E0032BB64 /* SwiftPackageProductDependency */ = { + B4F333F42512742E0032BB64 /* BiometricAuthentication */ = { isa = XCSwiftPackageProductDependency; - package = B4F333F32512742E0032BB64 /* RemoteSwiftPackageReference */; + package = B4F333F32512742E0032BB64 /* XCRemoteSwiftPackageReference "BiometricAuthentication" */; productName = BiometricAuthentication; }; - B4F3348A2512770F0032BB64 /* SwiftPackageProductDependency */ = { + B4F3348A2512770F0032BB64 /* Embassy */ = { isa = XCSwiftPackageProductDependency; - package = B4F334892512770F0032BB64 /* RemoteSwiftPackageReference */; + package = B4F334892512770F0032BB64 /* XCRemoteSwiftPackageReference "Embassy" */; productName = Embassy; }; - B4F3349E251277B80032BB64 /* SwiftPackageProductDependency */ = { + B4F3349E251277B80032BB64 /* Starscream */ = { isa = XCSwiftPackageProductDependency; - package = B4F3349D251277B80032BB64 /* RemoteSwiftPackageReference */; + package = B4F3349D251277B80032BB64 /* XCRemoteSwiftPackageReference "Starscream" */; productName = Starscream; }; - B4F3354B25127BAB0032BB64 /* SwiftPackageProductDependency */ = { + B4F3354B25127BAB0032BB64 /* Anchorage */ = { isa = XCSwiftPackageProductDependency; - package = B4F3354A25127BAB0032BB64 /* RemoteSwiftPackageReference */; + package = B4F3354A25127BAB0032BB64 /* XCRemoteSwiftPackageReference "Anchorage" */; productName = Anchorage; }; - B4F3355525127BD20032BB64 /* SwiftPackageProductDependency */ = { + B4F3355525127BD20032BB64 /* Then */ = { isa = XCSwiftPackageProductDependency; - package = B4F3355425127BD20032BB64 /* RemoteSwiftPackageReference */; + package = B4F3355425127BD20032BB64 /* XCRemoteSwiftPackageReference "Then" */; productName = Then; }; - BE31454525674E03004A908C /* SwiftPackageProductDependency */ = { + BE31454525674E03004A908C /* Proton */ = { isa = XCSwiftPackageProductDependency; - package = BE31454425674E03004A908C /* RemoteSwiftPackageReference */; + package = BE31454425674E03004A908C /* XCRemoteSwiftPackageReference "proton" */; productName = Proton; }; + BE8CDDCC25C261D1002BBFF4 /* Alamofire */ = { + isa = XCSwiftPackageProductDependency; + package = BE8CDDCB25C261D1002BBFF4 /* XCRemoteSwiftPackageReference "Alamofire" */; + productName = Alamofire; + }; /* End XCSwiftPackageProductDependency section */ /* Begin XCVersionGroup section */ diff --git a/Slide for Reddit.xcodeproj/xcshareddata/xcschemes/Slide for Apple Watch.xcscheme b/Slide for Reddit.xcodeproj/xcshareddata/xcschemes/Slide for Apple Watch.xcscheme index 0530f2df2..0d084ded0 100644 --- a/Slide for Reddit.xcodeproj/xcshareddata/xcschemes/Slide for Apple Watch.xcscheme +++ b/Slide for Reddit.xcodeproj/xcshareddata/xcschemes/Slide for Apple Watch.xcscheme @@ -65,8 +65,10 @@ debugServiceExtension = "internal" allowLocationSimulation = "YES" notificationPayloadFile = "Slide for Apple Watch Extension/PushNotificationPayload.apns"> - + - + - + - + + + + + diff --git a/Slide for Reddit.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Slide for Reddit.xcworkspace/xcshareddata/swiftpm/Package.resolved index e0557b5f9..990c26537 100644 --- a/Slide for Reddit.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Slide for Reddit.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,6 +1,15 @@ { "object": { "pins": [ + { + "package": "Alamofire", + "repositoryURL": "https://github.com/Alamofire/Alamofire.git", + "state": { + "branch": null, + "revision": "eaf6e622dd41b07b251d8f01752eab31bc811493", + "version": "5.4.1" + } + }, { "package": "Anchorage", "repositoryURL": "https://github.com/Rightpoint/Anchorage", diff --git a/Slide for Reddit/AccountController.swift b/Slide for Reddit/AccountController.swift index e2866adeb..a80324b3c 100644 --- a/Slide for Reddit/AccountController.swift +++ b/Slide for Reddit/AccountController.swift @@ -22,7 +22,6 @@ class AccountController { } static func switchAccount(name: String) { - changed = true ActionStates.upVotedFullnames.removeAll() ActionStates.downVotedFullnames.removeAll() ActionStates.savedFullnames.removeAll() @@ -36,7 +35,6 @@ class AccountController { static var isLoggedIn = false static var isGold = false - static var changed = false static var modSubs: [String] = [] static var current: Account? diff --git a/Slide for Reddit/AnyModalViewController.swift b/Slide for Reddit/AnyModalViewController.swift index 95173de86..1348f74b9 100644 --- a/Slide for Reddit/AnyModalViewController.swift +++ b/Slide for Reddit/AnyModalViewController.swift @@ -8,12 +8,16 @@ import Anchorage import AVKit -import SubtleVolume + +#if os(iOS) + import SubtleVolume +#endif + import Then import UIKit class AnyModalViewController: UIViewController { - let volume = SubtleVolume(style: SubtleVolumeStyle.rounded) + var volume: SubtleVolume? let volumeHeight: CGFloat = 3 static var linkID = "" @@ -56,6 +60,7 @@ class AnyModalViewController: UIViewController { var bottomButtons = UIStackView() var goToCommentsButton = UIButton() var upvoteButton = UIButton() + private var volumeObserver: NSKeyValueObservation! var closeButton = UIButton().then { $0.accessibilityIdentifier = "Close Button" @@ -171,9 +176,6 @@ class AnyModalViewController: UIViewController { connectActions() handleHideUI() - volume.barTintColor = .white - volume.barBackgroundColor = UIColor.white.withAlphaComponent(0.3) - volume.animation = .slideDown var is13 = false if #available(iOS 13, *) { @@ -181,8 +183,14 @@ class AnyModalViewController: UIViewController { } if !is13 { - view.addSubview(volume) - NotificationCenter.default.addObserver(volume, selector: #selector(SubtleVolume.resume), name: UIApplication.didBecomeActiveNotification, object: nil) + volume = SubtleVolume(style: .rounded) + + volume!.barTintColor = .white + volume!.barBackgroundColor = UIColor.white.withAlphaComponent(0.3) + volume!.animation = .slideDown + + view.addSubview(volume!) + NotificationCenter.default.addObserver(volume!, selector: #selector(SubtleVolume.resume), name: UIApplication.didBecomeActiveNotification, object: nil) } if urlToLoad != nil && self.embeddedPlayer == nil { @@ -255,8 +263,10 @@ class AnyModalViewController: UIViewController { func layoutVolume() { let volumeYPadding: CGFloat = 10 let volumeXPadding = UIScreen.main.bounds.width * 0.4 / 2 - volume.superview?.bringSubviewToFront(volume) - volume.frame = CGRect(x: safeAreaInsets.left + volumeXPadding, y: safeAreaInsets.top + volumeYPadding, width: UIScreen.main.bounds.width - (volumeXPadding * 2) - safeAreaInsets.left - safeAreaInsets.right, height: volumeHeight) + if let volume = volume { + volume.superview?.bringSubviewToFront(volume) + volume.frame = CGRect(x: safeAreaInsets.left + volumeXPadding, y: safeAreaInsets.top + volumeYPadding, width: UIScreen.main.bounds.width - (volumeXPadding * 2) - safeAreaInsets.left - safeAreaInsets.right, height: volumeHeight) + } } func stopDisplayLink() { @@ -588,6 +598,7 @@ class AnyModalViewController: UIViewController { muteButton = UIButton().then { $0.accessibilityIdentifier = "Toggle Mute" + $0.isHidden = true $0.accessibilityLabel = "Toggle Mute" $0.contentEdgeInsets = UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 8) } @@ -703,6 +714,13 @@ class AnyModalViewController: UIViewController { if !self.scrubber.isHidden { self.fullscreen(self) + if SettingValues.tapExitMedia { + if let parent = parent as? ModalMediaViewController { + parent.exit() + return + } + } + UIView.animate(withDuration: 0.2, animations: { self.scrubber.alpha = 0 }, completion: { (_) in @@ -896,6 +914,11 @@ extension AnyModalViewController { until a bit of time has passed. We react to that here, setting the audio session and the mute button state accordingly. */ + + if hasAudioTracks && muteButton.isHidden { + muteButton.isHidden = false + } + if !setOnce || lastTracks != hasAudioTracks { setOnce = true lastTracks = hasAudioTracks @@ -911,6 +934,15 @@ extension AnyModalViewController { // from silencing background audio mute() } + + volumeObserver = AVAudioSession.sharedInstance().observe(\.outputVolume) { [weak self] (_, _) in + guard let self = self else { return } + + if self.videoView.player?.isMuted ?? false { + self.unmute() + } + } + } if !sliderBeingUsed { diff --git a/Slide for Reddit/AppDelegate.swift b/Slide for Reddit/AppDelegate.swift index bc0e4a671..cd35279e0 100644 --- a/Slide for Reddit/AppDelegate.swift +++ b/Slide for Reddit/AppDelegate.swift @@ -395,7 +395,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { SwipeForwardNavigationController( rootViewController: main), ] - case .SPLIT: + default: let swipeNav = SwipeForwardNavigationController(rootViewController: NavigationHomeViewController(controller: main)) swipeNav.pushViewController(main, animated: false) splitViewController.viewControllers = [ @@ -418,46 +418,60 @@ class AppDelegate: UIResponder, UIApplicationDelegate { @available(iOS 14.0, *) func doHard14(_ window: UIWindow) -> MainViewController { - let style: UISplitViewController.Style = SettingValues.appMode == .SPLIT ? .tripleColumn : .doubleColumn + let style: UISplitViewController.Style = SettingValues.appMode == .SPLIT || SettingValues.appMode == .TRIPLE_MULTI_COLUMN + ? .tripleColumn : .doubleColumn var splitViewController: NoHomebarSplitViewController = NoHomebarSplitViewController(style: style) let main: SplitMainViewController = SplitMainViewController(transitionStyle: .scroll, navigationOrientation: .horizontal, options: nil) - switch UIDevice.current.userInterfaceIdiom { - case .pad: - switch SettingValues.appMode { - case .SINGLE, .MULTI_COLUMN: - splitViewController.setViewController( - SwipeForwardNavigationController(rootViewController: NavigationHomeViewController(controller: main)), - for: .primary) - splitViewController.setViewController( - SwipeForwardNavigationController(rootViewController: main), - for: .secondary) - - let main2: SplitMainViewController = SplitMainViewController(transitionStyle: .scroll, navigationOrientation: .horizontal, options: nil) - let compact = SwipeForwardNavigationController(rootViewController: NavigationHomeViewController(controller: main2)) - - compact.pushViewController(main2, animated: false) - splitViewController.setViewController(compact, for: .compact) - - splitViewController.setViewController( - SwipeForwardNavigationController(rootViewController: main), - for: .secondary) - case .SPLIT: - splitViewController.setViewController( - SwipeForwardNavigationController(rootViewController: NavigationHomeViewController(controller: main)), - for: .primary) - splitViewController.setViewController( - SwipeForwardNavigationController(rootViewController: main), - for: .supplementary) - splitViewController.setViewController( - PlaceholderViewController(), - for: .secondary) + if SettingValues.appMode == .TRIPLE_MULTI_COLUMN { + splitViewController.setViewController( + SwipeForwardNavigationController(rootViewController: NavigationHomeViewController(controller: main)), + for: .primary) + splitViewController.setViewController( + SwipeForwardNavigationController(rootViewController: main), + for: .supplementary) + splitViewController.setViewController( + PlaceholderViewController(), + for: .secondary) + + } else { + switch UIDevice.current.userInterfaceIdiom { + case .pad, .mac: + switch SettingValues.appMode { + case .SINGLE, .MULTI_COLUMN: + splitViewController.setViewController( + SwipeForwardNavigationController(rootViewController: NavigationHomeViewController(controller: main)), + for: .primary) + splitViewController.setViewController( + SwipeForwardNavigationController(rootViewController: main), + for: .secondary) + + let main2: SplitMainViewController = SplitMainViewController(transitionStyle: .scroll, navigationOrientation: .horizontal, options: nil) + let compact = SwipeForwardNavigationController(rootViewController: NavigationHomeViewController(controller: main2)) + + compact.pushViewController(main2, animated: false) + splitViewController.setViewController(compact, for: .compact) + + splitViewController.setViewController( + SwipeForwardNavigationController(rootViewController: main), + for: .secondary) + default: + splitViewController.setViewController( + SwipeForwardNavigationController(rootViewController: NavigationHomeViewController(controller: main)), + for: .primary) + splitViewController.setViewController( + SwipeForwardNavigationController(rootViewController: main), + for: .supplementary) + splitViewController.setViewController( + PlaceholderViewController(), + for: .secondary) + } + default: + splitViewController = NoHomebarSplitViewController() + let navHome = NavigationHomeViewController(controller: main) + splitViewController.viewControllers = [SwipeForwardNavigationController(rootViewController: navHome), SwipeForwardNavigationController(rootViewController: main)] } - default: - splitViewController = NoHomebarSplitViewController() - let navHome = NavigationHomeViewController(controller: main) - splitViewController.viewControllers = [SwipeForwardNavigationController(rootViewController: navHome), SwipeForwardNavigationController(rootViewController: main)] } window.rootViewController = splitViewController @@ -472,11 +486,21 @@ class AppDelegate: UIResponder, UIApplicationDelegate { func setupSplitLayout(_ splitViewController: UISplitViewController) { // Set column widths if #available(iOS 14.0, *) { - splitViewController.preferredPrimaryColumnWidthFraction = 0.33 - splitViewController.minimumPrimaryColumnWidth = UIScreen.main.bounds.width * 0.33 - if splitViewController.style == .tripleColumn { - splitViewController.preferredSupplementaryColumnWidthFraction = 0.33 - splitViewController.minimumSupplementaryColumnWidth = UIScreen.main.bounds.width * 0.33 + if SettingValues.appMode == .TRIPLE_MULTI_COLUMN { + splitViewController.minimumPrimaryColumnWidth = UIScreen.main.bounds.width * 0.15 + splitViewController.preferredPrimaryColumnWidthFraction = 0.15 + splitViewController.maximumPrimaryColumnWidth = UIScreen.main.bounds.width * 0.15 + + splitViewController.minimumSupplementaryColumnWidth = UIScreen.main.bounds.width * 0.25 + splitViewController.maximumSupplementaryColumnWidth = UIScreen.main.bounds.width * 0.25 + splitViewController.preferredSupplementaryColumnWidthFraction = 0.25 + } else { + splitViewController.preferredPrimaryColumnWidthFraction = 0.33 + splitViewController.minimumPrimaryColumnWidth = UIScreen.main.bounds.width * 0.33 + if splitViewController.style == .tripleColumn { + splitViewController.preferredSupplementaryColumnWidthFraction = 0.33 + splitViewController.minimumSupplementaryColumnWidth = UIScreen.main.bounds.width * 0.33 + } } } else { splitViewController.preferredPrimaryColumnWidthFraction = 0.4 @@ -485,35 +509,40 @@ class AppDelegate: UIResponder, UIApplicationDelegate { splitViewController.presentsWithGesture = true - // Set display mode and split behavior - switch UIDevice.current.userInterfaceIdiom { - case .pad: - switch SettingValues.appMode { - case .SINGLE, .MULTI_COLUMN: - if UIApplication.shared.isSplitOrSlideOver { - setupSplitPaneLayout(splitViewController) - } else if SettingValues.desktopMode { - splitViewController.preferredDisplayMode = .oneBesideSecondary - if #available(iOS 14.0, *) { - splitViewController.preferredSplitBehavior = .displace - } - } else { - splitViewController.preferredDisplayMode = .secondaryOnly - if #available(iOS 14.0, *) { - splitViewController.preferredSplitBehavior = .overlay + if SettingValues.appMode == .TRIPLE_MULTI_COLUMN { + splitViewController.presentsWithGesture = false + setupSplitPaneLayout(splitViewController) + } else { + // Set display mode and split behavior + switch UIDevice.current.userInterfaceIdiom { + case .pad: + switch SettingValues.appMode { + case .SINGLE, .MULTI_COLUMN: + if UIApplication.shared.isSplitOrSlideOver { + setupSplitPaneLayout(splitViewController) + } else if SettingValues.desktopMode { + splitViewController.preferredDisplayMode = .oneBesideSecondary + if #available(iOS 14.0, *) { + splitViewController.preferredSplitBehavior = .displace + } + } else { + splitViewController.preferredDisplayMode = .secondaryOnly + if #available(iOS 14.0, *) { + splitViewController.preferredSplitBehavior = .overlay + } } + default: + setupSplitPaneLayout(splitViewController) } - case .SPLIT: - setupSplitPaneLayout(splitViewController) + default: + splitViewController.preferredDisplayMode = .oneOverSecondary } - default: - splitViewController.preferredDisplayMode = .oneOverSecondary } } func setupSplitPaneLayout(_ splitViewController: UISplitViewController) { if #available(iOS 14.0, *) { - if SettingValues.desktopMode { + if SettingValues.desktopMode || UIDevice.current.isMac() { splitViewController.preferredDisplayMode = .twoBesideSecondary splitViewController.preferredSplitBehavior = .tile } else { @@ -777,12 +806,13 @@ class AppDelegate: UIResponder, UIApplicationDelegate { let themeName = url.absoluteString.removingPercentEncoding!.split("#")[1] let themeView = ThemeCellView().then { - $0.setTheme(string: url.absoluteString.removingPercentEncoding ?? url.absoluteString) + $0.setTheme(colors: url.absoluteString.removingPercentEncoding ?? url.absoluteString) } let cv = themeView.contentView let alert = DragDownAlertMenu(title: themeName, subtitle: "", icon: nil, extraView: cv, themeColor: nil, full: false) - + alert.extraViewHeight = 60 + alert.addAction(title: "Save Theme", icon: UIImage(sfString: .squareAndArrowDownFill, overrideString: "save-1")) { let colorString = url.absoluteString.removingPercentEncoding ?? url.absoluteString @@ -1157,7 +1187,27 @@ extension AppDelegate: UIWindowSceneDelegate { willResignActive() SlideCoreData.sharedInstance.saveContext() } - + + func windowScene(_ windowScene: UIWindowScene, didUpdate previousCoordinateSpace: UICoordinateSpace, interfaceOrientation previousInterfaceOrientation: UIInterfaceOrientation, traitCollection previousTraitCollection: UITraitCollection) { + if UIDevice.current.isMac() { + let size = windowScene.coordinateSpace.bounds.size + + for window in windowScene.windows { + if #available(iOS 14.0, *) { + if let split = window.rootViewController as? UISplitViewController, split.style == .tripleColumn { + split.minimumPrimaryColumnWidth = size.width * 0.15 + split.preferredPrimaryColumnWidthFraction = 0.15 + split.maximumPrimaryColumnWidth = size.width * 0.15 + + split.minimumSupplementaryColumnWidth = size.width * 0.6 + split.maximumSupplementaryColumnWidth = size.width * 0.6 + split.preferredSupplementaryColumnWidthFraction = 0.6 + } + } + } + } + } + func windowScene(_ windowScene: UIWindowScene, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: @escaping (Bool) -> Void) { if let url = shortcutItem.userInfo?["sub"] { VCPresenter.openRedditLink("/r/\(url)", window?.rootViewController as? UINavigationController, window?.rootViewController) @@ -1216,6 +1266,10 @@ extension AppDelegate: UIWindowSceneDelegate { if let windowScene = scene as? UIWindowScene { let window = UIWindow(windowScene: windowScene) self.window = window + + if UIDevice.current.isMac() && (connectionOptions.userActivities.first?.activityType != "settings") { + windowScene.sizeRestrictions?.minimumSize = CGSize(width: UIScreen.main.bounds.width * 0.75, height: UIScreen.main.bounds.height * 0.75) + } didFinishLaunching(window: window) /* TODO This launchedURL = launchOptions?[UIApplication.LaunchOptionsKey.url] as? URL @@ -1230,16 +1284,98 @@ extension AppDelegate: UIWindowSceneDelegate { }*/ } - if let userActivity = connectionOptions.userActivities.first { - if (userActivity.userInfo?["TYPE"] as? NSString) ?? "" == "SUBREDDIT" { - VCPresenter.openRedditLink("/r/\(userActivity.title ?? "")", window?.rootViewController as? UINavigationController, window?.rootViewController) - } else if (userActivity.userInfo?["TYPE"] as? NSString) ?? "" == "INBOX" { - VCPresenter.showVC(viewController: InboxViewController(), popupIfPossible: false, parentNavigationController: window?.rootViewController as? UINavigationController, parentViewController: window?.rootViewController) - } else if let url = userActivity.webpageURL { - _ = handleURL(url) + if #available(iOS 14, *) { + if let userActivity = connectionOptions.userActivities.first { + if connectionOptions.userActivities.first?.activityType == "settings" { + window?.rootViewController = SwipeForwardNavigationController(rootViewController: SettingsViewController()) + } else if connectionOptions.userActivities.first?.activityType == "website", let url = userActivity.userInfo?["url"] as? URL { + window?.rootViewController = SwipeForwardNavigationController(rootViewController: WebsiteViewController(url: url, subreddit: "")) + } else if connectionOptions.userActivities.first?.activityType == "subreddit", let subreddit = userActivity.userInfo?["subreddit"] as? String { + let subVC = SingleSubredditViewController(subName: subreddit, single: true) + let split = UISplitViewController(style: .doubleColumn) + split.setViewController(subVC, for: .primary) + split.setViewController(PlaceholderViewController(), for: .secondary) + let size = window?.frame.size ?? CGSize(width: UIScreen.main.bounds.width * 0.75, height: UIScreen.main.bounds.height * 0.75) + + split.preferredContentSize = size + split.minimumPrimaryColumnWidth = split.preferredContentSize.width * 0.60 + split.preferredPrimaryColumnWidthFraction = 0.60 + split.maximumPrimaryColumnWidth = UIScreen.main.bounds.width * 0.60 + + split.preferredDisplayMode = .oneBesideSecondary + split.preferredSplitBehavior = .tile + split.presentsWithGesture = false + split.showsSecondaryOnlyButton = false + + window?.rootViewController = split + } else if connectionOptions.userActivities.first?.activityType == "inbox" { + let subVC = InboxViewController() + let split = UISplitViewController(style: .doubleColumn) + split.setViewController(subVC, for: .primary) + split.setViewController(PlaceholderViewController(), for: .secondary) + let size = window?.frame.size ?? CGSize(width: UIScreen.main.bounds.width * 0.75, height: UIScreen.main.bounds.height * 0.75) + + split.preferredContentSize = size + split.minimumPrimaryColumnWidth = split.preferredContentSize.width * 0.60 + split.preferredPrimaryColumnWidthFraction = 0.60 + split.maximumPrimaryColumnWidth = UIScreen.main.bounds.width * 0.60 + + split.preferredDisplayMode = .oneBesideSecondary + split.preferredSplitBehavior = .tile + split.presentsWithGesture = false + split.showsSecondaryOnlyButton = false + + window?.rootViewController = split + } else if connectionOptions.userActivities.first?.activityType == "profile", let profile = userActivity.userInfo?["profile"] as? String { + let subVC = SwipeForwardNavigationController(rootViewController: ProfileViewController(name: profile)) + let split = UISplitViewController(style: .doubleColumn) + split.setViewController(subVC, for: .primary) + split.setViewController(PlaceholderViewController(), for: .secondary) + let size = window?.frame.size ?? CGSize(width: UIScreen.main.bounds.width * 0.75, height: UIScreen.main.bounds.height * 0.75) + + split.preferredContentSize = size + split.minimumPrimaryColumnWidth = split.preferredContentSize.width * 0.60 + split.preferredPrimaryColumnWidthFraction = 0.60 + split.maximumPrimaryColumnWidth = UIScreen.main.bounds.width * 0.60 + + split.preferredDisplayMode = .oneBesideSecondary + split.preferredSplitBehavior = .tile + split.presentsWithGesture = false + split.showsSecondaryOnlyButton = false + + window?.rootViewController = split + } else if (userActivity.userInfo?["TYPE"] as? NSString) ?? "" == "SUBREDDIT" { + VCPresenter.openRedditLink("/r/\(userActivity.title ?? "")", window?.rootViewController as? UINavigationController, window?.rootViewController) + } else if (userActivity.userInfo?["TYPE"] as? NSString) ?? "" == "INBOX" { + VCPresenter.showVC(viewController: InboxViewController(), popupIfPossible: false, parentNavigationController: window?.rootViewController as? UINavigationController, parentViewController: window?.rootViewController) + } else if let url = userActivity.webpageURL { + _ = handleURL(url) + } + } + } else { + if let userActivity = connectionOptions.userActivities.first { + if connectionOptions.userActivities.first?.activityType == "settings" { + window?.rootViewController = SwipeForwardNavigationController(rootViewController: SettingsViewController()) + } else if connectionOptions.userActivities.first?.activityType == "website", let url = userActivity.userInfo?["url"] as? URL { + window?.rootViewController = SwipeForwardNavigationController(rootViewController: WebsiteViewController(url: url, subreddit: "")) + } else if (userActivity.userInfo?["TYPE"] as? NSString) ?? "" == "SUBREDDIT" { + VCPresenter.openRedditLink("/r/\(userActivity.title ?? "")", window?.rootViewController as? UINavigationController, window?.rootViewController) + } else if (userActivity.userInfo?["TYPE"] as? NSString) ?? "" == "INBOX" { + VCPresenter.showVC(viewController: InboxViewController(), popupIfPossible: false, parentNavigationController: window?.rootViewController as? UINavigationController, parentViewController: window?.rootViewController) + } else if let url = userActivity.webpageURL { + _ = handleURL(url) + } } - } + + #if targetEnvironment(macCatalyst) + guard let windowScene = scene as? UIWindowScene else { return } + + if let titlebar = windowScene.titlebar { + titlebar.titleVisibility = .hidden + titlebar.toolbar = nil + } + #endif } } @@ -1287,3 +1423,38 @@ class NoHomebarSplitViewController: UISplitViewController { } } } + +#if targetEnvironment(macCatalyst) +extension AppDelegate: NSToolbarDelegate { + + func toolbarDefaultItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] { + let identifiers: [NSToolbarItem.Identifier] = [ + + ] + return identifiers + } + + func toolbarAllowedItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] { + return toolbarDefaultItemIdentifiers(toolbar) + } + + func toolbar(_ toolbar: NSToolbar, + itemForItemIdentifier itemIdentifier: NSToolbarItem.Identifier, + willBeInsertedIntoToolbar flag: Bool) -> NSToolbarItem? { + + var toolbarItem: NSToolbarItem? + + switch itemIdentifier { + case .toggleSidebar: + toolbarItem = NSToolbarItem(itemIdentifier: itemIdentifier) + + default: + toolbarItem = nil + } + + return toolbarItem + } + +} +#endif + diff --git a/Slide for Reddit/Assets.xcassets/AppIcon.appiconset/Contents.json b/Slide for Reddit/Assets.xcassets/AppIcon.appiconset/Contents.json index 93a583906..f0400e87c 100644 --- a/Slide for Reddit/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/Slide for Reddit/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,158 +1,208 @@ { "images" : [ { - "size" : "20x20", - "idiom" : "iphone", "filename" : "Icon-App-20x20@2x.png", - "scale" : "2x" + "idiom" : "iphone", + "scale" : "2x", + "size" : "20x20" }, { - "size" : "20x20", - "idiom" : "iphone", "filename" : "Icon-App-20x20@3x.png", - "scale" : "3x" + "idiom" : "iphone", + "scale" : "3x", + "size" : "20x20" }, { - "size" : "29x29", - "idiom" : "iphone", "filename" : "Icon-App-29x29@1x.png", - "scale" : "1x" + "idiom" : "iphone", + "scale" : "1x", + "size" : "29x29" }, { - "size" : "29x29", - "idiom" : "iphone", "filename" : "Icon-App-29x29@2x.png", - "scale" : "2x" + "idiom" : "iphone", + "scale" : "2x", + "size" : "29x29" }, { - "size" : "29x29", - "idiom" : "iphone", "filename" : "Icon-App-29x29@3x.png", - "scale" : "3x" + "idiom" : "iphone", + "scale" : "3x", + "size" : "29x29" }, { - "size" : "40x40", - "idiom" : "iphone", "filename" : "Icon-App-40x40@2x.png", - "scale" : "2x" + "idiom" : "iphone", + "scale" : "2x", + "size" : "40x40" }, { - "size" : "40x40", - "idiom" : "iphone", "filename" : "Icon-App-40x40@3x.png", - "scale" : "3x" + "idiom" : "iphone", + "scale" : "3x", + "size" : "40x40" }, { - "size" : "57x57", - "idiom" : "iphone", "filename" : "Icon-App-57x57@1x.png", - "scale" : "1x" + "idiom" : "iphone", + "scale" : "1x", + "size" : "57x57" }, { - "size" : "57x57", - "idiom" : "iphone", "filename" : "Icon-App-57x57@2x.png", - "scale" : "2x" + "idiom" : "iphone", + "scale" : "2x", + "size" : "57x57" }, { - "size" : "60x60", - "idiom" : "iphone", "filename" : "Icon-App-60x60@2x.png", - "scale" : "2x" + "idiom" : "iphone", + "scale" : "2x", + "size" : "60x60" }, { - "size" : "60x60", - "idiom" : "iphone", "filename" : "Icon-App-60x60@3x.png", - "scale" : "3x" + "idiom" : "iphone", + "scale" : "3x", + "size" : "60x60" }, { - "size" : "20x20", - "idiom" : "ipad", "filename" : "Icon-App-20x20@1x.png", - "scale" : "1x" + "idiom" : "ipad", + "scale" : "1x", + "size" : "20x20" }, { - "size" : "20x20", - "idiom" : "ipad", "filename" : "Icon-App-20x20@2x.png", - "scale" : "2x" + "idiom" : "ipad", + "scale" : "2x", + "size" : "20x20" }, { - "size" : "29x29", - "idiom" : "ipad", "filename" : "Icon-App-29x29@1x.png", - "scale" : "1x" + "idiom" : "ipad", + "scale" : "1x", + "size" : "29x29" }, { - "size" : "29x29", - "idiom" : "ipad", "filename" : "Icon-App-29x29@2x.png", - "scale" : "2x" + "idiom" : "ipad", + "scale" : "2x", + "size" : "29x29" }, { - "size" : "40x40", - "idiom" : "ipad", "filename" : "Icon-App-40x40@1x.png", - "scale" : "1x" + "idiom" : "ipad", + "scale" : "1x", + "size" : "40x40" }, { - "size" : "40x40", - "idiom" : "ipad", "filename" : "Icon-App-40x40@2x.png", - "scale" : "2x" + "idiom" : "ipad", + "scale" : "2x", + "size" : "40x40" }, { - "size" : "50x50", - "idiom" : "ipad", "filename" : "Icon-Small-50x50@1x.png", - "scale" : "1x" + "idiom" : "ipad", + "scale" : "1x", + "size" : "50x50" }, { - "size" : "50x50", - "idiom" : "ipad", "filename" : "Icon-Small-50x50@2x.png", - "scale" : "2x" + "idiom" : "ipad", + "scale" : "2x", + "size" : "50x50" }, { - "size" : "72x72", - "idiom" : "ipad", "filename" : "Icon-App-72x72@1x.png", - "scale" : "1x" + "idiom" : "ipad", + "scale" : "1x", + "size" : "72x72" }, { - "size" : "72x72", - "idiom" : "ipad", "filename" : "Icon-App-72x72@2x.png", - "scale" : "2x" + "idiom" : "ipad", + "scale" : "2x", + "size" : "72x72" }, { - "size" : "76x76", - "idiom" : "ipad", "filename" : "Icon-App-76x76@1x.png", - "scale" : "1x" + "idiom" : "ipad", + "scale" : "1x", + "size" : "76x76" }, { - "size" : "76x76", - "idiom" : "ipad", "filename" : "Icon-App-76x76@2x.png", - "scale" : "2x" + "idiom" : "ipad", + "scale" : "2x", + "size" : "76x76" }, { - "size" : "83.5x83.5", - "idiom" : "ipad", "filename" : "Icon-App-83.5x83.5@2x.png", - "scale" : "2x" + "idiom" : "ipad", + "scale" : "2x", + "size" : "83.5x83.5" }, { - "size" : "1024x1024", - "idiom" : "ios-marketing", "filename" : "slide_ios_1024.png", - "scale" : "1x" + "idiom" : "ios-marketing", + "scale" : "1x", + "size" : "1024x1024" + }, + { + "idiom" : "mac", + "scale" : "1x", + "size" : "16x16" + }, + { + "idiom" : "mac", + "scale" : "2x", + "size" : "16x16" + }, + { + "idiom" : "mac", + "scale" : "1x", + "size" : "32x32" + }, + { + "idiom" : "mac", + "scale" : "2x", + "size" : "32x32" + }, + { + "idiom" : "mac", + "scale" : "1x", + "size" : "128x128" + }, + { + "idiom" : "mac", + "scale" : "2x", + "size" : "128x128" + }, + { + "idiom" : "mac", + "scale" : "1x", + "size" : "256x256" + }, + { + "idiom" : "mac", + "scale" : "2x", + "size" : "256x256" + }, + { + "idiom" : "mac", + "scale" : "1x", + "size" : "512x512" + }, + { + "idiom" : "mac", + "scale" : "2x", + "size" : "512x512" } ], "info" : { - "version" : 1, - "author" : "xcode" + "author" : "xcode", + "version" : 1 } -} \ No newline at end of file +} diff --git a/Slide for Reddit/AsyncAlertImagePickerViewController.swift b/Slide for Reddit/AsyncAlertImagePickerViewController.swift index f220f1bb5..f2bc075a6 100644 --- a/Slide for Reddit/AsyncAlertImagePickerViewController.swift +++ b/Slide for Reddit/AsyncAlertImagePickerViewController.swift @@ -25,7 +25,7 @@ extension AlertController { func addAsyncImagePicker(flow: UICollectionView.ScrollDirection, paging: Bool, images: [URL], selection: AsyncImagePickerViewController.SelectionType? = nil) { let vc = AsyncImagePickerViewController(flow: flow, paging: paging, images: images, selection: selection) - if UIDevice.current.userInterfaceIdiom == .pad { + if UIDevice.current.respectIpadLayout() { vc.preferredContentSize.height = vc.preferredSize.height * 0.9 vc.preferredContentSize.width = vc.preferredSize.width * 0.9 } else { @@ -82,7 +82,7 @@ final class AsyncImagePickerViewController: UIViewController { } var columns: CGFloat { - return UIDevice.current.userInterfaceIdiom == .pad ? 3 : 2 + return UIDevice.current.respectIpadLayout() ? 3 : 2 } var itemSize: CGSize { diff --git a/Slide for Reddit/AutoCache.swift b/Slide for Reddit/AutoCache.swift index e4c0d686e..22cb92e00 100644 --- a/Slide for Reddit/AutoCache.swift +++ b/Slide for Reddit/AutoCache.swift @@ -39,7 +39,8 @@ public class AutoCache: NSObject { AutoCache.current = self self.subs = subs if !self.subs.isEmpty { - doCache(subs: subs, progress: { sub, post, total, _ in + let startIndex = UserDefaults.standard.integer(forKey: "CACHE_LAST_INDEX") + doCache(subs: subs, startIndex: startIndex, progress: { sub, post, total, _ in DispatchQueue.main.async { NotificationCenter.default.post(name: .autoCacheProgress, object: nil, userInfo: ["subreddit": sub, "progress": Float(post) / Float(total)]) self.cacheProgress = Float(post) / Float(total) @@ -47,6 +48,7 @@ public class AutoCache: NSObject { }, completion: { (total, failed) in DispatchQueue.main.async { AutoCache.current = nil + UserDefaults.standard.setValue(0, forKey: "CACHE_LAST_INDEX") NotificationCenter.default.post(name: .autoCacheFinished, object: nil, userInfo: ["total": total, "failed": failed]) } }) @@ -62,8 +64,8 @@ public class AutoCache: NSObject { AutoCache.current = nil } - func doCache(subs: [String], progress: @escaping (String, Int, Int, Int) -> Void, completion: @escaping (Int, Int) -> Void) { - cacheSub(0, progress: progress, completion: completion, total: 0, failed: 0) + func doCache(subs: [String], startIndex: Int, progress: @escaping (String, Int, Int, Int) -> Void, completion: @escaping (Int, Int) -> Void) { + cacheSub(startIndex, progress: progress, completion: completion, total: 0, failed: 0) } func cacheComments(_ index: Int, commentIndex: Int, currentLinks: [SubmissionObject], done: Int, failed: Int, progress: @escaping (String, Int, Int, Int) -> Void, completion: @escaping (Int, Int) -> Void) { @@ -132,6 +134,8 @@ public class AutoCache: NSObject { self.cacheSub(index + 1, progress: progress, completion: completion, total: total, failed: failed) return } + + UserDefaults.standard.setValue(index, forKey: "CACHE_LAST_INDEX") NotificationCenter.default.post(name: .autoCacheStarted, object: nil, userInfo: ["subreddit": self.subs[index]]) self.currentSubreddit = self.subs[index] diff --git a/Slide for Reddit/BottomMenuPresentationController.swift b/Slide for Reddit/BottomMenuPresentationController.swift index cd2ac2f67..3239fd4b2 100644 --- a/Slide for Reddit/BottomMenuPresentationController.swift +++ b/Slide for Reddit/BottomMenuPresentationController.swift @@ -97,7 +97,7 @@ extension BottomMenuPresentationController { let horizontalCoveragePercent: CGFloat = 0.95 // Make smaller on iPad - var width = containerView.bounds.size.width * (UIDevice.current.userInterfaceIdiom == .pad ? 0.75 : horizontalCoveragePercent) + var width = containerView.bounds.size.width * (UIDevice.current.respectIpadLayout() ? 0.75 : horizontalCoveragePercent) if width < 250 { width = containerView.bounds.size.width * horizontalCoveragePercent } @@ -147,7 +147,7 @@ class SlideInTransition: NSObject, UIViewControllerAnimatedTransitioning { guard let viewToAnimate = viewControllerToAnimate.view else { return } var offsetFrame = viewToAnimate.bounds - var width = UIScreen.main.bounds.width * (UIDevice.current.userInterfaceIdiom == .pad ? 0.75 : 0.95) + var width = UIScreen.main.bounds.width * (UIDevice.current.respectIpadLayout() ? 0.75 : 0.95) if width < 250 { width = UIScreen.main.bounds.width * 0.95 } diff --git a/Slide for Reddit/CacheSettings.swift b/Slide for Reddit/CacheSettings.swift index a8071b55f..fc4e5cee4 100644 --- a/Slide for Reddit/CacheSettings.swift +++ b/Slide for Reddit/CacheSettings.swift @@ -79,8 +79,6 @@ class CacheSettings: BubbleSettingTableViewController { var delete = UIButton() - public static var changed = false - override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { return indexPath.section == 0 ? 80 : 60 } diff --git a/Slide for Reddit/CachedTitle.swift b/Slide for Reddit/CachedTitle.swift index 493129a6e..80e88bc20 100644 --- a/Slide for Reddit/CachedTitle.swift +++ b/Slide for Reddit/CachedTitle.swift @@ -204,7 +204,9 @@ class CachedTitle { authorAttributes[.foregroundColor] = UIColor.white } - authorAttributes[.textHighlight] = TextHighlight(["url": URL(string: "/u/\(submission.author)")]) + if SettingValues.tapProfilesAndSubs || full, let authorUrl = URL(string: "/u/\(submission.author)") { + authorAttributes[.textHighlight] = TextHighlight(["url": authorUrl]) + } let authorString = NSMutableAttributedString(string: "\u{00A0}\(AccountController.formatUsername(input: submission.author, small: false) + (submission.isCakeday ? " 🎂" : ""))\u{00A0}", attributes: authorAttributes) endString.append(authorString) @@ -332,7 +334,7 @@ class CachedTitle { let attrs = [NSAttributedString.Key.font: FontGenerator.fontOfSize(size: 12, submission: true), NSAttributedString.Key.foregroundColor: colorF] as [NSAttributedString.Key: Any] - let boldString = NSMutableAttributedString(string: "r/\(submission.crosspostSubreddit ?? "")", attributes: attrs) + let boldString = NSMutableAttributedString(string: "\((submission.crosspostSubreddit ?? "").getSubredditFormatted())", attributes: attrs) let color = ColorUtil.getColorForSub(sub: submission.crosspostSubreddit ?? "") if color != ColorUtil.baseColor { @@ -420,7 +422,7 @@ class CachedTitle { attributedTitle.append(oc) } - let endString = NSMutableAttributedString(string: "r/\(submission.subreddit) • \(DateFormatter().timeSince(from: submission.created as NSDate, numericDates: true))\((submission.isEdited ? ("(edit \(DateFormatter().timeSince(from: submission.edited! as NSDate, numericDates: true)))") : "")) • ", attributes: [NSAttributedString.Key.font: FontGenerator.fontOfSize(size: 12, submission: true), NSAttributedString.Key.foregroundColor: colorF]) + let endString = NSMutableAttributedString(string: "\(submission.subreddit.getSubredditFormatted()) • \(DateFormatter().timeSince(from: submission.created as NSDate, numericDates: true))\((submission.isEdited ? ("(edit \(DateFormatter().timeSince(from: submission.edited! as NSDate, numericDates: true)))") : "")) • ", attributes: [NSAttributedString.Key.font: FontGenerator.fontOfSize(size: 12, submission: true), NSAttributedString.Key.foregroundColor: colorF]) var authorAttributes: [NSAttributedString.Key: Any] = [NSAttributedString.Key.font: FontGenerator.fontOfSize(size: 12, submission: true), NSAttributedString.Key.foregroundColor: colorF] let userColor = ColorUtil.getColorForUser(name: submission.author) @@ -501,20 +503,27 @@ class CachedTitle { iconString.append(NSAttributedString(attachment: attachment)) attrs[.baselineOffset] = (((24 - fontSize) / 2) - (titleFont.descender / 2)) } - let tapString = NSMutableAttributedString(string: " r/\(link.subreddit)", attributes: attrs) - tapString.addAttributes([.urlAction: URL(string: "https://www.reddit.com/r/\(link.subreddit)")!], range: NSRange(location: 0, length: tapString.length)) + let tapString = NSMutableAttributedString(string: " \(link.subreddit.getSubredditFormatted())", attributes: attrs) + if SettingValues.tapProfilesAndSubs || full { + tapString.addAttributes([.urlAction: URL(string: "https://www.reddit.com/r/\(link.subreddit)")!], range: NSRange(location: 0, length: tapString.length)) + } iconString.append(tapString) } else { if color != ColorUtil.baseColor { let preString = NSMutableAttributedString(string: "⬤ ", attributes: [NSAttributedString.Key.font: titleFont, NSAttributedString.Key.foregroundColor: color]) iconString = preString - let tapString = NSMutableAttributedString(string: "r/\(link.subreddit)", attributes: attrs) - tapString.addAttributes([.urlAction: URL(string: "https://www.reddit.com/r/\(link.subreddit)")!], range: NSRange(location: 0, length: tapString.length)) + let tapString = NSMutableAttributedString(string: "\(link.subreddit.getSubredditFormatted())", attributes: attrs) + if SettingValues.tapProfilesAndSubs || full { + tapString.addAttributes([.urlAction: URL(string: "https://www.reddit.com/r/\(link.subreddit)")!], range: NSRange(location: 0, length: tapString.length)) + } + iconString.append(tapString) } else { - let tapString = NSMutableAttributedString(string: "r/\(link.subreddit)", attributes: attrs) - tapString.addAttributes([.urlAction: URL(string: "https://www.reddit.com/r/\(link.subreddit)")!], range: NSRange(location: 0, length: tapString.length)) + let tapString = NSMutableAttributedString(string: "\(link.subreddit.getSubredditFormatted())", attributes: attrs) + if SettingValues.tapProfilesAndSubs || full { + tapString.addAttributes([.urlAction: URL(string: "https://www.reddit.com/r/\(link.subreddit)")!], range: NSRange(location: 0, length: tapString.length)) + } iconString = tapString } } diff --git a/Slide for Reddit/ColorUtil.swift b/Slide for Reddit/ColorUtil.swift index 6e0b66ede..24358051b 100644 --- a/Slide for Reddit/ColorUtil.swift +++ b/Slide for Reddit/ColorUtil.swift @@ -105,9 +105,8 @@ public class ColorUtil { if accent != nil { baseAccent = accent! } - if #available(iOS 13.0, *) { } else { // Re-draw views on iOS 11 and 12 - NotificationCenter.default.post(name: .onThemeChanged, object: nil) - } + + NotificationCenter.default.post(name: .onThemeChanged, object: nil) return true } @@ -301,16 +300,16 @@ public class ColorUtil { static func initializeThemes() { ColorUtil.themes.removeAll() - ColorUtil.themes.append(Theme(title: "light", displayName: "Light", foregroundColor: UIColor.white, backgroundColor: UIColor(hexString: "#e5e5e5"), navIconColor: UIColor(hexString: "#000000").withAlphaComponent(0.87), fontColor: UIColor(hexString: "#000000").withAlphaComponent(0.87), isLight: true, isCustom: false)) + ColorUtil.themes.append(Theme(title: "light", displayName: "Light", foregroundColor: UIColor.white, backgroundColor: UIColor(hexString: "#f2f2f7"), navIconColor: UIColor(hexString: "#3c3c43").withAlphaComponent(0.87), fontColor: UIColor(hexString: "#000000").withAlphaComponent(0.87), isLight: true, isCustom: false)) ColorUtil.themes.append(Theme(title: "dark", displayName: "Dark Gray", foregroundColor: UIColor(hexString: "#303030"), backgroundColor: UIColor(hexString: "#212121"), navIconColor: UIColor(hexString: "#FFFFFF").withAlphaComponent(0.87), fontColor: UIColor(hexString: "#FFFFFF").withAlphaComponent(0.87), isLight: false, isCustom: false)) - ColorUtil.themes.append(Theme(title: "black", displayName: "AMOLED Black", foregroundColor: UIColor.black, backgroundColor: UIColor.black, navIconColor: UIColor(hexString: "#FFFFFF").withAlphaComponent(0.87), fontColor: UIColor(hexString: "#FFFFFF").withAlphaComponent(0.87), isLight: false, isCustom: false)) + ColorUtil.themes.append(Theme(title: "black", displayName: "Black", foregroundColor: UIColor.black, backgroundColor: UIColor.black, navIconColor: UIColor(hexString: "#FFFFFF").withAlphaComponent(0.87), fontColor: UIColor(hexString: "#FFFFFF").withAlphaComponent(0.87), isLight: false, isCustom: false)) ColorUtil.themes.append(Theme(title: "blue", displayName: "Blue", foregroundColor: UIColor(hexString: "#37474F"), backgroundColor: UIColor(hexString: "#2F3D44"), navIconColor: UIColor(hexString: "#FFFFFF").withAlphaComponent(0.87), fontColor: UIColor(hexString: "#FFFFFF").withAlphaComponent(0.87), isLight: false, isCustom: false)) ColorUtil.themes.append(Theme(title: "sepia", displayName: "Sepia", foregroundColor: UIColor(hexString: "#e2dfd7"), backgroundColor: UIColor(hexString: "#cac5ad"), navIconColor: UIColor(hexString: "#3e3d36").withAlphaComponent(0.87), fontColor: UIColor(hexString: "#3e3d36").withAlphaComponent(0.87), isLight: false, isCustom: false)) ColorUtil.themes.append(Theme(title: "red", displayName: "Dark Red", foregroundColor: UIColor(hexString: "#402c2c"), backgroundColor: UIColor(hexString: "#312322"), navIconColor: UIColor(hexString: "#fff7ed").withAlphaComponent(0.87), fontColor: UIColor(hexString: "#fff7ed").withAlphaComponent(0.87), isLight: false, isCustom: false)) ColorUtil.themes.append(Theme(title: "deep", displayName: "Deep Purple", foregroundColor: UIColor(hexString: "#1f1e26"), backgroundColor: UIColor(hexString: "#16161C"), navIconColor: UIColor(hexString: "#FFFFFF").withAlphaComponent(0.87), fontColor: UIColor(hexString: "#FFFFFF").withAlphaComponent(0.87), isLight: false, isCustom: false)) ColorUtil.themes.append(Theme(title: "mint", displayName: "Mint Green", foregroundColor: UIColor(hexString: "#ffffff"), backgroundColor: UIColor(hexString: "#eef6e8"), navIconColor: UIColor(hexString: "#9fc675"), fontColor: UIColor(hexString: "#09360f").withAlphaComponent(0.87), isLight: true, isCustom: false)) ColorUtil.themes.append(Theme(title: "cream", displayName: "Crème", foregroundColor: UIColor(hexString: "#DCD8C2"), backgroundColor: UIColor(hexString: "#D1CDB9"), navIconColor: UIColor(hexString: "#444139").withAlphaComponent(0.87), fontColor: UIColor(hexString: "#444139").withAlphaComponent(0.87), isLight: true, isCustom: false)) - ColorUtil.themes.append(Theme(title: "acontrast", displayName: "AMOLED Black with Contrast", foregroundColor: UIColor.black, backgroundColor: UIColor(hexString: "#111010"), navIconColor: UIColor(hexString: "#FFFFFF").withAlphaComponent(0.87), fontColor: UIColor(hexString: "#FFFFFF").withAlphaComponent(0.87), isLight: false, isCustom: false)) + ColorUtil.themes.append(Theme(title: "acontrast", displayName: "Black with Contrast", foregroundColor: UIColor.black, backgroundColor: UIColor(hexString: "#111010"), navIconColor: UIColor(hexString: "#FFFFFF").withAlphaComponent(0.87), fontColor: UIColor(hexString: "#FFFFFF").withAlphaComponent(0.87), isLight: false, isCustom: false)) ColorUtil.themes.append(Theme(title: "pink", displayName: "Pink", foregroundColor: UIColor(hexString: "#FFFFFC"), backgroundColor: UIColor(hexString: "#fff5e8"), navIconColor: UIColor(hexString: "#ea8ab4"), fontColor: UIColor(hexString: "#262844").withAlphaComponent(0.87), isLight: true, isCustom: false)) ColorUtil.themes.append(Theme(title: "solarize", displayName: "Solarized", foregroundColor: UIColor(hexString: "#0C3641"), backgroundColor: UIColor(hexString: "#032B35"), navIconColor: UIColor(hexString: "#6E73C1"), fontColor: UIColor(hexString: "#839496"), isLight: false, isCustom: false)) @@ -447,7 +446,7 @@ extension UIColor { static var isLightTheme: Bool { if #available(iOS 13.0, *) { - return UITraitCollection.current.userInterfaceStyle != .dark && SettingValues.nightModeEnabled ? ColorUtil.theme.isLight : ColorUtil.nightTheme.isLight + return UITraitCollection.current.userInterfaceStyle == .dark && SettingValues.nightModeEnabled ? ColorUtil.nightTheme.isLight : ColorUtil.theme.isLight } else { return ColorUtil.swappedTheme.isLight } diff --git a/Slide for Reddit/CommentCellView.swift b/Slide for Reddit/CommentCellView.swift index 9e7133f74..c70070bbe 100644 --- a/Slide for Reddit/CommentCellView.swift +++ b/Slide for Reddit/CommentCellView.swift @@ -108,7 +108,7 @@ class CommentCellView: UICollectionViewCell, UIGestureRecognizerDelegate { iconString.append(NSAttributedString(attachment: attachment)) attrs[.baselineOffset] = (((24 - fontSize) / 2) - (titleFont.descender / 2)) } - let tapString = NSMutableAttributedString(string: " r/\(comment.subreddit)", attributes: attrs) + let tapString = NSMutableAttributedString(string: " \(comment.subreddit.getSubredditFormatted())", attributes: attrs) tapString.addAttributes([.urlAction: URL(string: "https://www.reddit.com/r/\(comment.subreddit)")!], range: NSRange(location: 0, length: tapString.length)) iconString.append(tapString) @@ -116,11 +116,11 @@ class CommentCellView: UICollectionViewCell, UIGestureRecognizerDelegate { if color != ColorUtil.baseColor { let preString = NSMutableAttributedString(string: "⬤ ", attributes: [NSAttributedString.Key.font: titleFont, NSAttributedString.Key.foregroundColor: color]) iconString = preString - let tapString = NSMutableAttributedString(string: "r/\(comment.subreddit)", attributes: attrs) + let tapString = NSMutableAttributedString(string: "\(comment.subreddit.getSubredditFormatted())", attributes: attrs) tapString.addAttributes([.urlAction: URL(string: "https://www.reddit.com/r/\(comment.subreddit)")!], range: NSRange(location: 0, length: tapString.length)) iconString.append(tapString) } else { - let tapString = NSMutableAttributedString(string: "r/\(comment.subreddit)", attributes: attrs) + let tapString = NSMutableAttributedString(string: "\(comment.subreddit.getSubredditFormatted())", attributes: attrs) tapString.addAttributes([.urlAction: URL(string: "https://www.reddit.com/r/\(comment.subreddit)")!], range: NSRange(location: 0, length: tapString.length)) iconString = tapString } diff --git a/Slide for Reddit/CommentDepthCell.swift b/Slide for Reddit/CommentDepthCell.swift index 8ef19b072..e3d53629d 100644 --- a/Slide for Reddit/CommentDepthCell.swift +++ b/Slide for Reddit/CommentDepthCell.swift @@ -747,7 +747,7 @@ class CommentDepthCell: MarginedTableViewCell, UIViewControllerPreviewingDelegat removedSubviews.forEach({ $0.removeFromSuperview() }) - if UIDevice.current.userInterfaceIdiom == .pad && (!UIApplication.shared.isSplitOrSlideOver || UIApplication.shared.isMac()) { + if UIDevice.current.respectIpadLayout() && (!UIApplication.shared.isSplitOrSlideOver || UIDevice.current.isMacReal()) { menu.addArrangedSubviews(flexSpace(), flexSpace(), flexSpace(), editButton, deleteButton, upvoteButton, downvoteButton, replyButton, moreButton, modButton) } else { menu.addArrangedSubviews(editButton, deleteButton, upvoteButton, downvoteButton, replyButton, moreButton, modButton) @@ -1342,7 +1342,7 @@ class CommentDepthCell: MarginedTableViewCell, UIViewControllerPreviewingDelegat } par.present(activityViewController, animated: true, completion: {}) })) - + if AccountController.isLoggedIn { actions.append(AlertMenuAction(title: ActionStates.isSaved(s: comment!) ? "Unsave" : "Save", icon: UIImage(sfString: SFSymbol.starFill, overrideString: "save")!.menuIcon(), action: { par.saveComment(self.comment!) @@ -1361,6 +1361,15 @@ class CommentDepthCell: MarginedTableViewCell, UIViewControllerPreviewingDelegat par.blockUser(name: self.comment!.author) })) + actions.append(AlertMenuAction(title: "Share u/\(comment!.author)'s profile", icon: UIImage(sfString: SFSymbol.xmark, overrideString: "hide")!.menuIcon(), action: { + let activityViewController = UIActivityViewController(activityItems: [URL(string: "https://www.reddit.com/u/\(self.comment!.author)") ?? URL(string: "about://blank")], applicationActivities: nil) + if let presenter = activityViewController.popoverPresentationController { + presenter.sourceView = self.moreButton + presenter.sourceRect = self.moreButton.bounds + } + par.present(activityViewController, animated: true, completion: {}) + })) + actions.append(AlertMenuAction(title: "Copy text", icon: UIImage(sfString: SFSymbol.docOnDocFill, overrideString: "copy")!.menuIcon(), action: { let alert = AlertController.init(title: "Copy text", message: nil, preferredStyle: .alert) @@ -1874,6 +1883,64 @@ class CommentDepthCell: MarginedTableViewCell, UIViewControllerPreviewingDelegat flairString = flairTitle } } + + var awardString: NSMutableAttributedString? + if !SettingValues.hideAwardsComments { + let to = 3 + if !comment.awardsDictionary.keys.isEmpty { + var awardCount = 0 + let awardDict = comment.awardsDictionary + + let values = awardDict.values + let sortedValues = values.sorted { (a, b) -> Bool in + let amountA = Int((a as? [String])?[4] ?? "0") ?? 0 + let amountB = Int((b as? [String])?[4] ?? "0") ?? 0 + + return amountA > amountB + } + for raw in sortedValues { + if let award = raw as? [String] { + awardCount += Int(award[2]) ?? 0 + } + } + + var totalAwards = 0 + var attachments = [NSTextAttachment]() + + for raw in sortedValues { + if let award = raw as? [String] { + if totalAwards == to { + break + } + + totalAwards += 1 + + let url = award[1] + if let urlAsURL = URL(string: url) { + let attachment = AsyncTextAttachmentNoLoad(imageURL: urlAsURL, delegate: nil, rounded: false, backgroundColor: UIColor.foregroundColor) + attachment.bounds = CGRect(x: 0, y: -2 + (15 * -0.5) / 2, width: 15, height: 15) + attachments.append(attachment) + } + } + } + + let awardLine = NSMutableAttributedString(string: "\n", attributes: [NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 10), NSAttributedString.Key.foregroundColor: UIColor.foregroundColor]) + + for award in attachments { + awardLine.append(NSAttributedString(attachment: award)) + awardLine.appendString(" ") + } + + if totalAwards == to { + awardLine.append(NSMutableAttributedString(string: "\(awardCount) Awards", attributes: [NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 10), NSAttributedString.Key.foregroundColor: UIColor.fontColor, .baselineOffset: -2])) + } + + awardLine.addAttributes([.urlAction: URL(string: CachedTitle.AWARD_KEY)!], range: NSRange(location: 2, length: awardLine.length - 2)) // We will catch this URL later on, start it after the newline + + awardString = awardLine + awardString?.append(NSAttributedString(string: "\u{00A0}")) // Stop tap from going to the end of the view width + } + } let pinned = NSMutableAttributedString.init(string: "\u{00A0}PINNED\u{00A0}", attributes: [NSAttributedString.Key.font: FontGenerator.boldFontOfSize(size: 12, submission: false), .badgeColor: GMColor.green500Color(), NSAttributedString.Key.foregroundColor: UIColor.white]) @@ -1924,13 +1991,6 @@ class CommentDepthCell: MarginedTableViewCell, UIViewControllerPreviewingDelegat infoString.append(spacer) infoString.append(pinned) } - - // TODO flairs and awards - /*if comment.isCakeday { - infoString.append(spacer) - let gild = NSMutableAttributedString.yy_attachmentString(withEmojiImage: UIImage(named: "cakeday")!, fontSize: boldFont.pointSize)! - infoString.append(gild) - }*/ if parent!.removed.contains(comment.id) || (!(comment.removedBy ?? "").isEmpty() && !parent!.approved.contains(comment.id)) { let attrs = [NSAttributedString.Key.font: FontGenerator.boldFontOfSize(size: 12, submission: false), NSAttributedString.Key.foregroundColor: GMColor.red500Color()] @@ -1946,9 +2006,22 @@ class CommentDepthCell: MarginedTableViewCell, UIViewControllerPreviewingDelegat infoString.append(NSMutableAttributedString.init(string: "Approved\(!(comment.approvedBy ?? "").isEmpty() ? " by \(comment.approvedBy!)":"")", attributes: attrs)) } + if let awards = awardString { + infoString.append(awards) + } + paragraphStyle.lineSpacing = 1.5 // infoString.setAttributes([NSAttributedString.Key.paragraphStyle: paragraphStyle], range: NSRange(location: 0, length: infoString.length)) + if SettingValues.showProfileImagesComments && comment.authorProfileImage != nil { + if let urlAsURL = URL(string: comment.authorProfileImage?.unescapeHTML ?? "") { + let attachment = AsyncTextAttachmentNoLoad(imageURL: urlAsURL, delegate: nil, rounded: true, backgroundColor: color) + attachment.bounds = CGRect(x: -2, y: -2, width: boldFont.pointSize + 4, height: boldFont.pointSize + 4) + infoString.insert(NSAttributedString(string: " "), at: 0) + infoString.insert(NSAttributedString(attachment: attachment), at: 0) + } + } + commentBody.tColor = ColorUtil.accentColorForSub(sub: comment.subreddit) if !isCollapsed || !SettingValues.collapseFully { title.linkTextAttributes = [NSAttributedString.Key.foregroundColor: ColorUtil.accentColorForSub(sub: comment.subreddit)] @@ -2085,8 +2158,58 @@ class CommentDepthCell: MarginedTableViewCell, UIViewControllerPreviewingDelegat } extension CommentDepthCell: TextDisplayStackViewDelegate { + func showAwardMenu() { + guard let comment = comment else { return } + let awardDict = comment.awardsDictionary + + let alertController = DragDownAlertMenu(title: "Comment awards", subtitle: "", icon: nil) + var coinTotal = 0 + + let sortedValues = awardDict.values.sorted { (a, b) -> Bool in + let amountA = Int((a as? [String])?[4] ?? "0") ?? 0 + let amountB = Int((b as? [String])?[4] ?? "0") ?? 0 + + return amountA > amountB + } + + for raw in sortedValues { + if let award = raw as? [String] { + coinTotal += Int(award[4]) ?? 0 + alertController.addView(title: "\(award[0]) x\(award[2])", icon_url: award[5], action: {() in + let alertController = DragDownAlertMenu(title: award[0], subtitle: award[3], icon: award[5]) + alertController.modalPresentationStyle = .overCurrentContext + if let window = UIApplication.shared.keyWindow, let modalVC = window.rootViewController?.presentedViewController { + if let presented = modalVC.presentedViewController { + alertController.show(presented) + } else { + alertController.show(modalVC) + } + } else if let window = UIApplication.shared.keyWindow, let root = window.rootViewController { + alertController.show(root) + } + }) + } + } + + alertController.subtitle = "\(coinTotal) coins spent" + + if #available(iOS 10.0, *) { + HapticUtility.hapticActionStrong() + } else if SettingValues.hapticFeedback { + AudioServicesPlaySystemSound(1519) + } + if let parent = parent { + alertController.show(parent) + } + } + func linkTapped(url: URL, text: String) { islink = true + if url.absoluteString == CachedTitle.AWARD_KEY { + showAwardMenu() + return + } + if !text.isEmpty { self.parent?.showSpoiler(text) } else { @@ -2097,6 +2220,11 @@ extension CommentDepthCell: TextDisplayStackViewDelegate { func linkLongTapped(url: URL) { longBlocking = true + if url.absoluteString == CachedTitle.AWARD_KEY { + showAwardMenu() + return + } + let alertController = DragDownAlertMenu(title: "Link options", subtitle: url.absoluteString, icon: url.absoluteString) alertController.addAction(title: "Share URL", icon: UIImage(sfString: SFSymbol.squareAndArrowUp, overrideString: "share")!.menuIcon()) { @@ -2503,7 +2631,7 @@ extension CommentDepthCell: UIContextMenuInteractionDelegate { } } - if UIDevice.current.userInterfaceIdiom == .pad || UIApplication.shared.isMac() { + if UIDevice.current.respectIpadLayout() || UIDevice.current.isMacReal() { if self.parent?.menuCell == self { if let parent = self.parent { let menu = self.getMoreMenu(parent) @@ -2619,6 +2747,17 @@ extension CommentDepthCell: UIContextMenuInteractionDelegate { VCPresenter.openRedditLink("https://www.reddit.com/message/compose?to=\(username)", self.parent?.navigationController, self.parent) }) + if !Subscriptions.isSubscriber("u_\(username)") { + children.append(UIAction(title: "Follow user", image: UIImage(sfString: SFSymbol.plusCircleFill, overrideString: "add")!.menuIcon()) { _ in + if let session = (UIApplication.shared.delegate as? AppDelegate)?.session { + Subscriptions.subscribe("u_\(username)", true, session: session) + DispatchQueue.main.async { + BannerUtil.makeBanner(text: "Followed \(username)", seconds: 3, context: self.parent) + } + } + }) + } + children.append(UIAction(title: "Block user", image: UIImage(sfString: SFSymbol.personCropCircleBadgeXmark, overrideString: "copy")!.menuIcon(), attributes: UIMenuElement.Attributes.destructive, handler: { [weak self] (_) in guard let self = self else { return } if let parent = self.parent { diff --git a/Slide for Reddit/CommentViewController.swift b/Slide for Reddit/CommentViewController.swift index 592a0e4b9..3bb14c213 100644 --- a/Slide for Reddit/CommentViewController.swift +++ b/Slide for Reddit/CommentViewController.swift @@ -34,20 +34,20 @@ class CommentViewController: MediaViewController, UITableViewDelegate, UITableVi func subscribe(link: SubmissionObject) { let sub = link.subreddit - let alrController = UIAlertController.init(title: "Follow r/\(sub)", message: nil, preferredStyle: .alert) + let alrController = UIAlertController.init(title: "Subscribe to \(sub.getSubredditFormatted())", message: nil, preferredStyle: .alert) if AccountController.isLoggedIn { let somethingAction = UIAlertAction(title: "Subscribe", style: UIAlertAction.Style.default, handler: { (_: UIAlertAction!) in Subscriptions.subscribe(sub, true, session: self.session!) self.subChanged = true - BannerUtil.makeBanner(text: "Subscribed to r/\(sub)", color: ColorUtil.accentColorForSub(sub: sub), seconds: 3, context: self, top: true) + BannerUtil.makeBanner(text: "Subscribed to \(sub.getSubredditFormatted())", color: ColorUtil.accentColorForSub(sub: sub), seconds: 3, context: self, top: true) }) alrController.addAction(somethingAction) } - let somethingAction = UIAlertAction(title: "Casually subscribe", style: UIAlertAction.Style.default, handler: { (_: UIAlertAction!) in + let somethingAction = UIAlertAction(title: "Follow without Subscribing", style: UIAlertAction.Style.default, handler: { (_: UIAlertAction!) in Subscriptions.subscribe(sub, false, session: self.session!) self.subChanged = true - BannerUtil.makeBanner(text: "r/\(sub) added to your subreddit list", color: ColorUtil.accentColorForSub(sub: sub), seconds: 3, context: self, top: true) + BannerUtil.makeBanner(text: "\(sub.getSubredditFormatted()) added to your subreddit list", color: ColorUtil.accentColorForSub(sub: sub), seconds: 3, context: self, top: true) }) alrController.addAction(somethingAction) @@ -92,7 +92,7 @@ class CommentViewController: MediaViewController, UITableViewDelegate, UITableVi var didDisappearCompletely = false var live = false var liveTimer = Timer() - var refreshControl: UIRefreshControl! + var refreshControl: UIRefreshControl? var tableView: UITableView! var sortButton = UIButton() @@ -881,7 +881,7 @@ class CommentViewController: MediaViewController, UITableViewDelegate, UITableVi } @objc func refresh(_ sender: AnyObject) { - self.tableView.setContentOffset(CGPoint(x: 0, y: self.tableView.contentOffset.y - (self.refreshControl!.frame.size.height)), animated: true) + self.tableView.setContentOffset(CGPoint(x: 0, y: self.tableView.contentOffset.y - (self.refreshControl?.frame.size.height ?? 0)), animated: true) session = (UIApplication.shared.delegate as! AppDelegate).session approved.removeAll() removed.removeAll() @@ -1341,17 +1341,21 @@ class CommentViewController: MediaViewController, UITableViewDelegate, UITableVi self.view.backgroundColor = UIColor.backgroundColor self.tableView.backgroundColor = UIColor.backgroundColor self.navigationController?.view.backgroundColor = UIColor.foregroundColor - refreshControl = UIRefreshControl() - refreshControl?.tintColor = UIColor.fontColor - refreshControl?.attributedTitle = NSAttributedString(string: "") - refreshControl?.addTarget(self, action: #selector(CommentViewController.refresh(_:)), for: UIControl.Event.valueChanged) + if !UIDevice.current.isMac() { + refreshControl = UIRefreshControl() + refreshControl?.tintColor = UIColor.fontColor + refreshControl?.attributedTitle = NSAttributedString(string: "") + refreshControl?.addTarget(self, action: #selector(CommentViewController.refresh(_:)), for: UIControl.Event.valueChanged) + } var top = CGFloat(64) let bottom = CGFloat(45) if #available(iOS 11.0, *) { top = 0 } tableView.contentInset = UIEdgeInsets(top: top, left: 0, bottom: bottom, right: 0) - tableView.addSubview(refreshControl!) + if let refresh = refreshControl, !UIDevice.current.isMac() { + tableView.addSubview(refresh) + } self.navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: UIBarButtonItem.Style.plain, target: nil, action: nil) @@ -1691,9 +1695,9 @@ class CommentViewController: MediaViewController, UITableViewDelegate, UITableVi fullWidthBackGestureRecognizer?.isEnabled = true cellGestureRecognizer?.isEnabled = true - refreshControl.setValue(100, forKey: "_snappingHeight") + refreshControl?.setValue(100, forKey: "_snappingHeight") - if UIScreen.main.traitCollection.userInterfaceIdiom == .pad && Int(round(self.view.bounds.width / CGFloat(320))) > 1 && false { + if UIDevice.current.respectIpadLayout() && Int(round(self.view.bounds.width / CGFloat(320))) > 1 && false { self.navigationController!.view.backgroundColor = .clear } self.isHiding = false @@ -1777,7 +1781,7 @@ class CommentViewController: MediaViewController, UITableViewDelegate, UITableVi VCPresenter.showVC(viewController: related, popupIfPossible: false, parentNavigationController: self.navigationController, parentViewController: self) } - alertController.addAction(title: "View r/\(link.subreddit)'s sidebar", icon: UIImage(sfString: SFSymbol.infoCircle, overrideString: "info")!.menuIcon()) { + alertController.addAction(title: "View \(link.subreddit.getSubredditFormatted())'s sidebar", icon: UIImage(sfString: SFSymbol.infoCircle, overrideString: "info")!.menuIcon()) { Sidebar.init(parent: self, subname: self.submission!.subreddit).displaySidebar() } @@ -2141,66 +2145,104 @@ class CommentViewController: MediaViewController, UITableViewDelegate, UITableVi } func updateToolbar() { - navigationController?.setToolbarHidden(false, animated: false) - self.isToolbarHidden = false let space = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil) - var items: [UIBarButtonItem] = [] - if !context.isEmpty() { - items.append(space) - let loadFullThreadButton = UIBarButtonItem.init(title: "Load full thread", style: .plain, target: self, action: #selector(CommentViewController.loadAll(_:))) - loadFullThreadButton.accessibilityLabel = "Load full thread" - items.append(loadFullThreadButton) - items.append(space) - } else { - let up = UIButton(buttonImage: UIImage(sfString: SFSymbol.chevronCompactUp, overrideString: "up"), toolbar: true) - up.accessibilityLabel = "Navigate up one comment thread" - up.addTarget(self, action: #selector(CommentViewController.goUp(_:)), for: UIControl.Event.touchUpInside) - let upB = UIBarButtonItem(customView: up) - - let nav = UIButton(buttonImage: UIImage(sfString: SFSymbol.safariFill, overrideString: "nav"), toolbar: true) - nav.accessibilityLabel = "Change criteria for comment thread navigation" - nav.addTarget(self, action: #selector(CommentViewController.showNavTypes(_:)), for: UIControl.Event.touchUpInside) - let navB = UIBarButtonItem(customView: nav) - - let down = UIButton(buttonImage: UIImage(sfString: SFSymbol.chevronCompactDown, overrideString: "down"), toolbar: true) - down.accessibilityLabel = "Navigate down one comment thread" - down.addTarget(self, action: #selector(CommentViewController.goDown(_:)), for: UIControl.Event.touchUpInside) - let downB = UIBarButtonItem(customView: down) - - let more = UIButton(buttonImage: UIImage.init(sfString: SFSymbol.ellipsis, overrideString: "moreh"), toolbar: true) - more.accessibilityLabel = "Post options" - more.addTarget(self, action: #selector(self.showMenu(_:)), for: UIControl.Event.touchUpInside) - moreB = UIBarButtonItem(customView: more) + if UIDevice.current.isMac() { + navigationController?.setToolbarHidden(false, animated: false) + var items = [UIBarButtonItem]() - let mod = UIButton(buttonImage: UIImage(sfString: SFSymbol.shieldLefthalfFill, overrideString: "mod"), toolbar: true) - mod.accessibilityLabel = "Moderator options" - mod.addTarget(self, action: #selector(self.showMod(_:)), for: UIControl.Event.touchUpInside) - modB = UIBarButtonItem(customView: mod) - if modLink.isEmpty() && modB.customView != nil { - modB.customView? = UIView(frame: modB.customView!.frame) + if !context.isEmpty() { + items.append(space) + let loadFullThreadButton = UIBarButtonItem.init(title: "Load full thread", style: .plain, target: self, action: #selector(CommentViewController.loadAll(_:))) + loadFullThreadButton.accessibilityLabel = "Load full thread" + items.append(loadFullThreadButton) + items.append(space) + if parent != nil && parent is PagingCommentViewController { + + parent?.toolbarItems = items + parent?.navigationController?.toolbar.barTintColor = UIColor.backgroundColor + parent?.navigationController?.toolbar.tintColor = UIColor.fontColor + } else { + toolbarItems = items + navigationController?.toolbar.barTintColor = UIColor.backgroundColor + navigationController?.toolbar.tintColor = UIColor.fontColor + } + } else { + navigationController?.setToolbarHidden(true, animated: false) + + let more = UIButton(buttonImage: UIImage.init(sfString: SFSymbol.ellipsis, overrideString: "moreh"), toolbar: true) + more.accessibilityLabel = "Post options" + more.addTarget(self, action: #selector(self.showMenu(_:)), for: UIControl.Event.touchUpInside) + moreB = UIBarButtonItem(customView: more) + + items.append(moreB) + + navigationItem.leftBarButtonItems = items + navigationController?.toolbar.barTintColor = UIColor.backgroundColor + navigationController?.toolbar.tintColor = UIColor.fontColor } - - items.append(modB) - items.append(space) - items.append(upB) - items.append(space) - items.append(navB) - items.append(space) - items.append(downB) - items.append(space) - items.append(moreB) - } - self.navigationController?.navigationBar.shadowImage = UIImage() - navigationController?.navigationBar.isTranslucent = false - - if parent != nil && parent is PagingCommentViewController { - parent?.toolbarItems = items - parent?.navigationController?.toolbar.barTintColor = UIColor.backgroundColor - parent?.navigationController?.toolbar.tintColor = UIColor.fontColor } else { - toolbarItems = items - navigationController?.toolbar.barTintColor = UIColor.backgroundColor - navigationController?.toolbar.tintColor = UIColor.fontColor + navigationController?.setToolbarHidden(false, animated: false) + self.isToolbarHidden = false + var items: [UIBarButtonItem] = [] + if !context.isEmpty() { + items.append(space) + let loadFullThreadButton = UIBarButtonItem.init(title: "Load full thread", style: .plain, target: self, action: #selector(CommentViewController.loadAll(_:))) + loadFullThreadButton.accessibilityLabel = "Load full thread" + items.append(loadFullThreadButton) + items.append(space) + } else { + let up = UIButton(buttonImage: UIImage(sfString: SFSymbol.chevronCompactUp, overrideString: "up"), toolbar: true) + up.accessibilityLabel = "Navigate up one comment thread" + up.addTarget(self, action: #selector(CommentViewController.goUp(_:)), for: UIControl.Event.touchUpInside) + let upB = UIBarButtonItem(customView: up) + + let nav = UIButton(buttonImage: UIImage(sfString: SFSymbol.safariFill, overrideString: "nav"), toolbar: true) + nav.accessibilityLabel = "Change criteria for comment thread navigation" + nav.addTarget(self, action: #selector(CommentViewController.showNavTypes(_:)), for: UIControl.Event.touchUpInside) + let navB = UIBarButtonItem(customView: nav) + + let down = UIButton(buttonImage: UIImage(sfString: SFSymbol.chevronCompactDown, overrideString: "down"), toolbar: true) + down.accessibilityLabel = "Navigate down one comment thread" + down.addTarget(self, action: #selector(CommentViewController.goDown(_:)), for: UIControl.Event.touchUpInside) + let downB = UIBarButtonItem(customView: down) + + let more = UIButton(buttonImage: UIImage.init(sfString: SFSymbol.ellipsis, overrideString: "moreh"), toolbar: true) + more.accessibilityLabel = "Post options" + more.addTarget(self, action: #selector(self.showMenu(_:)), for: UIControl.Event.touchUpInside) + moreB = UIBarButtonItem(customView: more) + + let mod = UIButton(buttonImage: UIImage(sfString: SFSymbol.shieldLefthalfFill, overrideString: "mod"), toolbar: true) + mod.accessibilityLabel = "Moderator options" + mod.addTarget(self, action: #selector(self.showMod(_:)), for: UIControl.Event.touchUpInside) + modB = UIBarButtonItem(customView: mod) + if modLink.isEmpty() && modB.customView != nil { + modB.customView? = UIView(frame: modB.customView!.frame) + } + + items.append(modB) + items.append(space) + items.append(upB) + items.append(space) + items.append(navB) + items.append(space) + items.append(downB) + items.append(space) + items.append(moreB) + } + self.navigationController?.navigationBar.shadowImage = UIImage() + navigationController?.navigationBar.isTranslucent = false + + if parent != nil && parent is PagingCommentViewController { + + parent?.toolbarItems = items + parent?.navigationController?.toolbar.barTintColor = UIColor.backgroundColor + parent?.navigationController?.toolbar.tintColor = UIColor.fontColor + } else { + toolbarItems = items + navigationController?.toolbar.barTintColor = UIColor.backgroundColor + navigationController?.toolbar.tintColor = UIColor.fontColor + } + } } @@ -2664,6 +2706,16 @@ class CommentViewController: MediaViewController, UITableViewDelegate, UITableVi } func hideUI(inHeader: Bool) { + DispatchQueue.main.asyncAfter(deadline: .now() + 0.25) { [weak self] in + guard let strongSelf = self else { return } + strongSelf.createJumpButton() + strongSelf.isHiding = false + } + + if UIDevice.current.isMac() { + return + } + isHiding = true // self.tableView.endEditing(true) if inHeadView.superview == nil { @@ -2678,13 +2730,7 @@ class CommentViewController: MediaViewController, UITableViewDelegate, UITableVi } } self.isToolbarHidden = true - - DispatchQueue.main.asyncAfter(deadline: .now() + 0.25) { [weak self] in - guard let strongSelf = self else { return } - strongSelf.createJumpButton() - strongSelf.isHiding = false - } - + if SettingValues.hideStatusBar { self.setNeedsStatusBarAppearanceUpdate() } @@ -2692,7 +2738,11 @@ class CommentViewController: MediaViewController, UITableViewDelegate, UITableVi func showUI() { (navigationController)?.setNavigationBarHidden(false, animated: true) - (navigationController)?.setToolbarHidden(false, animated: true) + + if UIDevice.current.isMac() { + return + } + if live { progressDot.layer.removeAllAnimations() let pulseAnimation = CABasicAnimation(keyPath: "transform.scale") @@ -2942,7 +2992,7 @@ class CommentViewController: MediaViewController, UITableViewDelegate, UITableVi for c in children { strings.append(c) } - try session?.getMoreChildren(strings, name: link.getId(), sort: .top, id: more.getId(), completion: { (result) -> Void in + try session?.getMoreChildren(strings, name: link.getId(), sort: sort, id: more.getId(), completion: { (result) -> Void in switch result { case .failure(let error): print(error) @@ -3172,7 +3222,7 @@ class CommentViewController: MediaViewController, UITableViewDelegate, UITableVi strings.append(c) } cell.animateMore() - try session?.getMoreChildren(strings, name: link.getId(), sort: .top, id: more.getId(), completion: { (result) -> Void in + try session?.getMoreChildren(strings, name: link.getId(), sort: sort, id: more.getId(), completion: { (result) -> Void in switch result { case .failure(let error): print(error) @@ -3265,7 +3315,7 @@ extension CommentViewController: UIGestureRecognizerDelegate { cellGestureRecognizer.delegate = self cellGestureRecognizer.maximumNumberOfTouches = 1 tableView.addGestureRecognizer(cellGestureRecognizer) - if UIDevice.current.userInterfaceIdiom != .pad { + if !UIDevice.current.respectIpadLayout() { // cellGestureRecognizer.require(toFail: tableView.panGestureRecognizer) } @@ -3290,7 +3340,7 @@ extension CommentViewController: UIGestureRecognizerDelegate { return } - if UIDevice.current.userInterfaceIdiom == .pad && SettingValues.appMode != .SINGLE { + if UIDevice.current.respectIpadLayout() && SettingValues.appMode != .SINGLE { if #available(iOS 14, *) { return } diff --git a/Slide for Reddit/ContentListingViewController.swift b/Slide for Reddit/ContentListingViewController.swift index 4fbd20c5d..d4603fc58 100644 --- a/Slide for Reddit/ContentListingViewController.swift +++ b/Slide for Reddit/ContentListingViewController.swift @@ -35,20 +35,20 @@ class ContentListingViewController: MediaViewController, UICollectionViewDelegat func subscribe(link: SubmissionObject) { let sub = link.subreddit - let alrController = UIAlertController.init(title: "Follow r/\(sub)", message: nil, preferredStyle: .alert) + let alrController = UIAlertController.init(title: "Subscribe to \(sub.getSubredditFormatted())", message: nil, preferredStyle: .alert) if AccountController.isLoggedIn { let somethingAction = UIAlertAction(title: "Subscribe", style: UIAlertAction.Style.default, handler: { (_: UIAlertAction!) in Subscriptions.subscribe(sub, true, session: self.session!) self.subChanged = true - BannerUtil.makeBanner(text: "Subscribed\nr/\(sub)", color: ColorUtil.accentColorForSub(sub: sub), seconds: 3, context: self, top: true) + BannerUtil.makeBanner(text: "Subscribed\n\(sub.getSubredditFormatted())", color: ColorUtil.accentColorForSub(sub: sub), seconds: 3, context: self, top: true) }) alrController.addAction(somethingAction) } - let somethingAction = UIAlertAction(title: "Casually subscribe", style: UIAlertAction.Style.default, handler: { (_: UIAlertAction!) in + let somethingAction = UIAlertAction(title: "Follow without subscribing", style: UIAlertAction.Style.default, handler: { (_: UIAlertAction!) in Subscriptions.subscribe(sub, false, session: self.session!) self.subChanged = true - BannerUtil.makeBanner(text: "Added\nr/\(sub) ", color: ColorUtil.accentColorForSub(sub: sub), seconds: 3, context: self, top: true) + BannerUtil.makeBanner(text: "Casually subscribed\n\(sub.getSubredditFormatted()) ", color: ColorUtil.accentColorForSub(sub: sub), seconds: 3, context: self, top: true) }) alrController.addAction(somethingAction) @@ -156,8 +156,8 @@ class ContentListingViewController: MediaViewController, UICollectionViewDelegat self.navigationController?.delegate = self if !loaded && !loading { - self.tableView.contentOffset = CGPoint(x: 0, y: -self.refreshControl.frame.size.height) - refreshControl.beginRefreshing() + self.tableView.contentOffset = CGPoint(x: 0, y: -(self.refreshControl?.frame.size.height ?? 0)) + refreshControl?.beginRefreshing() } else { self.tableView.reloadData() } @@ -193,13 +193,17 @@ class ContentListingViewController: MediaViewController, UICollectionViewDelegat self.tableView.delegate = self self.tableView.dataSource = self - refreshControl = UIRefreshControl() - refreshControl.tintColor = UIColor.fontColor - - refreshControl.attributedTitle = NSAttributedString(string: "") - refreshControl.addTarget(self, action: #selector(self.drefresh(_:)), for: UIControl.Event.valueChanged) - tableView.addSubview(refreshControl) - refreshControl.centerAnchors /==/ tableView.centerAnchors + if !UIDevice.current.isMac() { + refreshControl = UIRefreshControl() + refreshControl?.tintColor = UIColor.fontColor + + refreshControl?.attributedTitle = NSAttributedString(string: "") + refreshControl?.addTarget(self, action: #selector(self.drefresh(_:)), for: UIControl.Event.valueChanged) + if let control = self.refreshControl { + self.tableView.addSubview(control) + control.centerAnchors /==/ self.tableView.centerAnchors + } + } tableView.alwaysBounceVertical = true @@ -493,13 +497,13 @@ class ContentListingViewController: MediaViewController, UICollectionViewDelegat } } - var refreshControl: UIRefreshControl! + var refreshControl: UIRefreshControl? func refresh() { loading = true emptyStateView.isHidden = true baseData.reset() - refreshControl.beginRefreshing() + refreshControl?.beginRefreshing() flowLayout.reset(modal: presentingViewController != nil, vc: self, isGallery: false) flowLayout.invalidateLayout() tableView.reloadData() @@ -531,14 +535,18 @@ class ContentListingViewController: MediaViewController, UICollectionViewDelegat } func endAndResetRefresh() { - self.refreshControl.endRefreshing() - self.refreshControl.removeFromSuperview() - self.refreshControl = UIRefreshControl() - self.refreshControl.tintColor = UIColor.fontColor - - self.refreshControl.attributedTitle = NSAttributedString(string: "") - self.refreshControl.addTarget(self, action: #selector(self.drefresh(_:)), for: UIControl.Event.valueChanged) - self.tableView.addSubview(self.refreshControl) + if !UIDevice.current.isMac() { + self.refreshControl?.endRefreshing() + self.refreshControl?.removeFromSuperview() + self.refreshControl = UIRefreshControl() + self.refreshControl?.tintColor = UIColor.fontColor + + self.refreshControl?.attributedTitle = NSAttributedString(string: "") + self.refreshControl?.addTarget(self, action: #selector(self.drefresh(_:)), for: UIControl.Event.valueChanged) + if let control = self.refreshControl { + self.tableView.addSubview(control) + } + } } var loading: Bool = false diff --git a/Slide for Reddit/Fonts/LinkParser.swift b/Slide for Reddit/Fonts/LinkParser.swift index be02dfb71..bf0309c47 100644 --- a/Slide for Reddit/Fonts/LinkParser.swift +++ b/Slide for Reddit/Fonts/LinkParser.swift @@ -122,7 +122,9 @@ class LinkParser { } if isItalic { - let descriptor = newFont.fontDescriptor.withSymbolicTraits(UIFontDescriptor.SymbolicTraits.traitItalic) ?? newFont.fontDescriptor + var symbolicTraits = newFont.fontDescriptor.symbolicTraits + symbolicTraits.insert(UIFontDescriptor.SymbolicTraits.traitItalic) + let descriptor = newFont.fontDescriptor.withSymbolicTraits(symbolicTraits) ?? newFont.fontDescriptor newFont = UIFont(descriptor: descriptor, size: f.pointSize) } diff --git a/Slide for Reddit/ImageMediaViewController.swift b/Slide for Reddit/ImageMediaViewController.swift index fd5e5f12d..526b45f5f 100644 --- a/Slide for Reddit/ImageMediaViewController.swift +++ b/Slide for Reddit/ImageMediaViewController.swift @@ -162,6 +162,12 @@ class ImageMediaViewController: EmbeddableMediaViewController { } @objc func fullscreen(_ sender: AnyObject) { + if SettingValues.tapExitMedia { + if let parent = parent as? ModalMediaViewController { + parent.exit() + return + } + } if let strongParent = parent as? ModalMediaViewController, strongParent.fullscreen { strongParent.unFullscreen(self) } else if let strongParent = parent as? ModalMediaViewController { diff --git a/Slide for Reddit/Info.plist b/Slide for Reddit/Info.plist index 80c68a9f4..aa1feec12 100644 --- a/Slide for Reddit/Info.plist +++ b/Slide for Reddit/Info.plist @@ -504,7 +504,6 @@ UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight UISupportedInterfaceOrientations~ipad diff --git a/Slide for Reddit/LinkCellView.swift b/Slide for Reddit/LinkCellView.swift index 7acc2a69e..de2204f22 100644 --- a/Slide for Reddit/LinkCellView.swift +++ b/Slide for Reddit/LinkCellView.swift @@ -1281,11 +1281,13 @@ class LinkCellView: UICollectionViewCell, UIViewControllerPreviewingDelegate, UI videoView?.isHidden = false topVideoView?.isHidden = false sound.isHidden = true + self.updateProgress(-1, "", buffering: false) self.innerView.bringSubviewToFront(topVideoView!) self.progressDot.isHidden = true self.timeView.isHidden = true if wasPlayingAudio { + sound.setImage(UIImage(sfString: SFSymbol.speakerSlashFill, overrideString: "mute")?.getCopy(withSize: CGSize.square(size: 20), withColor: GMColor.red400Color()), for: .normal) DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { if (self.videoView?.player?.currentItem?.tracks.count ?? 1) > 1 && !VideoMediaViewController.soundLocked { do { @@ -1551,7 +1553,7 @@ class LinkCellView: UICollectionViewCell, UIViewControllerPreviewingDelegate, UI setVisibility(downvote, actions.isVotingPossible) setVisibility(hide, actions.isHideEnabled && !full) setVisibility(readLater, actions.isReadLaterEnabled) - setVisibility(save, actions.isSaveEnabled && actions.isSavePossible) + setVisibility(save, (actions.isSaveEnabled && actions.isSavePossible) || (self.parentViewController is ContentListingViewController && (self.parentViewController as? ContentListingViewController)?.baseData is CollectionsContributionLoader)) setVisibility(reply, actions.isReplyPossible && full) setVisibility(menu, actions.isMenuEnabled) setVisibility(share, actions.isShareEnabled) @@ -2018,7 +2020,7 @@ class LinkCellView: UICollectionViewCell, UIViewControllerPreviewingDelegate, UI let attrs = [NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 14), NSAttributedString.Key.foregroundColor: colorF] as [NSAttributedString.Key: Any] - let boldString = NSMutableAttributedString(string: "r/\(submission.crosspostSubreddit ?? "")", attributes: attrs) + let boldString = NSMutableAttributedString(string: "\((submission.crosspostSubreddit ?? "").getSubredditFormatted())", attributes: attrs) let color = ColorUtil.getColorForSub(sub: submission.crosspostSubreddit ?? "") if color != ColorUtil.baseColor { boldString.addAttribute(NSAttributedString.Key.foregroundColor, value: color, range: NSRange.init(location: 0, length: boldString.length)) @@ -2469,7 +2471,7 @@ class LinkCellView: UICollectionViewCell, UIViewControllerPreviewingDelegate, UI case .success(let flairs): list.append(contentsOf: flairs) DispatchQueue.main.async { - let sheet = DragDownAlertMenu(title: "r/\(self.link!.subreddit) flairs", subtitle: "", icon: nil, themeColor: ColorUtil.accentColorForSub(sub: self.link!.subreddit), full: true) + let sheet = DragDownAlertMenu(title: "\((self.link?.subreddit ?? "").getSubredditFormatted()) flairs", subtitle: "", icon: nil, themeColor: ColorUtil.accentColorForSub(sub: self.link!.subreddit), full: true) for flair in flairs { sheet.addAction(title: (flair.text.isEmpty) ? flair.name : flair.text, icon: nil, action: { @@ -3362,7 +3364,7 @@ extension LinkCellView: UIContextMenuInteractionDelegate { }) } - if UIDevice.current.userInterfaceIdiom == .pad || UIApplication.shared.isMac() { + if UIDevice.current.respectIpadLayout() || UIDevice.current.isMacReal() { return UIContextMenuConfiguration(identifier: nil, previewProvider: nil, actionProvider: { _ in return self.del?.getMoreMenu(self) }) @@ -3472,6 +3474,17 @@ extension LinkCellView: UIContextMenuInteractionDelegate { VCPresenter.openRedditLink("https://www.reddit.com/message/compose?to=\(username)", self.parentViewController?.navigationController, self.parentViewController) }) + if !Subscriptions.isSubscriber("u_\(username)") { + children.append(UIAction(title: "Follow user", image: UIImage(sfString: SFSymbol.plusCircleFill, overrideString: "add")!.menuIcon()) { _ in + if let session = (UIApplication.shared.delegate as? AppDelegate)?.session { + Subscriptions.subscribe("u_\(username)", true, session: session) + DispatchQueue.main.async { + BannerUtil.makeBanner(text: "Followed \(username)", seconds: 3, context: self.parentViewController) + } + } + }) + } + children.append(UIAction(title: "Block user", image: UIImage(sfString: SFSymbol.personCropCircleBadgeXmark, overrideString: "copy")!.menuIcon(), attributes: UIMenuElement.Attributes.destructive, handler: { [weak self] (_) in guard let self = self else { return } if let parent = self.parentViewController { diff --git a/Slide for Reddit/MainViewController.swift b/Slide for Reddit/MainViewController.swift index e971897b1..122571706 100644 --- a/Slide for Reddit/MainViewController.swift +++ b/Slide for Reddit/MainViewController.swift @@ -32,8 +32,6 @@ class MainViewController: ColorMuxPagingViewController, UINavigationControllerDe var isReload = false var readLaterBadge: BadgeSwift? public static var current: String = "" - public static var needsRestart = false - public static var needsReTheme = false public var toolbar: UIView? var tabBar: SubredditPagingTitleCollectionView! var subs: UIView? diff --git a/Slide for Reddit/MessageCellView.swift b/Slide for Reddit/MessageCellView.swift index 504c7f078..bab2d90e7 100644 --- a/Slide for Reddit/MessageCellView.swift +++ b/Slide for Reddit/MessageCellView.swift @@ -130,7 +130,7 @@ class MessageCellView: UICollectionViewCell { iconString.append(NSAttributedString(attachment: attachment)) attrs[.baselineOffset] = (((24 - fontSize) / 2) - (titleFont.descender / 2)) } - let tapString = NSMutableAttributedString(string: " r/\(message.subreddit)", attributes: attrs) + let tapString = NSMutableAttributedString(string: " \(message.subreddit.getSubredditFormatted())", attributes: attrs) tapString.addAttributes([.urlAction: URL(string: "https://www.reddit.com/r/\(message.subreddit)")!], range: NSRange(location: 0, length: tapString.length)) iconString.append(tapString) @@ -138,11 +138,11 @@ class MessageCellView: UICollectionViewCell { if color != ColorUtil.baseColor { let preString = NSMutableAttributedString(string: "⬤ ", attributes: [NSAttributedString.Key.font: titleFont, NSAttributedString.Key.foregroundColor: color]) iconString = preString - let tapString = NSMutableAttributedString(string: "r/\(message.subreddit)", attributes: attrs) + let tapString = NSMutableAttributedString(string: "\(message.subreddit.getSubredditFormatted())", attributes: attrs) tapString.addAttributes([.urlAction: URL(string: "https://www.reddit.com/r/\(message.subreddit)")!], range: NSRange(location: 0, length: tapString.length)) iconString.append(tapString) } else { - let tapString = NSMutableAttributedString(string: "r/\(message.subreddit)", attributes: attrs) + let tapString = NSMutableAttributedString(string: "\(message.subreddit.getSubredditFormatted())", attributes: attrs) tapString.addAttributes([.urlAction: URL(string: "https://www.reddit.com/r/\(message.subreddit)")!], range: NSRange(location: 0, length: tapString.length)) iconString = tapString } diff --git a/Slide for Reddit/ModLogCellView.swift b/Slide for Reddit/ModLogCellView.swift index bbe2e7464..cbb2ba918 100644 --- a/Slide for Reddit/ModLogCellView.swift +++ b/Slide for Reddit/ModLogCellView.swift @@ -91,7 +91,7 @@ class ModlogCellView: UICollectionViewCell { color = UIColor.fontColor } - let subString = NSMutableAttributedString(string: "r/\(item.subreddit)", attributes: [NSAttributedString.Key.font: FontGenerator.fontOfSize(size: 16, submission: false), NSAttributedString.Key.foregroundColor: color]) + let subString = NSMutableAttributedString(string: "\(item.subreddit.getSubredditFormatted())", attributes: [NSAttributedString.Key.font: FontGenerator.fontOfSize(size: 16, submission: false), NSAttributedString.Key.foregroundColor: color]) let infoString = NSMutableAttributedString() infoString.append(endString) diff --git a/Slide for Reddit/ModalMediaViewController.swift b/Slide for Reddit/ModalMediaViewController.swift index fd9597bc0..3196af90d 100644 --- a/Slide for Reddit/ModalMediaViewController.swift +++ b/Slide for Reddit/ModalMediaViewController.swift @@ -285,7 +285,6 @@ class ModalMediaViewController: UIViewController { panGestureRecognizer!.allowedScrollTypesMask = .continuous } panGestureRecognizer!.cancelsTouchesInView = false - view.addGestureRecognizer(panGestureRecognizer!) background = UIView() @@ -524,9 +523,9 @@ extension ModalMediaViewController: UIGestureRecognizerDelegate { } else if panGesture.state == .ended { let velocity = panGesture.velocity(in: view) - - let down = panGesture.velocity(in: view).y > 0 - if abs(velocity.y) >= 1000 || abs(self.view.frame.origin.y) > self.view.frame.size.height / 2 { + + let down = panGesture.velocity(in: view).y > 0 || viewToMove.frame.origin.y > 0 + if abs(velocity.y) >= 1000 || abs(viewToMove.frame.origin.y) > self.view.frame.size.height / (UIDevice.current.isMac() ? 4 : 2) { UIView.animate(withDuration: 0.2, animations: { viewToMove.frame.origin = CGPoint( diff --git a/Slide for Reddit/ModerationViewController.swift b/Slide for Reddit/ModerationViewController.swift index 48bdea7b9..e939a5d11 100644 --- a/Slide for Reddit/ModerationViewController.swift +++ b/Slide for Reddit/ModerationViewController.swift @@ -34,7 +34,7 @@ class ModerationViewController: TabsContentPagingViewController { } override func appearOthers() { - self.title = "r/\(subreddit)" + self.title = "\(subreddit.getSubredditFormatted())" } @objc func new(_ sender: AnyObject) { diff --git a/Slide for Reddit/NavigationHomeViewController.swift b/Slide for Reddit/NavigationHomeViewController.swift index bb2600951..2b60dee6b 100644 --- a/Slide for Reddit/NavigationHomeViewController.swift +++ b/Slide for Reddit/NavigationHomeViewController.swift @@ -75,9 +75,29 @@ class NavigationHomeViewController: UIViewController { $0.searchBarStyle = UISearchBar.Style.minimal $0.placeholder = " Search subs, posts, or profiles" $0.isTranslucent = true - $0.barStyle = .blackTranslucent + $0.barStyle = .black + if #available(iOS 13.0, *) { + $0.searchTextField.tintColor = UIColor.fontColor + $0.searchTextField.textColor = UIColor.fontColor + } else { + // Fallback on earlier versions + } $0.accessibilityLabel = "Search" $0.accessibilityHint = "Search subreddits, posts, or profiles" + + if UIDevice.current.isMac() { + if #available(iOS 13.0, *) { + $0.searchTextField.attributedPlaceholder = NSAttributedString(string: " Search subs, posts, or profiles", attributes: [.foregroundColor: UIColor.fontColor]) + $0.searchTextField.leftView?.tintColor = UIColor.fontColor + $0.searchTextField.rightView?.tintColor = UIColor.fontColor + $0.searchTextField.backgroundColor = UIColor.backgroundColor + if let clearButton = $0.searchTextField.value(forKey: "_clearButton") as? UIButton { + let templateImage = clearButton.imageView?.image?.withRenderingMode(.alwaysTemplate) + clearButton.setImage(templateImage, for: .normal) + clearButton.tintColor = UIColor.fontColor + } + } + } } var accountHeader: CurrentAccountHeaderView? @@ -112,7 +132,8 @@ class NavigationHomeViewController: UIViewController { updateAccessibility() searchBar.isUserInteractionEnabled = true NotificationCenter.default.addObserver(self, selector: #selector(onThemeChanged), name: .onThemeChanged, object: nil) - + NotificationCenter.default.addObserver(self, selector: #selector(onSubredditOrderChanged), name: .subredditOrderChanged, object: nil) + /*if let sectionIndex = tableView.sectionIndexView, let nav = (navigationController as? SwipeForwardNavigationController) { //DISABLE for now NavigationHomeViewController.edgeGesture = UIScreenEdgePanGestureRecognizer(target: nav, action: #selector(nav.handleRightSwipe(_:))) NavigationHomeViewController.edgeGesture!.edges = UIRectEdge.right @@ -123,8 +144,16 @@ class NavigationHomeViewController: UIViewController { @objc func onThemeChanged() { doViews() + + self.navigationController?.setToolbarHidden(true, animated: false) + self.navigationController?.setToolbarHidden(false, animated: false) } + @objc func onSubredditOrderChanged() { + subsSource.reload() + self.tableView.reloadData() + } + func doViews() { tableView = UITableView(frame: CGRect.zero, style: .grouped) tableView.backgroundColor = UIColor.foregroundColor @@ -226,6 +255,8 @@ class NavigationHomeViewController: UIViewController { override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) + accountHeader?.initCurrentAccount(self) + if SettingValues.autoKeyboard { // TODO enable this? searchBar.becomeFirstResponder() } @@ -278,7 +309,11 @@ class NavigationHomeViewController: UIViewController { tableView.register(SubredditCellView.classForCoder(), forCellReuseIdentifier: "search") tableView.register(SubredditCellView.classForCoder(), forCellReuseIdentifier: "profile") - view.addSubview(tableView) + if UIDevice.current.isMac() { + view.addSubviews(headerView, tableView) + } else { + view.addSubview(tableView) + } setColors(MainViewController.current) } @@ -304,7 +339,14 @@ class NavigationHomeViewController: UIViewController { searchBar.heightAnchor /==/ 50 searchBar.bottomAnchor /==/ headerView.bottomAnchor - tableView.topAnchor /==/ view.safeTopAnchor + if UIDevice.current.isMac() { + headerView.topAnchor /==/ view.safeTopAnchor + headerView.horizontalAnchors /==/ view.horizontalAnchors + tableView.topAnchor /==/ headerView.bottomAnchor + } else { + tableView.topAnchor /==/ view.safeTopAnchor + } + tableView.contentInset = UIEdgeInsets(top: 8, left: 0, bottom: 0, right: 0) tableView.horizontalAnchors /==/ view.horizontalAnchors tableView.bottomAnchor /==/ view.bottomAnchor @@ -395,7 +437,7 @@ extension NavigationHomeViewController: UITableViewDelegate, UITableViewDataSour func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { if section == 0 { - return 50 + 4 + accountHeader!.estimateHeight() + return UIDevice.current.isMac() ? 0 : 50 + 4 + (accountHeader?.estimateHeight() ?? 0) } if isSearching && section == 0 { return 0 @@ -482,7 +524,11 @@ extension NavigationHomeViewController: UITableViewDelegate, UITableViewDataSour toReturn.backgroundColor = UIColor.foregroundColor if section == 0 { - return headerView + if UIDevice.current.isMac() { + return UIView() + } else { + return headerView + } } if isSearching { switch section { @@ -642,7 +688,7 @@ extension NavigationHomeViewController: UISearchBarDelegate { do { let requestString = "https://www.reddit.com/api/subreddit_autocomplete_v2.json?always_show_media=1&api_type=json&expand_srs=1&feature=link_preview&from_detail=1&include_users=true&obey_over18=1&raw_json=1&rtj=debug&sr_detail=1&query=\(searchTerm)&include_over_18=\((AccountController.isLoggedIn && SettingValues.nsfwEnabled) ? "true" : "false")" print("Requesting \(requestString)") - task = Alamofire.request(requestString, method: .get).responseString { response in + task = AF.request(requestString, method: .get).responseString { response in do { guard let data = response.data else { return @@ -670,6 +716,9 @@ extension NavigationHomeViewController: UISearchBarDelegate { DispatchQueue.main.async { self.suggestions = self.suggestions.sorted { ($0.hasPrefix(searchTerm) ? 0 : 1) < ($1.hasPrefix(searchTerm) ? 0 : 1) } self.tableView.reloadData() + self.tableView.deselectRow(at: IndexPath(row: 0, section: 0), animated: false) + self.tableView.resignFirstResponder() + self.searchBar.becomeFirstResponder() } } } catch { @@ -694,13 +743,15 @@ extension NavigationHomeViewController: UISearchBarDelegate { DispatchQueue.main.async { self.suggestions = self.suggestions.sorted { ($0.hasPrefix(searchTerm) ? 0 : 1) < ($1.hasPrefix(searchTerm) ? 0 : 1) } self.tableView.reloadData() + self.tableView.deselectRow(at: IndexPath(row: 0, section: 0), animated: false) + self.tableView.resignFirstResponder() + self.searchBar.becomeFirstResponder() } case .failure(let error): print(error) } }) } - } func searchTableList() { @@ -895,7 +946,7 @@ class CurrentAccountHeaderView: UIView { } var forwardButton = UIButton(type: .custom).then { - $0.setImage(UIImage(sfString: UIDevice.current.userInterfaceIdiom == .pad ? .xmark : .chevronRight, overrideString: "next")!.getCopy(withSize: .square(size: 20), withColor: UIColor.fontColor), for: UIControl.State.normal) + $0.setImage(UIImage(sfString: UIDevice.current.respectIpadLayout() ? .xmark : .chevronRight, overrideString: "next")!.getCopy(withSize: .square(size: 20), withColor: UIColor.fontColor), for: UIControl.State.normal) $0.contentEdgeInsets = UIEdgeInsets(top: 7, left: 8, bottom: 7, right: 8) $0.accessibilityLabel = "Go home" } @@ -1227,7 +1278,7 @@ extension CurrentAccountHeaderView { nav.pushNextViewControllerFromRight(nil) } else { var is14Column = false - if #available(iOS 14, *), SettingValues.appMode == .SPLIT && UIDevice.current.userInterfaceIdiom == .pad { + if #available(iOS 14, *), SettingValues.appMode == .SPLIT && UIDevice.current.respectIpadLayout() { is14Column = true } if #available(iOS 14, *), self.parent?.splitViewController?.style == .doubleColumn { @@ -1242,7 +1293,7 @@ extension CurrentAccountHeaderView { UIApplication.shared.sendAction(action, to: target, from: nil, for: nil) } else { UIView.animate(withDuration: 0.3, animations: { - if (SettingValues.appMode == .MULTI_COLUMN || SettingValues.appMode == .SINGLE) && UIDevice.current.userInterfaceIdiom == .pad { + if (SettingValues.appMode == .MULTI_COLUMN || SettingValues.appMode == .SINGLE) && UIDevice.current.respectIpadLayout() { UIView.animate(withDuration: 0.5, animations: { () -> Void in self.parent?.splitViewController?.preferredDisplayMode = .primaryHidden }, completion: { (_) in diff --git a/Slide for Reddit/PagingTitleCollectionView.swift b/Slide for Reddit/PagingTitleCollectionView.swift index 1c0f1b20b..e7fdf143e 100644 --- a/Slide for Reddit/PagingTitleCollectionView.swift +++ b/Slide for Reddit/PagingTitleCollectionView.swift @@ -256,7 +256,7 @@ class SubredditTitleCollectionViewCell: UICollectionViewCell { title.adjustsFontSizeToFitWidth = true title.translatesAutoresizingMaskIntoConstraints = false - title.text = subreddit + title.text = subreddit.getSubredditFormattedShort() title.numberOfLines = 1 title.sizeToFit() sideView.backgroundColor = ColorUtil.getColorForSub(sub: subreddit) diff --git a/Slide for Reddit/PostActions.swift b/Slide for Reddit/PostActions.swift index c083a2110..9fb16ddf5 100644 --- a/Slide for Reddit/PostActions.swift +++ b/Slide for Reddit/PostActions.swift @@ -143,6 +143,16 @@ class PostActions: NSObject { cell.downvote() case .MODERATE: PostActions.showModMenu(cell, parent: parent) + case .SHARE_AUTHOR: + if let authorUrl = URL(string: "https://reddit.com/u/" + link.subreddit) { + let activityViewController: UIActivityViewController = UIActivityViewController(activityItems: [SubjectItemSource(subject: link.title.decodeHTML(), url: authorUrl)], applicationActivities: nil) + if let presenter = activityViewController.popoverPresentationController { + presenter.sourceView = cell.contentView + presenter.sourceRect = cell.contentView.bounds + } + + parent.present(activityViewController, animated: true, completion: nil) + } } } diff --git a/Slide for Reddit/PostFilter.swift b/Slide for Reddit/PostFilter.swift index 94a570a27..ed67ab1bd 100644 --- a/Slide for Reddit/PostFilter.swift +++ b/Slide for Reddit/PostFilter.swift @@ -57,18 +57,23 @@ class PostFilter { public static func containedIn(_ array: [NSString], value: String) -> Bool { for text in array { - if value.localizedCaseInsensitiveContains(String(text)) { + if regexMatch(text as String, against: value) { return true } } return false } + + public static func regexMatch(_ regex: String, against: String) -> Bool { + let pattern = try? NSRegularExpression(pattern: regex, options: .caseInsensitive) + return ((pattern?.firstMatch(in: against, options: [], range: NSRange(location: 0, length: against.length))) != nil) + } public static func matches(_ link: SubmissionObject, baseSubreddit: String, gallery: Bool) -> Bool { - let mainMatch = (PostFilter.domains.contains(where: { $0.containedIn(base: link.domain) })) || - PostFilter.profiles.contains(where: { $0.caseInsensitiveCompare(link.author) == .orderedSame }) || - PostFilter.subreddits.contains(where: { $0.caseInsensitiveCompare(link.subreddit) == .orderedSame }) || + let mainMatch = (PostFilter.domains.contains(where: { $0.containedIn(base: link.domain) || regexMatch($0 as String, against: link.domain) })) || contains(PostFilter.flairs, value: link.flair) || + containedIn(PostFilter.subreddits, value: link.subreddit) || + containedIn(PostFilter.profiles, value: link.author) || containedIn(PostFilter.selftext, value: link.htmlBody ?? "") || containedIn(PostFilter.titles, value: link.title) || (link.isNSFW && !SettingValues.nsfwEnabled) || (link.isNSFW && gallery && !(SettingValues.nsfwPreviews || SettingValues.hideNSFWCollection && Subscriptions.isCollection(baseSubreddit))) || link.hidden || History.getSeen(s: link) && SettingValues.hideSeen diff --git a/Slide for Reddit/ProfileInfoViewController.swift b/Slide for Reddit/ProfileInfoViewController.swift index 53b2223de..d68694be4 100644 --- a/Slide for Reddit/ProfileInfoViewController.swift +++ b/Slide for Reddit/ProfileInfoViewController.swift @@ -237,7 +237,7 @@ extension ProfileInfoViewController { b.addTapGestureRecognizer(action: { _ in if trophy.url != nil { var trophyURL = trophy.url!.absoluteString - if !trophyURL.contains("reddit.com") { + if !trophyURL.contains("http") { trophyURL = "https://www.reddit.com" + trophyURL } VCPresenter.presentModally(viewController: WebsiteViewController(url: URL(string: trophyURL) ?? trophy.url!, subreddit: ""), self, nil) @@ -346,6 +346,24 @@ extension ProfileInfoViewController { } extension ProfileInfoViewController: ProfileHeaderViewDelegate { + func didRequestUnFollow() { + if let session = (UIApplication.shared.delegate as? AppDelegate)?.session, let username = self.user?.name { + Subscriptions.unsubscribe("u_\(username)", session: session) + DispatchQueue.main.async { + BannerUtil.makeBanner(text: "Un-followed \(username)", seconds: 3, context: self) + } + } + } + + func didRequestFollow() { + if let session = (UIApplication.shared.delegate as? AppDelegate)?.session, let username = self.user?.name { + Subscriptions.subscribe("u_\(username)", true, session: session) + DispatchQueue.main.async { + BannerUtil.makeBanner(text: "Followed \(username)", seconds: 3, context: self) + } + } + } + func didRequestPrivateMessage() { if user == nil { return @@ -458,6 +476,8 @@ protocol ProfileHeaderViewDelegate: AnyObject { func didRequestPrivateMessage() func didRequestRemoveFriend() func didRequestAddFriend() + func didRequestUnFollow() + func didRequestFollow() func didRequestSetColor() func didRequestEditTag() } @@ -493,6 +513,7 @@ class ProfileHeaderView: UIView { var user: Account? var friendCell = UITableViewCell() + var followCell = UITableViewCell() var colorCell = UITableViewCell().then { $0.configure(text: "Set user color", imageName: "add", sfSymbolName: .eyedropperFull, imageColor: GMColor.yellow500Color()) @@ -520,7 +541,7 @@ class ProfileHeaderView: UIView { addSubviews(infoStack, trophyArea, cellStack) infoStack.addArrangedSubviews(commentKarmaLabel, postKarmaLabel) - cellStack.addArrangedSubviews(messageCell, friendCell, colorCell, tagCell) + cellStack.addArrangedSubviews(messageCell, friendCell, followCell, colorCell, tagCell) self.clipsToBounds = true @@ -549,6 +570,9 @@ class ProfileHeaderView: UIView { self.friendCell.configure(text: account?.isFriend ?? false ? "Remove friend" : "Add friend", imageName: "profile", sfSymbolName: account?.isFriend ?? false ? SFSymbol.personBadgeMinusFill : SFSymbol.personBadgePlusFill, imageColor: GMColor.yellow500Color()) + let isFollower = Subscriptions.isSubscriber("u_\(account?.name ?? "")") + self.followCell.configure(text: isFollower ? "Stop following and unsubscribe" : "Follow and Subscribe", imageName: "add", sfSymbolName: isFollower ? SFSymbol.minusCircleFill : SFSymbol.plusCircleFill, imageColor: GMColor.yellow500Color()) + postKarmaLabel.attributedText = { let attrs = [NSAttributedString.Key.font: FontGenerator.boldFontOfSize(size: 16, submission: true)] let attributedString = NSMutableAttributedString(string: "\(account?.linkKarma.delimiter ?? "0")", attributes: attrs) @@ -570,6 +594,7 @@ class ProfileHeaderView: UIView { cellStack.horizontalAnchors /==/ horizontalAnchors messageCell.heightAnchor /==/ 50 + followCell.heightAnchor /==/ 50 friendCell.heightAnchor /==/ 50 tagCell.heightAnchor /==/ 50 colorCell.heightAnchor /==/ 50 @@ -581,11 +606,26 @@ class ProfileHeaderView: UIView { friendCell.addTapGestureRecognizer { [weak self] (_) in guard let strongSelf = self else { return } if strongSelf.user?.isFriend ?? false { + strongSelf.friendCell.configure(text: "Add friend", imageName: "profile", sfSymbolName: SFSymbol.personBadgePlusFill, imageColor: GMColor.yellow500Color()) strongSelf.delegate?.didRequestRemoveFriend() } else { + strongSelf.friendCell.configure(text: "Remove friend", imageName: "profile", sfSymbolName: SFSymbol.personBadgeMinusFill, imageColor: GMColor.yellow500Color()) strongSelf.delegate?.didRequestAddFriend() } } + + followCell.addTapGestureRecognizer { [weak self] (_) in + guard let strongSelf = self else { return } + let isFollower = Subscriptions.isSubscriber("u_\(strongSelf.user?.name ?? "")") + + if !isFollower { + strongSelf.delegate?.didRequestFollow() + } else { + strongSelf.delegate?.didRequestUnFollow() + } + + strongSelf.followCell.configure(text: !isFollower ? "Stop following and unsubscribe" : "Follow and Subscribe", imageName: "add", sfSymbolName: !isFollower ? SFSymbol.minusCircleFill : SFSymbol.plusCircleFill, imageColor: GMColor.yellow500Color()) + } messageCell.addTapGestureRecognizer { [weak self] (_) in guard let strongSelf = self else { return } strongSelf.delegate?.didRequestPrivateMessage() diff --git a/Slide for Reddit/ProfileViewController.swift b/Slide for Reddit/ProfileViewController.swift index 25e4d9bf9..5a3bb2754 100644 --- a/Slide for Reddit/ProfileViewController.swift +++ b/Slide for Reddit/ProfileViewController.swift @@ -97,6 +97,7 @@ class ProfileViewController: TabsContentPagingViewController { let vc = ProfileInfoViewController(accountNamed: user) vc.modalPresentationStyle = .custom vc.transitioningDelegate = currentAccountTransitioningManager + vc.profile = self present(vc, animated: true) } @@ -126,8 +127,12 @@ class ProfileViewController: TabsContentPagingViewController { extension ProfileViewController: TabsContentPagingViewControllerDelegate { func shouldUpdateButtons() { - if currentIndex >= 1 { - let current = content[currentIndex - 1] + var offset = 1 + if name != AccountController.currentName { + offset = 0 + } + if currentIndex >= offset { + let current = content[currentIndex - offset] if current == .comments || current == .submitted || current == .overview { navigationItem.rightBarButtonItems = [ moreB!, sortB!] } else { @@ -156,7 +161,7 @@ extension ProfileViewController: ColorPickerViewDelegate { } else { let alertController = UIAlertController(title: "\n\n\n\n\n\n\n\n", message: nil, preferredStyle: UIAlertController.Style.actionSheet) let margin: CGFloat = 10.0 - let rect = CGRect(x: margin, y: margin, width: UIScreen.main.traitCollection.userInterfaceIdiom == .pad ? 314 - margin * 4.0: alertController.view.bounds.size.width - margin * 4.0, height: 150) + let rect = CGRect(x: margin, y: margin, width: UIDevice.current.respectIpadLayout() ? 314 - margin * 4.0: alertController.view.bounds.size.width - margin * 4.0, height: 150) let MKColorPicker = ColorPickerView.init(frame: rect) MKColorPicker.delegate = self MKColorPicker.colors = GMPalette.allColor() diff --git a/Slide for Reddit/RedditObjects/CommentObject.swift b/Slide for Reddit/RedditObjects/CommentObject.swift index cb0b0f508..52f9880e7 100644 --- a/Slide for Reddit/RedditObjects/CommentObject.swift +++ b/Slide for Reddit/RedditObjects/CommentObject.swift @@ -46,6 +46,7 @@ class CommentObject: RedditObject { public var scoreHidden: Bool = false public var submissionTitle: String = "" public var subreddit: String = "" + public var authorProfileImage: String? public var voteDirection: Bool = false static func thingToCommentOrMore(thing: Thing, depth: Int) -> RedditObject? { @@ -97,6 +98,7 @@ class CommentObject: RedditObject { self.parentID = model.parentID self.permalink = model.permalink self.removalNote = model.removalNote + self.authorProfileImage = model.authorProfileImage self.removalReason = model.removalReason self.removedBy = model.removedBy @@ -120,6 +122,7 @@ class CommentObject: RedditObject { self.isSaved = comment.saved self.markdownBody = comment.body self.removalReason = comment.baseJson["ban_note"] as? String ?? "" + self.authorProfileImage = comment.baseJson["profile_img"] as? String self.removalNote = comment.baseJson["mod_note"] as? String ?? "" self.removedBy = comment.baseJson["banned_by"] as? String ?? "" self.isRemoved = !(self.removedBy ?? "").isEmpty() @@ -257,6 +260,7 @@ extension CommentObject: Cacheable { commentModel.approvedBy = self.approvedBy commentModel.author = self.author + commentModel.authorProfileImage = self.authorProfileImage commentModel.awardsJSON = self.awardsJSON commentModel.controversality = Int64(self.controversality) commentModel.created = self.created diff --git a/Slide for Reddit/ReplyViewController.swift b/Slide for Reddit/ReplyViewController.swift index 236ef501d..7004c829f 100644 --- a/Slide for Reddit/ReplyViewController.swift +++ b/Slide for Reddit/ReplyViewController.swift @@ -576,7 +576,7 @@ class ReplyViewController: MediaViewController, UITextViewDelegate { }) let requestString = "https://oauth.reddit.com/r/\(subreddit)/api/link_flair_v2.json" - Alamofire.request(requestString, method: .get, headers: ["Authorization": "bearer \(token.accessToken)"]).responseString { [weak self] response in + AF.request(requestString, method: .get, headers: ["Authorization": "bearer \(token.accessToken)"]).responseString { [weak self] response in guard let self = self else { return } do { guard let data = response.data else { @@ -1292,7 +1292,7 @@ class ReplyViewController: MediaViewController, UITextViewDelegate { } var alertController: UIAlertController? - var session: Session? + var session: reddift.Session? func getSubmissionEdited(_ name: String) { DispatchQueue.main.async { diff --git a/Slide for Reddit/SFSymbolsEnum.swift b/Slide for Reddit/SFSymbolsEnum.swift index ba549003b..48c74a704 100644 --- a/Slide for Reddit/SFSymbolsEnum.swift +++ b/Slide for Reddit/SFSymbolsEnum.swift @@ -1598,6 +1598,9 @@ public enum SFSymbol: String { /// 􀘲 case bubbleLeftAndBubbleRightFill = "bubble.left.and.bubble.right.fill" + + /// 􀪨 + case arrowUpAndPersonRectanglePortrait = "arrow.up.and.person.rectangle.portrait" /// 􀌫 case bubbleLeftFill = "bubble.left.fill" diff --git a/Slide for Reddit/SearchViewController.swift b/Slide for Reddit/SearchViewController.swift index 22665dc80..d86fa198d 100644 --- a/Slide for Reddit/SearchViewController.swift +++ b/Slide for Reddit/SearchViewController.swift @@ -95,7 +95,7 @@ class SearchViewController: ContentListingViewController { self.refreshControl?.beginRefreshing() }) base.getData(reload: true) - self.navigationItem.titleView = self.setTitle(title: self.search, subtitle: "r/\(self.sub)") + self.navigationItem.titleView = self.setTitle(title: self.search, subtitle: "\(self.sub.getSubredditFormatted())") } } }, inputPlaceholder: "Edit your search...", inputValue: self.search, inputIcon: UIImage(sfString: SFSymbol.pencil, overrideString: "edit")!.menuIcon(), textRequired: true, exitOnAction: true) diff --git a/Slide for Reddit/SettingValues.swift b/Slide for Reddit/SettingValues.swift index 733d84ea9..0e2456be7 100644 --- a/Slide for Reddit/SettingValues.swift +++ b/Slide for Reddit/SettingValues.swift @@ -135,6 +135,8 @@ class SettingValues { public static let pref_commentLimit = "COMMENT_LIMIT" public static let pref_submissionLimit = "SUBMISSION_LIMIT" public static let pref_hideAwards = "HIDE_AWARDS_v2" + public static let pref_hideAwardsComments = "HIDE_AWARDS_COMMENTS_V2" + public static let pref_showProfileImagesComments = "SHOW_PROFILE_IMAGES_COMMENTS" public static let pref_subredditIcons = "SUBREDDIT_ICONS" public static let pref_streamVideos = "STREAM_VIDEOS" public static let pref_fullWidthHeaderCells = "FULL_WIDTH_HEADER_CELLS" @@ -148,6 +150,8 @@ class SettingValues { public static let pref_coloredFlairs = "COLORED_FLAIRS" public static let pref_showFlairs = "SHOW_FLAIRS" public static let pref_desktopMode = "DESKTOP_MODE" + public static let pref_tapProfilesAndSubs = "TAP_PROFILES_AND_SUBS" + public static let pref_tapExitMedia = "TAP_EXIT_MEDIA" public static let BROWSER_INTERNAL = "internal" public static let BROWSER_SAFARI_INTERNAL_READABILITY = "readability" @@ -283,6 +287,7 @@ class SettingValues { public static var disable13Popup = true public static var thumbTag = true public static var hideAwards = false + public static var hideAwardsComments = false public static var streamVideos = true public static var fullWidthHeaderCells = false public static var disablePopupIpad = false @@ -293,6 +298,9 @@ class SettingValues { public static var coloredFlairs = false public static var showFlairs = true public static var desktopMode = false + public static var tapExitMedia = true + public static var tapProfilesAndSubs = false + public static var showProfileImagesComments = false public static var commentLimit = 95 public static var submissionLimit = 13 @@ -492,15 +500,18 @@ class SettingValues { } public static func initialize() { - let pad = UIDevice.current.userInterfaceIdiom == .pad + let pad = UIDevice.current.respectIpadLayout() let settings = UserDefaults.standard SettingValues.saveNSFWHistory = settings.bool(forKey: SettingValues.pref_saveNSFWHistory) SettingValues.reduceColor = settings.object(forKey: SettingValues.pref_reduceColor) == nil ? true : settings.bool(forKey: SettingValues.pref_reduceColor) SettingValues.saveHistory = settings.object(forKey: SettingValues.pref_saveHistory) == nil ? true : settings.bool(forKey: SettingValues.pref_saveHistory) - let columns = 2 // TODO - Maybe calculate per device? + var columns = 2 // TODO - Maybe calculate per device? + if UIDevice.current.isMac() { + columns = 1 + } SettingValues.multiColumnCount = settings.object(forKey: SettingValues.pref_multiColumnCount) == nil ? columns : settings.integer(forKey: SettingValues.pref_multiColumnCount) - SettingValues.portraitMultiColumnCount = settings.object(forKey: SettingValues.pref_portraitMultiColumnCount) == nil ? (UIDevice.current.userInterfaceIdiom == .pad ? 2 : 1) : settings.integer(forKey: SettingValues.pref_portraitMultiColumnCount) + SettingValues.portraitMultiColumnCount = settings.object(forKey: SettingValues.pref_portraitMultiColumnCount) == nil ? (UIDevice.current.respectIpadLayout() ? 2 : 1) : settings.integer(forKey: SettingValues.pref_portraitMultiColumnCount) SettingValues.galleryCount = settings.object(forKey: SettingValues.pref_galleryCount) == nil ? columns : settings.integer(forKey: SettingValues.pref_galleryCount) SettingValues.highlightOp = settings.object(forKey: SettingValues.pref_highlightOp) == nil ? true : settings.bool(forKey: SettingValues.pref_highlightOp) @@ -532,8 +543,8 @@ class SettingValues { } } - SettingValues.desktopMode = settings.object(forKey: SettingValues.pref_desktopMode) == nil ? UIApplication.shared.isMac() : settings.bool(forKey: SettingValues.pref_desktopMode) - SettingValues.desktopMode = SettingValues.desktopMode && (UIDevice.current.userInterfaceIdiom == .pad || UIApplication.shared.isMac()) // Only enable this on Mac or iPad + SettingValues.desktopMode = settings.object(forKey: SettingValues.pref_desktopMode) == nil ? UIDevice.current.isMac() : settings.bool(forKey: SettingValues.pref_desktopMode) + SettingValues.desktopMode = SettingValues.desktopMode && (UIDevice.current.respectIpadLayout() || UIDevice.current.isMacReal()) // Only enable this on Mac or iPad SettingValues.scrollSidebar = settings.object(forKey: SettingValues.pref_scrollSidebar) == nil ? true : settings.bool(forKey: SettingValues.pref_scrollSidebar) @@ -586,10 +597,15 @@ class SettingValues { SettingValues.disable13Popup = false // REMOVE this setting settings.bool(forKey: SettingValues.pref_disable13Popup) SettingValues.streamVideos = settings.object(forKey: SettingValues.pref_streamVideos) == nil ? true : settings.bool(forKey: SettingValues.pref_streamVideos) SettingValues.fullWidthHeaderCells = settings.bool(forKey: SettingValues.pref_fullWidthHeaderCells) + if UIDevice.current.isMac() { + SettingValues.fullWidthHeaderCells = true + } SettingValues.gfycatAPI = settings.object(forKey: SettingValues.pref_gfycatAPI) == nil ? true : settings.bool(forKey: SettingValues.pref_gfycatAPI) SettingValues.imageFlairs = settings.object(forKey: SettingValues.pref_imageFlairs) == nil ? true : settings.bool(forKey: SettingValues.pref_imageFlairs) SettingValues.coloredFlairs = settings.object(forKey: SettingValues.pref_coloredFlairs) == nil ? true : settings.bool(forKey: SettingValues.pref_coloredFlairs) SettingValues.showFlairs = settings.object(forKey: SettingValues.pref_showFlairs) == nil ? true : settings.bool(forKey: SettingValues.pref_showFlairs) + + SettingValues.tapProfilesAndSubs = settings.object(forKey: SettingValues.pref_tapProfilesAndSubs) == nil ? true : settings.bool(forKey: SettingValues.pref_tapProfilesAndSubs) SettingValues.subredditIcons = settings.object(forKey: SettingValues.pref_subredditIcons) == nil ? true : settings.bool(forKey: SettingValues.pref_subredditIcons) SettingValues.disablePopupIpad = settings.bool(forKey: SettingValues.pref_disablePopupIpad) @@ -633,6 +649,9 @@ class SettingValues { SettingValues.disableBanner = settings.bool(forKey: SettingValues.pref_disableBanner) SettingValues.newIndicator = settings.bool(forKey: SettingValues.pref_newIndicator) SettingValues.hideAwards = settings.bool(forKey: SettingValues.pref_hideAwards) + SettingValues.hideAwardsComments = settings.object(forKey: SettingValues.pref_hideAwardsComments) == nil ? true : settings.bool(forKey: SettingValues.pref_hideAwardsComments) + SettingValues.showProfileImagesComments = settings.bool(forKey: SettingValues.pref_showProfileImagesComments) + SettingValues.tapExitMedia = settings.bool(forKey: SettingValues.pref_tapExitMedia) SettingValues.dataSavingEnabled = settings.bool(forKey: SettingValues.pref_dataSavingEnabled) SettingValues.dataSavingDisableWiFi = settings.bool(forKey: SettingValues.pref_dataSavingDisableWifi) @@ -642,7 +661,8 @@ class SettingValues { SettingValues.saveButton = settings.object(forKey: SettingValues.pref_saveButton) == nil ? true : settings.bool(forKey: SettingValues.pref_saveButton) SettingValues.readLaterButton = settings.object(forKey: SettingValues.pref_readLaterButton) == nil ? true : settings.bool(forKey: SettingValues.pref_readLaterButton) SettingValues.hideButton = settings.bool(forKey: SettingValues.pref_hideButton) - SettingValues.nightModeEnabled = settings.bool(forKey: SettingValues.pref_nightMode) + SettingValues.nightModeEnabled = settings.object(forKey: SettingValues.pref_nightMode) == nil ? true : settings.bool(forKey: SettingValues.pref_nightMode) + SettingValues.nightStart = settings.object(forKey: SettingValues.pref_nightStartH) == nil ? 9 : settings.integer(forKey: SettingValues.pref_nightStartH) SettingValues.nightStartMin = settings.object(forKey: SettingValues.pref_nightStartH) == nil ? 0 : settings.integer(forKey: SettingValues.pref_nightStartM) SettingValues.nightEnd = settings.object(forKey: SettingValues.pref_nightStartH) == nil ? 5 : settings.integer(forKey: SettingValues.pref_nightEndH) @@ -658,7 +678,7 @@ class SettingValues { SettingValues.abbreviateScores = settings.object(forKey: SettingValues.pref_abbreviateScores) == nil ? true : settings.bool(forKey: SettingValues.pref_abbreviateScores) SettingValues.scoreInTitle = settings.bool(forKey: SettingValues.pref_scoreInTitle) SettingValues.commentsInTitle = settings.bool(forKey: SettingValues.pref_commentsInTitle) - SettingValues.appMode = AppMode.init(rawValue: settings.string(forKey: SettingValues.pref_appMode) ?? (pad ? "multi" : "single")) ?? (pad ? .SPLIT : .SINGLE) + SettingValues.appMode = AppMode.init(rawValue: settings.string(forKey: SettingValues.pref_appMode) ?? (UIDevice.current.isMac() ? "triple" : (pad ? "multi" : "single"))) ?? (UIDevice.current.isMac() ? .TRIPLE_MULTI_COLUMN : (pad ? .SPLIT : .SINGLE)) SettingValues.hideSeen = settings.bool(forKey: SettingValues.pref_hideSeen) SettingValues.postViewMode = PostViewType.init(rawValue: settings.string(forKey: SettingValues.pref_postViewMode) ?? "card") ?? .CARD @@ -767,6 +787,7 @@ class SettingValues { case READ_LATER = "readlater" case SHARE_CONTENT = "sharecontent" case SHARE_REDDIT = "sharereddit" + case SHARE_AUTHOR = "shareauthor" case CHROME = "openchrome" case SAFARI = "opensafari" case FILTER = "filter" @@ -804,7 +825,7 @@ class SettingValues { } public static func getMenuNone() -> [PostOverflowAction] { - let menu = UserDefaults.standard.stringArray(forKey: "postMenu") ?? ["profile", "sub", "moderate", "report", "block", "save", "crosspost", "readlater", "sharecontent", "sharereddit", "openchrome", "opensafari", "filter", "copy", "hide"] + let menu = UserDefaults.standard.stringArray(forKey: "postMenu") ?? ["profile", "sub", "moderate", "report", "block", "save", "crosspost", "readlater", "sharecontent", "sharereddit", "shareauthor", "openchrome", "opensafari", "filter", "copy", "hide"] var toReturn = [PostOverflowAction]() for item in menu { toReturn.append(PostOverflowAction(rawValue: item)!) @@ -823,12 +844,12 @@ class SettingValues { if link == nil { return "Subreddit" } - return "r/\(link!.subreddit)" + return "\(link!.subreddit.getSubredditFormatted())" case .SUBSCRIBE: if link == nil { return "Subscribe" } - return "Subscribe to r/\(link!.subreddit)" + return "Subscribe to \(link!.subreddit.getSubredditFormatted())" case .REPORT: return "Report content" case .BLOCK: @@ -846,6 +867,8 @@ class SettingValues { return "Share content link" case .SHARE_REDDIT: return "Share reddit link" + case .SHARE_AUTHOR: + return "Share author profile" case .CHROME: return "Open in Chrome" case .SAFARI: @@ -890,6 +913,8 @@ class SettingValues { return UIImage(sfString: SFSymbol.squareAndArrowUp, overrideString: "share")!.menuIcon() case .SHARE_REDDIT: return UIImage(sfString: SFSymbol.bubbleLeftAndBubbleRightFill, overrideString: "comments")!.menuIcon() + case .SHARE_AUTHOR: + return UIImage(sfString: SFSymbol.arrowUpAndPersonRectanglePortrait, overrideString: "share")!.menuIcon() case .CHROME: return UIImage(sfString: SFSymbol.link, overrideString: "link")!.menuIcon() case .SAFARI: @@ -1279,12 +1304,13 @@ class SettingValues { } public enum AppMode: String { - public static let cases: [AppMode] = [.SPLIT, .SINGLE, .MULTI_COLUMN] + public static let cases: [AppMode] = UIDevice.current.isMac() ? [.SPLIT, .SINGLE, .MULTI_COLUMN, .TRIPLE_MULTI_COLUMN] : [.SPLIT, .SINGLE, .MULTI_COLUMN] case SPLIT = "split" case SINGLE = "single" case MULTI_COLUMN = "multi" - + case TRIPLE_MULTI_COLUMN = "triple" + func getTitle() -> String { switch self { case .SPLIT: @@ -1293,17 +1319,21 @@ class SettingValues { return "Single list" case .MULTI_COLUMN: return "Multi-column mode" + case .TRIPLE_MULTI_COLUMN: + return "Multi-column with comments" } } func getDescription() -> String { switch self { case .SPLIT: - return "Displays submissions on the left and comments on the right (requires an iPad)" + return "Displays submissions on the left and comments on the right" case .SINGLE: return "Single column display of submissions" case .MULTI_COLUMN: return "Multiple column display of submissions" + case .TRIPLE_MULTI_COLUMN: + return "Multiple column display of submissions with comments on the right" } } } diff --git a/Slide for Reddit/SettingsAudio.swift b/Slide for Reddit/SettingsAudio.swift index aa936e523..569e31ef4 100644 --- a/Slide for Reddit/SettingsAudio.swift +++ b/Slide for Reddit/SettingsAudio.swift @@ -61,10 +61,10 @@ class SettingsAudio: BubbleSettingTableViewController { muteModalVideoSwitch = UISwitch().then { $0.onTintColor = ColorUtil.baseAccent - $0.isOn = SettingValues.muteVideosInModal + $0.isOn = !SettingValues.muteVideosInModal } muteModalVideoSwitch.addTarget(self, action: #selector(SettingsAudio.switchIsChanged(_:)), for: UIControl.Event.valueChanged) - muteModalVideoCell.textLabel?.text = "Always start videos muted" + muteModalVideoCell.textLabel?.text = "Play video sound when opening full-screen" muteModalVideoCell.accessoryView = muteModalVideoSwitch muteModalVideoCell.textLabel?.numberOfLines = 0 muteModalVideoCell.selectionStyle = UITableViewCell.SelectionStyle.none @@ -74,7 +74,7 @@ class SettingsAudio: BubbleSettingTableViewController { $0.isOn = SettingValues.modalVideosRespectHardwareMuteSwitch } modalVideoFollowsMuteSwitchSwitch.addTarget(self, action: #selector(SettingsAudio.switchIsChanged(_:)), for: UIControl.Event.valueChanged) - modalVideoFollowsMuteSwitchCell.textLabel?.text = "Start videos muted if your device is muted" + modalVideoFollowsMuteSwitchCell.textLabel?.text = "Respect device mute switch" modalVideoFollowsMuteSwitchCell.accessoryView = modalVideoFollowsMuteSwitchSwitch modalVideoFollowsMuteSwitchCell.textLabel?.numberOfLines = 0 modalVideoFollowsMuteSwitchCell.selectionStyle = UITableViewCell.SelectionStyle.none @@ -84,7 +84,7 @@ class SettingsAudio: BubbleSettingTableViewController { $0.isOn = SettingValues.muteYouTube } muteYTSwitch.addTarget(self, action: #selector(SettingsAudio.switchIsChanged(_:)), for: UIControl.Event.valueChanged) - muteYTCell.textLabel?.text = "Always start YouTube videos muted" + muteYTCell.textLabel?.text = "Mute YouTube videos" muteYTCell.accessoryView = muteYTSwitch muteYTCell.textLabel?.numberOfLines = 0 muteYTCell.selectionStyle = UITableViewCell.SelectionStyle.none @@ -116,7 +116,7 @@ class SettingsAudio: BubbleSettingTableViewController { func refresh() { muteInlineVideoSwitch.isOn = SettingValues.muteInlineVideos - muteModalVideoSwitch.isOn = SettingValues.muteVideosInModal + muteModalVideoSwitch.isOn = !SettingValues.muteVideosInModal modalVideoFollowsMuteSwitchSwitch.isOn = SettingValues.modalVideosRespectHardwareMuteSwitch self.tableView.reloadData() @@ -148,7 +148,7 @@ private extension SettingsAudio { case muteInlineVideoSwitch: SettingValues.muteInlineVideos = changed.isOn case muteModalVideoSwitch: - SettingValues.muteVideosInModal = changed.isOn + SettingValues.muteVideosInModal = !changed.isOn case modalVideoFollowsMuteSwitchSwitch: SettingValues.modalVideosRespectHardwareMuteSwitch = changed.isOn case muteYTSwitch: diff --git a/Slide for Reddit/SettingsBackup.swift b/Slide for Reddit/SettingsBackup.swift index 98b95c5b5..5f55ed578 100644 --- a/Slide for Reddit/SettingsBackup.swift +++ b/Slide for Reddit/SettingsBackup.swift @@ -14,9 +14,6 @@ import SDWebImage import UIKit class SettingsBackup: BubbleSettingTableViewController { - - static var changed = false - var restore: UITableViewCell = InsetCell(style: .subtitle, reuseIdentifier: nil) var backup: UITableViewCell = InsetCell(style: .subtitle, reuseIdentifier: nil) diff --git a/Slide for Reddit/SettingsComments.swift b/Slide for Reddit/SettingsComments.swift index 4b922b3aa..922f9a408 100644 --- a/Slide for Reddit/SettingsComments.swift +++ b/Slide for Reddit/SettingsComments.swift @@ -24,6 +24,16 @@ class SettingsComments: BubbleSettingTableViewController, ColorPickerViewDelegat var wideIndicator = UISwitch().then { $0.onTintColor = ColorUtil.baseAccent } + + var hideAwardsCell: UITableViewCell = InsetCell() + var hideAwards = UISwitch().then { + $0.onTintColor = ColorUtil.baseAccent + } + + var showProfilesCell: UITableViewCell = InsetCell(style: .subtitle, reuseIdentifier: "profile") + var showProfiles = UISwitch().then { + $0.onTintColor = ColorUtil.baseAccent + } var floatingJumpCell: UITableViewCell = InsetCell(style: .subtitle, reuseIdentifier: "jump") @@ -64,6 +74,12 @@ class SettingsComments: BubbleSettingTableViewController, ColorPickerViewDelegat } else if changed == wideIndicator { SettingValues.wideIndicators = changed.isOn UserDefaults.standard.set(changed.isOn, forKey: SettingValues.pref_widerIndicators) + } else if changed == hideAwards { + SettingValues.hideAwards = changed.isOn + UserDefaults.standard.set(changed.isOn, forKey: SettingValues.pref_hideAwardsComments) + } else if changed == showProfiles { + SettingValues.showProfileImagesComments = changed.isOn + UserDefaults.standard.set(changed.isOn, forKey: SettingValues.pref_showProfileImagesComments) } else if changed == hideAutomod { SettingValues.hideAutomod = changed.isOn UserDefaults.standard.set(changed.isOn, forKey: SettingValues.pref_hideAutomod) @@ -93,11 +109,11 @@ class SettingsComments: BubbleSettingTableViewController, ColorPickerViewDelegat override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { tableView.deselectRow(at: indexPath, animated: true) - if indexPath.section == 1 && indexPath.row == 0 { + if indexPath.section == 2 && indexPath.row == 0 { showAuthorChooser() - } else if indexPath.section == 1 && indexPath.row == 1 { + } else if indexPath.section == 2 && indexPath.row == 1 { showDepthChooser() - } else if indexPath.section == 0 && indexPath.row == 2 { + } else if indexPath.section == 1 && indexPath.row == 2 { showJumpChooser() } } @@ -226,7 +242,7 @@ class SettingsComments: BubbleSettingTableViewController, ColorPickerViewDelegat let alertController = UIAlertController(title: "\n\n\n\n\n\n\n\n", message: nil, preferredStyle: UIAlertController.Style.actionSheet) let margin: CGFloat = 10.0 - let rect = CGRect(x: margin, y: margin, width: UIScreen.main.traitCollection.userInterfaceIdiom == .pad ? 314 - margin * 4.0: alertController.view.bounds.size.width - margin * 4.0, height: 150) + let rect = CGRect(x: margin, y: margin, width: UIDevice.current.respectIpadLayout() ? 314 - margin * 4.0: alertController.view.bounds.size.width - margin * 4.0, height: 150) let MKColorPicker = ColorPickerView.init(frame: rect) MKColorPicker.delegate = self MKColorPicker.colors = GMPalette.allColor() @@ -279,7 +295,13 @@ class SettingsComments: BubbleSettingTableViewController, ColorPickerViewDelegat self.view.backgroundColor = UIColor.backgroundColor // set the title self.title = "Comments settings" - self.headers = ["Comments page", "Comment display", "Comment interaction"] + self.headers = ["Profiles and Awards", "Comments page", "Comment display", "Comment interaction"] + + createCell(hideAwardsCell, hideAwards, isOn: SettingValues.hideAwardsComments, text: "Hide Reddit awards") + createCell(showProfilesCell, showProfiles, isOn: SettingValues.showProfileImagesComments, text: "Show profile images") + showProfilesCell.detailTextLabel?.textColor = UIColor.fontColor + showProfilesCell.detailTextLabel?.numberOfLines = 0 + showProfilesCell.detailTextLabel?.text = "Experimental" createCell(disableNavigationBarCell, disableNavigationBar, isOn: SettingValues.disableNavigationBar, text: "Disable comment navigation toolbar") createCell(fullscreenImageCell, fullscreenImage, isOn: !SettingValues.commentFullScreen, text: "Crop the lead banner image") @@ -348,26 +370,32 @@ class SettingsComments: BubbleSettingTableViewController, ColorPickerViewDelegat override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { switch indexPath.section { case 0: + switch indexPath.row { + case 0: return self.hideAwardsCell + case 1: return self.showProfilesCell + default: fatalError("Unkown row in section 0") + } + case 1: switch indexPath.row { case 0: return self.fullscreenImageCell case 1: return self.hideAutomodCell case 2: return self.floatingJumpCell - default: fatalError("Unkown row in section 0") + default: fatalError("Unkown row in section 1") } - case 1: + case 2: switch indexPath.row { case 0: return self.authorThemeCell case 1: return self.themeColorCell case 2: return self.wideIndicatorCell case 3: return self.highlightOpCell - default: fatalError("Unknown row in section 1") + default: fatalError("Unknown row in section 2") } - case 2: + case 3: switch indexPath.row { case 0: return self.collapseDefaultCell case 1: return self.collapseFullyCell case 2: return self.swapLongPressCell - default: fatalError("Unknown row in section 2") + default: fatalError("Unknown row in section 3") } default: fatalError("Unknown section") } @@ -376,9 +404,10 @@ class SettingsComments: BubbleSettingTableViewController, ColorPickerViewDelegat override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { switch section { - case 0: return 3 - case 1: return 4 - case 2: return 3 + case 0: return 2 + case 1: return 3 + case 2: return 4 + case 3: return 3 default: fatalError("Unknown number of sections") } } diff --git a/Slide for Reddit/SettingsContentFilters.swift b/Slide for Reddit/SettingsContentFilters.swift index 6cbaa2398..47a73271d 100644 --- a/Slide for Reddit/SettingsContentFilters.swift +++ b/Slide for Reddit/SettingsContentFilters.swift @@ -140,7 +140,8 @@ class SettingsContentFilters: BubbleSettingTableViewController, UISearchBarDeleg self.view.backgroundColor = UIColor.backgroundColor // set the title - self.title = "Filters" + self.navigationItem.titleView = setTitle(title: "Content Filters", subtitle: "Tip: you can use Regex in filter fields") + self.headers = ["Submission domain filters", "Submission body text filters", "Submission title filters", "Submission author filters", "Subreddit filters", "Submission flair filters"] setupSearchBar(domainEnter, "Add new domain filter") diff --git a/Slide for Reddit/SettingsCustomTheme.swift b/Slide for Reddit/SettingsCustomTheme.swift index 11aa7c4cd..fce15d7c9 100644 --- a/Slide for Reddit/SettingsCustomTheme.swift +++ b/Slide for Reddit/SettingsCustomTheme.swift @@ -147,7 +147,8 @@ class SettingsCustomTheme: UITableViewController { colorString += (self.foregroundColor.toHexString() + self.backgroundColor.toHexString() + self.fontColor.toHexString() + self.navIconColor.toHexString() + ColorUtil.baseColor.toHexString() + ColorUtil.baseAccent.toHexString() + "#" + String(self.statusbarEnabled)).addPercentEncoding UserDefaults.standard.set(colorString, forKey: "Theme+" + (self.themeText ?? today_string)) UserDefaults.standard.synchronize() - SettingsTheme.needsRestart = true + + NotificationCenter.default.post(name: .settingsThemeNeedsRestart, object: nil) ColorUtil.initializeThemes() self.dismiss(animated: true, completion: nil) @@ -171,10 +172,11 @@ class SettingsCustomTheme: UITableViewController { UserDefaults.standard.synchronize() if isCurrentTheme { _ = ColorUtil.doInit() - MainViewController.needsReTheme = true } ColorUtil.initializeThemes() - SettingsTheme.needsRestart = true + + NotificationCenter.default.post(name: .settingsThemeNeedsRestart, object: nil) + self.delegate?.themeSaved() self.dismiss(animated: true, completion: nil) } @@ -301,7 +303,7 @@ class SettingsCustomTheme: UITableViewController { } override func viewWillDisappear(_ animated: Bool) { - SubredditReorderViewController.changed = true + NotificationCenter.default.post(name: .subNeedsReload, object: nil) } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { diff --git a/Slide for Reddit/SettingsDonate.swift b/Slide for Reddit/SettingsDonate.swift index 800c09325..4f187728c 100644 --- a/Slide for Reddit/SettingsDonate.swift +++ b/Slide for Reddit/SettingsDonate.swift @@ -16,9 +16,6 @@ import SDWebImage import UIKit class SettingsDonate: UIViewController, MFMailComposeViewControllerDelegate { - - static var changed = false - override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) } diff --git a/Slide for Reddit/SettingsFont.swift b/Slide for Reddit/SettingsFont.swift index 3f2083f0b..daf416fb9 100644 --- a/Slide for Reddit/SettingsFont.swift +++ b/Slide for Reddit/SettingsFont.swift @@ -77,7 +77,9 @@ class SettingsFont: BubbleSettingTableViewController { SettingValues.postFontOffset = size UserDefaults.standard.set(size, forKey: SettingValues.pref_postFontSize) UserDefaults.standard.synchronize() - SubredditReorderViewController.changed = true + + NotificationCenter.default.post(name: .cellsNeedReDraw, object: nil) + CachedTitle.titleFont = FontGenerator.fontOfSize(size: CachedTitle.baseFontSize, submission: true) FontGenerator.initialize() refresh() @@ -500,7 +502,7 @@ extension SettingsFont { CachedTitle.titleFont = FontGenerator.fontOfSize(size: 18, submission: true) CachedTitle.titleFontSmall = FontGenerator.fontOfSize(size: 14, submission: true) SingleSubredditViewController.cellVersion += 1 - MainViewController.needsReTheme = true + NotificationCenter.default.post(name: .cellsNeedReDraw, object: nil) if let nav = self.navigationController as? SwipeForwardNavigationController { nav.fullWidthBackGestureRecognizer.isEnabled = true } diff --git a/Slide for Reddit/SettingsGeneral.swift b/Slide for Reddit/SettingsGeneral.swift index e4a5f64e9..0282ffc2d 100644 --- a/Slide for Reddit/SettingsGeneral.swift +++ b/Slide for Reddit/SettingsGeneral.swift @@ -7,6 +7,7 @@ // import Anchorage +import CloudKit import reddift import RLBAlertsPickers import SDCAlertView @@ -14,6 +15,13 @@ import UIKit import UserNotifications class SettingsGeneral: BubbleSettingTableViewController { + /** + Corresponds to USR_DOMAIN in info.plist, which derives its value + from USR_DOMAIN in the pbxproj build settings. Default is `ccrama.me`. + */ + lazy var USR_DOMAIN: String = { + return Bundle.main.object(forInfoDictionaryKey: "USR_DOMAIN") as! String + }() var hideFAB: InsetCell = InsetCell(style: .subtitle, reuseIdentifier: "hidefab") var scrubUsername: InsetCell = InsetCell.init(style: .subtitle, reuseIdentifier: "scrub") @@ -34,6 +42,7 @@ class SettingsGeneral: BubbleSettingTableViewController { var commentSorting: InsetCell = InsetCell.init(style: .subtitle, reuseIdentifier: "comment") var searchSorting: InsetCell = InsetCell.init(style: .subtitle, reuseIdentifier: "search") var notifications: InsetCell = InsetCell.init(style: .subtitle, reuseIdentifier: "notif") + var debugiCloud: InsetCell = InsetCell.init(style: .subtitle, reuseIdentifier: "debugicloud") var hideFABSwitch = UISwitch().then { $0.onTintColor = ColorUtil.baseAccent } @@ -79,7 +88,7 @@ class SettingsGeneral: BubbleSettingTableViewController { @objc func switchIsChanged(_ changed: UISwitch) { if changed == showPagesSwitch { - MainViewController.needsRestart = true + NotificationCenter.default.post(name: .subNeedsReload, object: nil) SettingValues.showPages = changed.isOn UserDefaults.standard.set(changed.isOn, forKey: SettingValues.pref_showPages) } else if changed == autoKeyboardSwitch { @@ -100,7 +109,8 @@ class SettingsGeneral: BubbleSettingTableViewController { } else if changed == hideFABSwitch { SettingValues.hiddenFAB = !changed.isOn UserDefaults.standard.set(!changed.isOn, forKey: SettingValues.pref_hiddenFAB) - SubredditReorderViewController.changed = true + + NotificationCenter.default.post(name: .subNeedsReload, object: nil) doDisables() } else if changed == hapticFeedback { SettingValues.hapticFeedback = !changed.isOn @@ -136,7 +146,7 @@ class SettingsGeneral: BubbleSettingTableViewController { } else if changed == pinToolbarSwitch { SettingValues.dontHideTopBar = !changed.isOn UserDefaults.standard.set(!changed.isOn, forKey: SettingValues.pref_pinToolbar) - SubredditReorderViewController.changed = true + NotificationCenter.default.post(name: .tabBarsChanged, object: nil) if SettingValues.dontHideTopBar { self.totallyCollapse.contentView.alpha = 0.5 self.totallyCollapse.isUserInteractionEnabled = false @@ -178,7 +188,7 @@ class SettingsGeneral: BubbleSettingTableViewController { override func loadView() { super.loadView() - headers = ["Subreddits", "Auto-Hide", "Interaction", "Notifications", "Sorting", "Loading limits"] + headers = ["Subreddits", "Auto-Hide", "Interaction", "Notifications", "Sorting", "Loading limits", "Debug"] // set the title self.title = "General" @@ -198,6 +208,11 @@ class SettingsGeneral: BubbleSettingTableViewController { createCell(alwaysShowHeader, alwaysShowHeaderSwitch, isOn: SettingValues.alwaysShowHeader, text: "Show subreddit header") createCell(scrollSidebar, scrollSidebarSwitch, isOn: SettingValues.scrollSidebar, text: "Reset sidebar automatically") + createCell(debugiCloud, nil, isOn: false, text: "Tap to test Slide's iCloud connection") + self.debugiCloud.detailTextLabel?.text = "Any errors will be copied to your clipboard" + self.debugiCloud.detailTextLabel?.textColor = UIColor.fontColor + self.debugiCloud.detailTextLabel?.numberOfLines = 0 + self.alwaysShowHeader.detailTextLabel?.text = "When off, scrolling up past the first post will display the header" self.alwaysShowHeader.detailTextLabel?.textColor = UIColor.fontColor self.alwaysShowHeader.detailTextLabel?.numberOfLines = 0 @@ -363,7 +378,7 @@ class SettingsGeneral: BubbleSettingTableViewController { } override func numberOfSections(in tableView: UITableView) -> Int { - return 6 + return 7 } func doDisables() { @@ -401,32 +416,37 @@ class SettingsGeneral: BubbleSettingTableViewController { case 0: cell = self.pinToolbar case 1: cell = self.totallyCollapse case 2: cell = self.fullyHideNavbar - default: fatalError("Unknown row in section 0") + default: fatalError("Unknown row in section 1") } case 2: switch indexPath.row { case 0: cell = self.hapticFeedback case 1: cell = self.scrollSidebar // case 1: return self.matchSilence - default: fatalError("Unknown row in section 0") + default: fatalError("Unknown row in section 2") } case 3: switch indexPath.row { case 0: cell = self.notifications - default: fatalError("Unknown row in section 1") + default: fatalError("Unknown row in section 3") } case 4: switch indexPath.row { case 0: cell = self.postSorting case 1: cell = self.commentSorting case 2: cell = self.searchSorting - default: fatalError("Unknown row in section 2") + default: fatalError("Unknown row in section 4") } case 5: switch indexPath.row { case 0: cell = self.postLimit case 1: cell = self.commentLimit - default: fatalError("Unknown row in section 2") + default: fatalError("Unknown row in section 5") + } + case 6: + switch indexPath.row { + case 0: cell = debugiCloud + default: fatalError("Unknown row in section 6") } default: fatalError("Unknown section") } @@ -536,12 +556,54 @@ class SettingsGeneral: BubbleSettingTableViewController { showMenuComments(tableView.cellForRow(at: indexPath)) } else if indexPath.section == 4 && indexPath.row == 2 { showMenuSearch(tableView.cellForRow(at: indexPath)) + } else if indexPath.section == 6 && indexPath.row == 0 { + doDebugiCloud() + } + } + + func doDebugiCloud() { + let privateDatabase = CKContainer(identifier: "iCloud.\(USR_DOMAIN).redditslide").privateCloudDatabase + + let query = CKQuery(recordType: CKRecord.RecordType(stringLiteral: "collections"), predicate: NSPredicate(value: true)) + privateDatabase.perform(query, inZoneWith: nil) { (records, error) in + if error != nil { + DispatchQueue.main.async { + BannerUtil.makeBanner(text: "Slide can't connect to iCloud. The error has been copied to your clipboard", color: GMColor.red500Color(), seconds: 4, context: self) + } + let pasteboard = UIPasteboard.general + pasteboard.string = error?.localizedDescription ?? error.debugDescription + } else { + if let unwrappedRecord = records?[0] { + if let object = unwrappedRecord.object(forKey: "data_xml") as? String { + if let data = object.data(using: String.Encoding.utf8) { + do { + let dict = try PropertyListSerialization.propertyList(from: data, options: PropertyListSerialization.ReadOptions.mutableContainersAndLeaves, format: nil) as? NSMutableDictionary + DispatchQueue.main.async { + BannerUtil.makeBanner(text: "Slide successfully connected to iCloud", color: GMColor.green500Color(), seconds: 4, context: self) + } + return + } catch { + DispatchQueue.main.async { + BannerUtil.makeBanner(text: "Slide can't connect to iCloud. The error has been copied to your clipboard", color: GMColor.red500Color(), seconds: 4, context: self) + } + let pasteboard = UIPasteboard.general + pasteboard.string = "Error: Could not deserialize list" + } + } + } + } else { + DispatchQueue.main.async { + BannerUtil.makeBanner(text: "Slide can't connect to iCloud. The error has been copied to your clipboard", color: GMColor.red500Color(), seconds: 4, context: self) + } + let pasteboard = UIPasteboard.general + pasteboard.string = "Error: No records found" + } + } } - } override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - let pad = UIDevice.current.userInterfaceIdiom == .pad + let pad = UIDevice.current.respectIpadLayout() switch section { case 0: return 4 + (!pad ? 1 : 0) case 1: return 3 @@ -549,6 +611,7 @@ class SettingsGeneral: BubbleSettingTableViewController { case 3: return 1 case 4: return 3 case 5: return 2 + case 6: return 1 default: fatalError("Unknown number of sections") } } diff --git a/Slide for Reddit/SettingsGestures.swift b/Slide for Reddit/SettingsGestures.swift index 9542aa80e..65fb5e1c2 100644 --- a/Slide for Reddit/SettingsGestures.swift +++ b/Slide for Reddit/SettingsGestures.swift @@ -14,6 +14,11 @@ class SettingsGestures: BubbleSettingTableViewController { var disableBanner = UISwitch().then { $0.onTintColor = ColorUtil.baseAccent } + + var tapExitMediaCell: UITableViewCell = InsetCell.init(style: UITableViewCell.CellStyle.subtitle, reuseIdentifier: "tapmedia") + var tapExitMedia = UISwitch().then { + $0.onTintColor = ColorUtil.baseAccent + } var forceTouchSubmissionCell: UITableViewCell = InsetCell.init(style: UITableViewCell.CellStyle.subtitle, reuseIdentifier: "3dsubmission") @@ -42,7 +47,11 @@ class SettingsGestures: BubbleSettingTableViewController { if changed == disableBanner { SettingValues.disableBanner = changed.isOn UserDefaults.standard.set(changed.isOn, forKey: SettingValues.pref_disableBanner) - SubredditReorderViewController.changed = true + + NotificationCenter.default.post(name: .subNeedsReload, object: nil) + } else if changed == tapExitMedia { + SettingValues.tapExitMedia = changed.isOn + UserDefaults.standard.set(changed.isOn, forKey: SettingValues.pref_tapExitMedia) } UserDefaults.standard.synchronize() @@ -61,8 +70,8 @@ class SettingsGestures: BubbleSettingTableViewController { UserDefaults.standard.synchronize() self.commentGesturesCell.detailTextLabel?.text = SettingValues.commentGesturesMode.description() self.updateCells() - SplitMainViewController.needsReTheme = true - MainViewController.needsReTheme = true + + NotificationCenter.default.post(name: .subNeedsReload, object: nil) } } alertController.show(self) @@ -80,8 +89,8 @@ class SettingsGestures: BubbleSettingTableViewController { UserDefaults.standard.synchronize() self.submissionGesturesCell.detailTextLabel?.text = SettingValues.submissionGestureMode.description() self.updateCells() - SplitMainViewController.needsReTheme = true - MainViewController.needsReTheme = true + + NotificationCenter.default.post(name: .subNeedsReload, object: nil) } } alertController.show(self) @@ -168,7 +177,7 @@ class SettingsGestures: BubbleSettingTableViewController { UserDefaults.standard.set(action.rawValue, forKey: SettingValues.pref_submissionActionForceTouch) } - SubredditReorderViewController.changed = true + NotificationCenter.default.post(name: .subNeedsReload, object: nil) UserDefaults.standard.synchronize() self.updateCells() } @@ -196,7 +205,7 @@ class SettingsGestures: BubbleSettingTableViewController { self.view.backgroundColor = UIColor.backgroundColor // set the title self.title = "Gestures" - self.headers = ["Submissions", "Comments", "Main view edge shortcut"] + self.headers = ["Submissions", "Comments", "Media"] createCell(submissionGesturesCell, nil, isOn: false, text: "Submission gestures mode") self.submissionGesturesCell.detailTextLabel?.textColor = UIColor.fontColor self.submissionGesturesCell.detailTextLabel?.lineBreakMode = .byWordWrapping @@ -211,6 +220,13 @@ class SettingsGestures: BubbleSettingTableViewController { self.disableBannerCell.detailTextLabel?.numberOfLines = 0 self.disableBannerCell.detailTextLabel?.text = "Enabling this will open comments when clicking on the submission banner image" self.disableBannerCell.contentView.backgroundColor = UIColor.foregroundColor + + createCell(tapExitMediaCell, tapExitMedia, isOn: SettingValues.tapExitMedia, text: "Close media views by clicking or tapping") + self.tapExitMediaCell.detailTextLabel?.textColor = UIColor.fontColor + self.tapExitMediaCell.detailTextLabel?.lineBreakMode = .byWordWrapping + self.tapExitMediaCell.detailTextLabel?.numberOfLines = 0 + self.tapExitMediaCell.detailTextLabel?.text = "Disables tap for 'fullscreen' mode, allows for exiting media while using a mouse" + self.tapExitMediaCell.contentView.backgroundColor = UIColor.foregroundColor createCell(commentGesturesCell, nil, isOn: false, text: "Comment gestures mode") self.commentGesturesCell.detailTextLabel?.textColor = UIColor.fontColor @@ -362,7 +378,7 @@ class SettingsGestures: BubbleSettingTableViewController { default: fatalError("Unknown row in section 0") } case 2: - return self.sideShortcutActionCell + return self.tapExitMediaCell default: fatalError("Unknown section") } @@ -408,7 +424,8 @@ public class GesturePreviewCell: InsetCell { SettingValues.commentActionLeftRight = action UserDefaults.standard.set(action.rawValue, forKey: SettingValues.pref_commentActionLeftRight) UserDefaults.standard.synchronize() - MainViewController.needsReTheme = true + + NotificationCenter.default.post(name: .subNeedsReload, object: nil) self.parentController?.updateCells() } })) @@ -418,7 +435,8 @@ public class GesturePreviewCell: InsetCell { SettingValues.commentActionLeftLeft = action UserDefaults.standard.set(action.rawValue, forKey: SettingValues.pref_commentActionLeftLeft) UserDefaults.standard.synchronize() - MainViewController.needsReTheme = true + + NotificationCenter.default.post(name: .subNeedsReload, object: nil) self.parentController?.updateCells() } })) @@ -428,7 +446,8 @@ public class GesturePreviewCell: InsetCell { SettingValues.commentActionRightLeft = action UserDefaults.standard.set(action.rawValue, forKey: SettingValues.pref_commentActionRightLeft) UserDefaults.standard.synchronize() - MainViewController.needsReTheme = true + + NotificationCenter.default.post(name: .subNeedsReload, object: nil) self.parentController?.updateCells() } })) @@ -437,7 +456,8 @@ public class GesturePreviewCell: InsetCell { SettingValues.commentActionRightRight = action UserDefaults.standard.set(action.rawValue, forKey: SettingValues.pref_commentActionRightRight) UserDefaults.standard.synchronize() - MainViewController.needsReTheme = true + + NotificationCenter.default.post(name: .subNeedsReload, object: nil) self.parentController?.updateCells() } })) @@ -446,9 +466,9 @@ public class GesturePreviewCell: InsetCell { self.showActionSub { (action) in SettingValues.submissionActionLeft = action UserDefaults.standard.set(action.rawValue, forKey: SettingValues.pref_submissionActionLeft) - SubredditReorderViewController.changed = true UserDefaults.standard.synchronize() - MainViewController.needsReTheme = true + + NotificationCenter.default.post(name: .subNeedsReload, object: nil) self.parentController?.updateCells() } })) @@ -457,9 +477,9 @@ public class GesturePreviewCell: InsetCell { self.showActionSub { (action) in SettingValues.submissionActionRight = action UserDefaults.standard.set(action.rawValue, forKey: SettingValues.pref_submissionActionRight) - SubredditReorderViewController.changed = true UserDefaults.standard.synchronize() - MainViewController.needsReTheme = true + + NotificationCenter.default.post(name: .subNeedsReload, object: nil) self.parentController?.updateCells() } })) diff --git a/Slide for Reddit/SettingsLayout.swift b/Slide for Reddit/SettingsLayout.swift index 5a91bfe24..2344c9061 100644 --- a/Slide for Reddit/SettingsLayout.swift +++ b/Slide for Reddit/SettingsLayout.swift @@ -112,6 +112,11 @@ class SettingsLayout: BubbleSettingTableViewController { var more = UISwitch().then { $0.onTintColor = ColorUtil.baseAccent } + + var tapCell: UITableViewCell = InsetCell() + var tap = UISwitch().then { + $0.onTintColor = ColorUtil.baseAccent + } var shareCell: UITableViewCell = InsetCell() var share = UISwitch().then { @@ -165,6 +170,10 @@ class SettingsLayout: BubbleSettingTableViewController { } else if changed == more { SettingValues.menuButton = changed.isOn UserDefaults.standard.set(changed.isOn, forKey: SettingValues.pref_moreButton) + } else if changed == tap { + SettingValues.tapProfilesAndSubs = changed.isOn + UserDefaults.standard.set(changed.isOn, forKey: SettingValues.pref_tapProfilesAndSubs) + CachedTitle.titles.removeAll() } else if changed == infoBelowTitle { SettingValues.infoBelowTitle = changed.isOn UserDefaults.standard.set(changed.isOn, forKey: SettingValues.pref_infoBelowTitle) @@ -222,7 +231,9 @@ class SettingsLayout: BubbleSettingTableViewController { UserDefaults.standard.set(changed.isOn, forKey: SettingValues.pref_reduceElevation) } SingleSubredditViewController.cellVersion += 1 - MainViewController.needsReTheme = true + + NotificationCenter.default.post(name: .cellsNeedReDraw, object: nil) + UserDefaults.standard.synchronize() doDisables() doLink() @@ -341,7 +352,8 @@ class SettingsLayout: BubbleSettingTableViewController { self.doLink() tableView.reloadData() self.cardModeCell.detailTextLabel?.text = SettingValues.postViewMode.rawValue.capitalize() - MainViewController.needsReTheme = true + + NotificationCenter.default.post(name: .cellsNeedReDraw, object: nil) } alertController.addAction(title: "Large card view", icon: UIImage(named: "card")!.menuIcon()) { @@ -353,7 +365,8 @@ class SettingsLayout: BubbleSettingTableViewController { self.doLink() tableView.reloadData() self.cardModeCell.detailTextLabel?.text = SettingValues.postViewMode.rawValue.capitalize() - MainViewController.needsReTheme = true + + NotificationCenter.default.post(name: .cellsNeedReDraw, object: nil) } alertController.addAction(title: "Centered Image large card view", icon: UIImage(named: "centeredimage")!.menuIcon()) { @@ -365,7 +378,8 @@ class SettingsLayout: BubbleSettingTableViewController { self.doLink() tableView.reloadData() self.cardModeCell.detailTextLabel?.text = SettingValues.postViewMode.rawValue.capitalize() - MainViewController.needsReTheme = true + + NotificationCenter.default.post(name: .cellsNeedReDraw, object: nil) } alertController.addAction(title: "Compact list view", icon: UIImage(named: "compact")!.menuIcon()) { @@ -377,7 +391,8 @@ class SettingsLayout: BubbleSettingTableViewController { self.doLink() tableView.reloadData() self.cardModeCell.detailTextLabel?.text = SettingValues.postViewMode.rawValue.capitalize() - MainViewController.needsReTheme = true + + NotificationCenter.default.post(name: .cellsNeedReDraw, object: nil) } alertController.show(self) @@ -392,7 +407,8 @@ class SettingsLayout: BubbleSettingTableViewController { self.doLink() tableView.reloadData() self.imageCell.detailTextLabel?.text = SettingValues.postImageMode.rawValue.capitalize() - MainViewController.needsReTheme = true + + NotificationCenter.default.post(name: .cellsNeedReDraw, object: nil) } alertController.addAction(title: "Cropped image", icon: UIImage(named: "crop")!.menuIcon()) { @@ -403,7 +419,8 @@ class SettingsLayout: BubbleSettingTableViewController { self.doLink() tableView.reloadData() self.imageCell.detailTextLabel?.text = SettingValues.postImageMode.rawValue.capitalize() - MainViewController.needsReTheme = true + + NotificationCenter.default.post(name: .cellsNeedReDraw, object: nil) } alertController.addAction(title: "Shortened image", icon: UIImage(named: "crop")!.menuIcon()) { @@ -414,7 +431,8 @@ class SettingsLayout: BubbleSettingTableViewController { self.doLink() tableView.reloadData() self.imageCell.detailTextLabel?.text = SettingValues.postImageMode.rawValue.capitalize() - MainViewController.needsReTheme = true + + NotificationCenter.default.post(name: .cellsNeedReDraw, object: nil) } alertController.addAction(title: "Thumbnail only", icon: UIImage(named: "thumb")!.menuIcon()) { @@ -425,7 +443,8 @@ class SettingsLayout: BubbleSettingTableViewController { self.doLink() tableView.reloadData() self.imageCell.detailTextLabel?.text = SettingValues.postImageMode.rawValue.capitalize() - MainViewController.needsReTheme = true + + NotificationCenter.default.post(name: .cellsNeedReDraw, object: nil) } alertController.addAction(title: "No image", icon: UIImage(named: "hide")!.menuIcon()) { @@ -436,7 +455,8 @@ class SettingsLayout: BubbleSettingTableViewController { self.doLink() tableView.reloadData() self.imageCell.detailTextLabel?.text = SettingValues.postImageMode.rawValue.capitalize() - MainViewController.needsReTheme = true + + NotificationCenter.default.post(name: .cellsNeedReDraw, object: nil) } alertController.show(self) @@ -452,7 +472,8 @@ class SettingsLayout: BubbleSettingTableViewController { tableView.reloadData() self.actionBarCell.detailTextLabel?.text = SettingValues.actionBarMode.rawValue.capitalize() SingleSubredditViewController.cellVersion += 1 - MainViewController.needsReTheme = true + + NotificationCenter.default.post(name: .cellsNeedReDraw, object: nil) } alertController.addAction(title: "Left aligned button bar", icon: UIImage(sfString: SFSymbol.handPointLeftFill, overrideString: "code")!.menuIcon()) { @@ -464,7 +485,8 @@ class SettingsLayout: BubbleSettingTableViewController { tableView.reloadData() self.actionBarCell.detailTextLabel?.text = SettingValues.actionBarMode.rawValue.capitalize() SingleSubredditViewController.cellVersion += 1 - MainViewController.needsReTheme = true + + NotificationCenter.default.post(name: .cellsNeedReDraw, object: nil) } alertController.addAction(title: "Vote buttons on left side", icon: UIImage(sfString: SFSymbol.chevronUp, overrideString: "up")!.menuIcon()) { @@ -476,7 +498,8 @@ class SettingsLayout: BubbleSettingTableViewController { tableView.reloadData() self.actionBarCell.detailTextLabel?.text = SettingValues.actionBarMode.rawValue.capitalize() SingleSubredditViewController.cellVersion += 1 - MainViewController.needsReTheme = true + + NotificationCenter.default.post(name: .cellsNeedReDraw, object: nil) } alertController.addAction(title: "Vote buttons on right side", icon: UIImage(sfString: SFSymbol.chevronDown, overrideString: "down")!.menuIcon()) { @@ -488,8 +511,8 @@ class SettingsLayout: BubbleSettingTableViewController { tableView.reloadData() self.actionBarCell.detailTextLabel?.text = SettingValues.actionBarMode.rawValue.capitalize() SingleSubredditViewController.cellVersion += 1 - MainViewController.needsReTheme = true + NotificationCenter.default.post(name: .cellsNeedReDraw, object: nil) } alertController.addAction(title: "Disable buttons", icon: UIImage(sfString: SFSymbol.xmark, overrideString: "hide")!.menuIcon()) { @@ -501,7 +524,8 @@ class SettingsLayout: BubbleSettingTableViewController { tableView.reloadData() self.actionBarCell.detailTextLabel?.text = SettingValues.actionBarMode.rawValue.capitalize() SingleSubredditViewController.cellVersion += 1 - MainViewController.needsReTheme = true + + NotificationCenter.default.post(name: .cellsNeedReDraw, object: nil) } alertController.show(self) @@ -567,7 +591,8 @@ class SettingsLayout: BubbleSettingTableViewController { createCell(imageFlairsCell, imageFlairs, isOn: SettingValues.imageFlairs, text: "Show flair images") createCell(typeTitleCell, typeTitle, isOn: SettingValues.typeInTitle, text: "Content type in title") - createCell(hideAwardCell, hideAward, isOn: SettingValues.hideAwards, text: "Hide Reddit awards line") + createCell(hideAwardCell, hideAward, isOn: SettingValues.hideAwards, text: "Hide Reddit awards") + createCell(tapCell, tap, isOn: SettingValues.tapProfilesAndSubs, text: "Enable tappable author name and subreddit") createCell(smalltagCell, smalltag, isOn: SettingValues.smallerTag, text: "Smaller content tag") createCell(largerThumbnailCell, largerThumbnail, isOn: SettingValues.largerThumbnail, text: "Larger thumbnail") createCell(commentTitleCell, commentTitle, isOn: SettingValues.commentsInTitle, text: "Comment count in title") @@ -710,6 +735,7 @@ class SettingsLayout: BubbleSettingTableViewController { case 5: return self.domainInfoCell case 6: return self.hideImageSelftextCell case 7: return self.hideAwardCell + case 8: return self.tapCell default: fatalError("Unknown row in section 2") } case 3: @@ -748,7 +774,7 @@ class SettingsLayout: BubbleSettingTableViewController { switch section { case 0: return 1 case 1: return 5 - case 2: return 8 + case 2: return 9 case 3: return 3 case 4: return 4 case 5: return 7 diff --git a/Slide for Reddit/SettingsTheme.swift b/Slide for Reddit/SettingsTheme.swift index 7c1fd3fb3..ec1214eda 100644 --- a/Slide for Reddit/SettingsTheme.swift +++ b/Slide for Reddit/SettingsTheme.swift @@ -82,7 +82,7 @@ class SettingsTheme: BubbleSettingTableViewController, ColorPickerViewDelegate { } else { let alertController = UIAlertController(title: "\n\n\n\n\n\n\n\n", message: nil, preferredStyle: UIAlertController.Style.actionSheet) let margin: CGFloat = 10.0 - let rect = CGRect(x: margin, y: margin, width: UIScreen.main.traitCollection.userInterfaceIdiom == .pad ? 314 - margin * 4.0: UIScreen.main.bounds.size.width - margin * 4.0, height: 200) + let rect = CGRect(x: margin, y: margin, width: UIDevice.current.respectIpadLayout() ? 314 - margin * 4.0: UIScreen.main.bounds.size.width - margin * 4.0, height: 200) let MKColorPicker = ColorPickerView.init(frame: rect) MKColorPicker.delegate = self MKColorPicker.colors = GMPalette.allColor() @@ -118,7 +118,7 @@ class SettingsTheme: BubbleSettingTableViewController, ColorPickerViewDelegate { alertController.addAction(somethingAction) alertController.addAction(cancelAction) - if UIDevice.current.userInterfaceIdiom == .pad { + if UIDevice.current.respectIpadLayout() { alertController.preferredContentSize = CGSize(width: MKColorPicker.bounds.size.width + (margin * 2), height: MKColorPicker.bounds.size.height + 100) } @@ -157,6 +157,7 @@ class SettingsTheme: BubbleSettingTableViewController, ColorPickerViewDelegate { super.viewDidLoad() redoThemes() self.tableView.register(ThemeCellView.classForCoder(), forCellReuseIdentifier: "theme") + NotificationCenter.default.addObserver(self, selector: #selector(onSettingsThemeNeedsRestart), name: .settingsThemeNeedsRestart, object: nil) } func pickAccent() { @@ -172,7 +173,7 @@ class SettingsTheme: BubbleSettingTableViewController, ColorPickerViewDelegate { let alertController = UIAlertController(title: "\n\n\n\n\n\n\n\n", message: nil, preferredStyle: UIAlertController.Style.actionSheet) let margin: CGFloat = 10.0 - let rect = CGRect(x: margin, y: margin, width: UIScreen.main.traitCollection.userInterfaceIdiom == .pad ? 314 - margin * 4.0: alertController.view.bounds.size.width - margin * 4.0, height: 200) + let rect = CGRect(x: margin, y: margin, width: UIDevice.current.respectIpadLayout() ? 314 - margin * 4.0: alertController.view.bounds.size.width - margin * 4.0, height: 200) let MKColorPicker = ColorPickerView.init(frame: rect) MKColorPicker.delegate = self MKColorPicker.colors = GMPalette.allColorAccent() @@ -215,7 +216,7 @@ class SettingsTheme: BubbleSettingTableViewController, ColorPickerViewDelegate { alertController.addAction(somethingAction) alertController.addAction(cancelAction) alertController.modalPresentationStyle = .popover - if UIDevice.current.userInterfaceIdiom == .pad { + if UIDevice.current.respectIpadLayout() { alertController.preferredContentSize = CGSize(width: MKColorPicker.bounds.size.width + (margin * 2), height: MKColorPicker.bounds.size.height + 100) } if let presenter = alertController.popoverPresentationController { @@ -242,17 +243,20 @@ class SettingsTheme: BubbleSettingTableViewController, ColorPickerViewDelegate { } var doneOnce = false - static var needsRestart = false + + @objc func onSettingsThemeNeedsRestart() { + self.setupViews() + self.redoThemes() + self.tochange!.doCells() + self.tochange!.tableView.reloadData() + self.tableView.reloadData() + } + override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) setupBaseBarColors() - if doneOnce || SettingsTheme.needsRestart { - SettingsTheme.needsRestart = false - self.setupViews() - self.redoThemes() - self.tochange!.doCells() - self.tochange!.tableView.reloadData() - self.tableView.reloadData() + if doneOnce { + onSettingsThemeNeedsRestart() } else { doneOnce = true } @@ -380,15 +384,10 @@ class SettingsTheme: BubbleSettingTableViewController, ColorPickerViewDelegate { var themeText: String? @objc func switchIsChanged(_ changed: UISwitch) { - if changed == reduceColor { - MainViewController.needsReTheme = true - SettingValues.reduceColor = changed.isOn - UserDefaults.standard.set(changed.isOn, forKey: SettingValues.pref_reduceColor) - } else if changed == tintOutsideSwitch { + if changed == tintOutsideSwitch { SettingValues.onlyTintOutside = changed.isOn UserDefaults.standard.set(changed.isOn, forKey: SettingValues.pref_onlyTintOutside) } else if changed == reduceColor { - MainViewController.needsReTheme = true SettingValues.reduceColor = changed.isOn UserDefaults.standard.set(changed.isOn, forKey: SettingValues.pref_reduceColor) setupBaseBarColors() @@ -401,12 +400,14 @@ class SettingsTheme: BubbleSettingTableViewController, ColorPickerViewDelegate { let barButton = UIBarButtonItem.init(customView: button) navigationItem.leftBarButtonItem = barButton + + NotificationCenter.default.post(name: .reduceColorChanged, object: nil) } else if changed == nightEnabled { SettingValues.nightModeEnabled = changed.isOn UserDefaults.standard.set(changed.isOn, forKey: SettingValues.pref_nightMode) _ = ColorUtil.doInit() SingleSubredditViewController.cellVersion += 1 - MainViewController.needsReTheme = true + self.tochange!.doCells() self.tochange!.tableView.reloadData() } @@ -510,8 +511,7 @@ class SettingsTheme: BubbleSettingTableViewController, ColorPickerViewDelegate { UserDefaults.standard.set(theme.title, forKey: SettingValues.pref_nightTheme) UserDefaults.standard.synchronize() _ = ColorUtil.doInit() - SingleSubredditViewController.cellVersion += 1 - MainViewController.needsReTheme = true + self.setupViews() self.tableView.reloadData() self.tochange!.doCells() @@ -552,21 +552,23 @@ class SettingsTheme: BubbleSettingTableViewController, ColorPickerViewDelegate { let cv = themeView.contentView let alert = DragDownAlertMenu(title: theme.title, subtitle: "", icon: nil, extraView: cv, themeColor: nil, full: false) - alert.addAction(title: "Apply Theme", icon: UIImage(sfString: .checkmark, overrideString: "add")?.navIcon()) { - UserDefaults.standard.set(theme.title, forKey: "theme") - UserDefaults.standard.synchronize() - - _ = ColorUtil.doInit() - SingleSubredditViewController.cellVersion += 1 - self.tableView.reloadData() - MainViewController.needsReTheme = true - self.setupViews() - self.tochange!.doCells() - self.tochange!.tableView.reloadData() - self.tableView.reloadData() - self.setupBaseBarColors() - } + if ColorUtil.getCurrentTheme() != theme { + alert.addAction(title: "Apply Theme", icon: UIImage(sfString: .checkmark, overrideString: "add")?.navIcon()) { + UserDefaults.standard.set(theme.title, forKey: "theme") + UserDefaults.standard.synchronize() + + _ = ColorUtil.doInit() + SingleSubredditViewController.cellVersion += 1 + self.tableView.reloadData() + self.setupViews() + self.tochange!.doCells() + self.tochange!.tableView.reloadData() + self.tableView.reloadData() + self.setupBaseBarColors() + } + } + alert.extraViewHeight = 60 alert.addAction(title: "Edit Theme", icon: UIImage(sfString: .pencil, overrideString: "edit")?.navIcon()) { @@ -614,7 +616,7 @@ class SettingsTheme: BubbleSettingTableViewController, ColorPickerViewDelegate { _ = ColorUtil.doInit() SingleSubredditViewController.cellVersion += 1 self.tableView.reloadData() - MainViewController.needsReTheme = true + self.setupViews() self.tochange!.doCells() self.tochange!.tableView.reloadData() @@ -641,7 +643,7 @@ class SettingsTheme: BubbleSettingTableViewController, ColorPickerViewDelegate { _ = ColorUtil.doInit() self.setupViews() SingleSubredditViewController.cellVersion += 1 - MainViewController.needsReTheme = true + self.tableView.reloadData() self.tochange!.doCells() self.tochange!.tableView.reloadData() @@ -783,11 +785,10 @@ final public class PickerViewViewControllerColored: UIViewController { extension SettingsTheme: SettingsCustomThemeDelegate { func themeSaved() { - SettingsTheme.needsRestart = false _ = ColorUtil.doInit() SingleSubredditViewController.cellVersion += 1 self.tableView.reloadData() - MainViewController.needsReTheme = true + self.setupViews() self.tochange!.doCells() self.tochange!.tableView.reloadData() diff --git a/Slide for Reddit/SettingsViewController.swift b/Slide for Reddit/SettingsViewController.swift index 4d560201a..c473629fd 100644 --- a/Slide for Reddit/SettingsViewController.swift +++ b/Slide for Reddit/SettingsViewController.swift @@ -374,7 +374,7 @@ class SettingsViewController: MediaTableViewController, MFMailComposeViewControl self.subCell.imageView?.image = UIImage(sfString: .rCircleFill, overrideString: "subs")?.toolbarIcon() self.subCell.imageView?.tintColor = UIColor.fontColor - self.filters.textLabel?.text = "Filters" + self.filters.textLabel?.text = "Content Filters" self.filters.accessoryType = .disclosureIndicator self.filters.backgroundColor = UIColor.foregroundColor self.filters.textLabel?.textColor = UIColor.fontColor @@ -482,7 +482,7 @@ class SettingsViewController: MediaTableViewController, MFMailComposeViewControl } } else if changed == subIcons { SingleSubredditViewController.cellVersion += 1 - MainViewController.needsReTheme = true + NotificationCenter.default.post(name: .cellsNeedReDraw, object: nil) SettingValues.subredditIcons = changed.isOn UserDefaults.standard.set(changed.isOn, forKey: SettingValues.pref_subredditIcons) @@ -712,7 +712,7 @@ class SettingsViewController: MediaTableViewController, MFMailComposeViewControl UserDefaults.standard.synchronize() self.autoPlayCell.detailTextLabel?.text = SettingValues.autoPlayMode.description() + "\nAutoPlaying videos can lead to more data use" SingleSubredditViewController.cellVersion += 1 - SubredditReorderViewController.changed = true + NotificationCenter.default.post(name: .cellsNeedReDraw, object: nil) } } alertController.show(self) diff --git a/Slide for Reddit/SettingsViewMode.swift b/Slide for Reddit/SettingsViewMode.swift index 2611af17c..e4165a202 100644 --- a/Slide for Reddit/SettingsViewMode.swift +++ b/Slide for Reddit/SettingsViewMode.swift @@ -16,6 +16,7 @@ class SettingsViewMode: BubbleSettingTableViewController { var singleMode: UITableViewCell = InsetCell.init(style: .subtitle, reuseIdentifier: "single") var desktopMode: UITableViewCell = InsetCell.init(style: .subtitle, reuseIdentifier: "desktop") var splitMode: UITableViewCell = InsetCell.init(style: .subtitle, reuseIdentifier: "split") + var tripleMode: UITableViewCell = InsetCell.init(style: .subtitle, reuseIdentifier: "triple") var multicolumnMode: UITableViewCell = InsetCell.init(style: .subtitle, reuseIdentifier: "multi") var multicolumnCount: UITableViewCell = InsetCell.init(style: .subtitle, reuseIdentifier: "multicount") var multicolumnPortraitCount: UITableViewCell = InsetCell.init(style: .subtitle, reuseIdentifier: "portrait") @@ -51,7 +52,7 @@ class SettingsViewMode: BubbleSettingTableViewController { @objc func switchIsChanged(_ changed: UISwitch) { if changed == subredditBarSwitch { - MainViewController.needsRestart = true + NotificationCenter.default.post(name: .tabBarsChanged, object: nil) SettingValues.fullWidthHeaderCells = !changed.isOn UserDefaults.standard.set(!changed.isOn, forKey: SettingValues.pref_fullWidthHeaderCells) } else if changed == thireenPopupSwitch { @@ -100,9 +101,10 @@ class SettingsViewMode: BubbleSettingTableViewController { createCell(disablePopupSubreddit, disablePopupSubredditSwitch, isOn: SettingValues.disableSubredditPopupIpad, text: "Show subreddits full screen") createCell(disablePopup, disablePopupSwitch, isOn: SettingValues.disablePopupIpad, text: "Show comments full screen") createCell(disableMulticolumn, disableMulticolumnSwitch, isOn: !SettingValues.disableMulticolumnCollections, text: "Multi-column in profile and inbox") - createCell(singleMode, isOn: false, text: "Single-column posts") - createCell(multicolumnMode, isOn: false, text: "Multi-column posts") - createCell(splitMode, isOn: false, text: "Split-content") + createCell(singleMode, isOn: false, text: "Single-column posts\(UIDevice.current.isMacReal() ? "(designed for iPad)" : "")") + createCell(multicolumnMode, isOn: false, text: "Multi-column posts\(UIDevice.current.isMacReal() ? "(designed for iPad)" : "")") + createCell(splitMode, isOn: false, text: "Split-content\(UIDevice.current.isMacReal() ? "(designed for iPad)" : "")") + createCell(tripleMode, isOn: false, text: "Triple-pane Multi-column\(UIDevice.current.isMac() ? "(designed for MacOS)" : "")") createCell(multicolumnCount, isOn: false, text: "Multi-column count (Pro)") createCell(multicolumnPortraitCount, isOn: false, text: "Portrait Multi-column count (Pro)") createCell(galleryCount, isOn: false, text: "Gallery-mode column count (Pro)") @@ -113,7 +115,13 @@ class SettingsViewMode: BubbleSettingTableViewController { self.singleMode.backgroundColor = UIColor.foregroundColor self.singleMode.textLabel?.textColor = UIColor.fontColor self.singleMode.detailTextLabel?.numberOfLines = 0 - + + self.tripleMode.detailTextLabel?.text = SettingValues.AppMode.TRIPLE_MULTI_COLUMN.getDescription() + self.tripleMode.detailTextLabel?.textColor = UIColor.fontColor + self.tripleMode.backgroundColor = UIColor.foregroundColor + self.tripleMode.textLabel?.textColor = UIColor.fontColor + self.tripleMode.detailTextLabel?.numberOfLines = 0 + self.splitMode.detailTextLabel?.text = SettingValues.AppMode.SPLIT.getDescription() self.splitMode.detailTextLabel?.textColor = UIColor.fontColor self.splitMode.backgroundColor = UIColor.foregroundColor @@ -167,13 +175,15 @@ class SettingsViewMode: BubbleSettingTableViewController { self.splitMode.accessoryType = .checkmark case .MULTI_COLUMN: self.multicolumnMode.accessoryType = .checkmark + case .TRIPLE_MULTI_COLUMN: + self.tripleMode.accessoryType = .checkmark } self.galleryCount.isUserInteractionEnabled = true self.galleryCount.textLabel!.isEnabled = true self.galleryCount.detailTextLabel!.isEnabled = true - if !SettingValues.isPro { + if !SettingValues.isPro && !UIDevice.current.isMac() { multicolumnCount.isUserInteractionEnabled = false multicolumnCount.textLabel!.isEnabled = false multicolumnCount.detailTextLabel!.isEnabled = false @@ -188,13 +198,13 @@ class SettingsViewMode: BubbleSettingTableViewController { multicolumnPortraitCount.contentView.alpha = 0.8 } - if UIDevice.current.userInterfaceIdiom != .pad { + if !UIDevice.current.respectIpadLayout() { self.splitMode.isUserInteractionEnabled = false self.splitMode.textLabel!.isEnabled = false self.splitMode.detailTextLabel!.isEnabled = false } - if SettingValues.appMode != .MULTI_COLUMN || !SettingValues.isPro { + if (SettingValues.appMode != .MULTI_COLUMN || !SettingValues.isPro) && !UIDevice.current.respectIpadLayout(){ self.multicolumnCount.isUserInteractionEnabled = false self.multicolumnCount.textLabel!.isEnabled = false self.multicolumnCount.detailTextLabel!.isEnabled = false @@ -226,7 +236,7 @@ class SettingsViewMode: BubbleSettingTableViewController { case 0: return self.singleMode case 1: return self.splitMode case 2: return self.multicolumnMode - case 3: return self.desktopMode + case 3: return UIDevice.current.isMac() ? self.tripleMode : self.desktopMode default: fatalError("Unknown row in section 0") } case 1: @@ -259,6 +269,11 @@ class SettingsViewMode: BubbleSettingTableViewController { case 2: SettingValues.appMode = .MULTI_COLUMN UserDefaults.standard.set(SettingValues.AppMode.MULTI_COLUMN.rawValue, forKey: SettingValues.pref_appMode) + case 3: + if UIDevice.current.isMac() { + SettingValues.appMode = .TRIPLE_MULTI_COLUMN + UserDefaults.standard.set(SettingValues.AppMode.TRIPLE_MULTI_COLUMN.rawValue, forKey: SettingValues.pref_appMode) + } default: break } @@ -286,46 +301,64 @@ class SettingsViewMode: BubbleSettingTableViewController { showPortraitMultiColumn() } - SubredditReorderViewController.changed = true + NotificationCenter.default.post(name: .subNeedsReload, object: nil) UserDefaults.standard.synchronize() setSelected() } func showMultiColumn() { - let pad = UIScreen.main.traitCollection.userInterfaceIdiom == .pad - let actionSheetController = AlertController(title: "Column count", message: nil, preferredStyle: .alert) + if UIDevice.current.isMac() { + let popup = DragDownAlertMenu(title: "Column Count", subtitle: "", icon: nil) + + for value in 1...5 { + popup.addAction(title: "\(value)", icon: nil) { + SettingValues.multiColumnCount = value + UserDefaults.standard.set(value, forKey: SettingValues.pref_multiColumnCount) + UserDefaults.standard.synchronize() + + NotificationCenter.default.post(name: .subNeedsReload, object: nil) + self.setSelected() + } + } + + popup.show(self) + } else { + let pad = UIDevice.current.respectIpadLayout() + let actionSheetController = AlertController(title: "Column count", message: nil, preferredStyle: .alert) - actionSheetController.addCloseButton() + actionSheetController.addCloseButton() - let values = pad ? [["1", "2", "3", "4", "5"]] : [["1", "2", "3"]] - let pickerView = PickerViewViewControllerColored(values: values, initialSelection: [(0, SettingValues.multiColumnCount - 1)], action: { (_, _, chosen, _) in - SettingValues.multiColumnCount = chosen.row + 1 - UserDefaults.standard.set(chosen.row + 1, forKey: SettingValues.pref_multiColumnCount) - UserDefaults.standard.synchronize() - SubredditReorderViewController.changed = true - self.setSelected() - }) + let values = pad ? [["1", "2", "3", "4", "5"]] : [["1", "2", "3"]] + let pickerView = PickerViewViewControllerColored(values: values, initialSelection: [(0, SettingValues.multiColumnCount - 1)], action: { (_, _, chosen, _) in + SettingValues.multiColumnCount = chosen.row + 1 + UserDefaults.standard.set(chosen.row + 1, forKey: SettingValues.pref_multiColumnCount) + UserDefaults.standard.synchronize() - actionSheetController.setupTheme() - - actionSheetController.attributedTitle = NSAttributedString(string: "Landscape column count", attributes: [NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 17), NSAttributedString.Key.foregroundColor: UIColor.fontColor]) - - actionSheetController.addChild(pickerView) - - let pv = pickerView.view! - actionSheetController.contentView.addSubview(pv) - - pv.edgeAnchors /==/ actionSheetController.contentView.edgeAnchors - 14 - pv.heightAnchor /==/ CGFloat(216) - pickerView.didMove(toParent: actionSheetController) - - actionSheetController.addBlurView() + NotificationCenter.default.post(name: .subNeedsReload, object: nil) + self.setSelected() + }) - self.present(actionSheetController, animated: true, completion: nil) + actionSheetController.setupTheme() + + actionSheetController.attributedTitle = NSAttributedString(string: "Landscape column count", attributes: [NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 17), NSAttributedString.Key.foregroundColor: UIColor.fontColor]) + + actionSheetController.addChild(pickerView) + + let pv = pickerView.view! + actionSheetController.contentView.addSubview(pv) + + pv.edgeAnchors /==/ actionSheetController.contentView.edgeAnchors - 14 + pv.heightAnchor /==/ CGFloat(216) + pickerView.didMove(toParent: actionSheetController) + + actionSheetController.addBlurView() + + self.present(actionSheetController, animated: true, completion: nil) + } } func showPortraitMultiColumn() { - let pad = UIScreen.main.traitCollection.userInterfaceIdiom == .pad + let pad = UIDevice.current.respectIpadLayout() let actionSheetController = AlertController(title: "Column count", message: nil, preferredStyle: .alert) actionSheetController.addCloseButton() @@ -335,7 +368,8 @@ class SettingsViewMode: BubbleSettingTableViewController { SettingValues.portraitMultiColumnCount = chosen.row + 1 UserDefaults.standard.set(chosen.row + 1, forKey: SettingValues.pref_portraitMultiColumnCount) UserDefaults.standard.synchronize() - SubredditReorderViewController.changed = true + + NotificationCenter.default.post(name: .subNeedsReload, object: nil) self.setSelected() }) @@ -358,7 +392,7 @@ class SettingsViewMode: BubbleSettingTableViewController { } func showGalleryColumn() { - let pad = UIScreen.main.traitCollection.userInterfaceIdiom == .pad + let pad = UIDevice.current.respectIpadLayout() let actionSheetController = AlertController(title: "Gallery column count", message: nil, preferredStyle: .alert) actionSheetController.addCloseButton() @@ -368,7 +402,8 @@ class SettingsViewMode: BubbleSettingTableViewController { SettingValues.galleryCount = chosen.row + 1 UserDefaults.standard.set(chosen.row + 1, forKey: SettingValues.pref_galleryCount) UserDefaults.standard.synchronize() - SubredditReorderViewController.changed = true + + NotificationCenter.default.post(name: .subNeedsReload, object: nil) self.setSelected() }) @@ -393,7 +428,7 @@ class SettingsViewMode: BubbleSettingTableViewController { override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { var ipadOffset = 0 var isIpad = false - if UIDevice.current.userInterfaceIdiom == .pad || UIApplication.shared.isMac() { + if UIDevice.current.respectIpadLayout() || UIDevice.current.isMac() { isIpad = true ipadOffset = 3 } diff --git a/Slide for Reddit/Sidebar.swift b/Slide for Reddit/Sidebar.swift index 28c58b2be..6594bcc75 100644 --- a/Slide for Reddit/Sidebar.swift +++ b/Slide for Reddit/Sidebar.swift @@ -62,7 +62,7 @@ class Sidebar: NSObject { parent!.subChanged = false BannerUtil.makeBanner(text: "Unsubscribed", seconds: 5, context: self.parent, top: true) } else { - let alrController = DragDownAlertMenu(title: "Follow r/\(sub.displayName)", subtitle: "", icon: nil, themeColor: ColorUtil.accentColorForSub(sub: sub.displayName), full: true) + let alrController = DragDownAlertMenu(title: "Subscribe to \(sub.displayName.getSubredditFormatted())", subtitle: "", icon: nil, themeColor: ColorUtil.accentColorForSub(sub: sub.displayName), full: true) if AccountController.isLoggedIn { alrController.addAction(title: "Subscribe", icon: nil) { Subscriptions.subscribe(sub.displayName, true, session: (UIApplication.shared.delegate as! AppDelegate).session!) @@ -71,7 +71,7 @@ class Sidebar: NSObject { } } - alrController.addAction(title: "Casually subscribe", icon: nil) { + alrController.addAction(title: "Follow without Subscribing", icon: nil) { Subscriptions.subscribe(sub.displayName, false, session: (UIApplication.shared.delegate as! AppDelegate).session!) self.parent!.subChanged = true BannerUtil.makeBanner(text: "Added to subscription list", seconds: 5, context: self.parent, top: true) diff --git a/Slide for Reddit/SingleSubredditViewController.swift b/Slide for Reddit/SingleSubredditViewController.swift index a47d32012..a758a2b93 100644 --- a/Slide for Reddit/SingleSubredditViewController.swift +++ b/Slide for Reddit/SingleSubredditViewController.swift @@ -136,6 +136,7 @@ class SingleSubredditViewController: MediaViewController, AutoplayScrollViewDele var searchText: String? + var refreshControl: UIRefreshControl! var hasHeader = false @@ -191,6 +192,18 @@ class SingleSubredditViewController: MediaViewController, AutoplayScrollViewDele } } + @objc func cellsNeedReDraw() { + reloadDataReset() + } + + @objc func subNeedsReload() { + swipeBackAdded = false + + reloadDataReset() + setupSwipeGesture() + setupGestures() + } + deinit { NotificationCenter.default.removeObserver(self) } @@ -199,11 +212,14 @@ class SingleSubredditViewController: MediaViewController, AutoplayScrollViewDele super.viewDidLoad() CachedTitle.titles.removeAll() - if UIDevice.current.userInterfaceIdiom == .pad && SettingValues.appMode == .SPLIT && (!UIApplication.shared.isSplitOrSlideOver || UIApplication.shared.isMac()) && !(splitViewController?.viewControllers[(splitViewController?.viewControllers.count ?? 1) - 1] is PlaceholderViewController) { + if UIDevice.current.respectIpadLayout() && SettingValues.appMode == .SPLIT && (!UIApplication.shared.isSplitOrSlideOver || UIDevice.current.isMacReal()) && !(splitViewController?.viewControllers[(splitViewController?.viewControllers.count ?? 1) - 1] is PlaceholderViewController) { splitViewController?.showDetailViewController(SwipeForwardNavigationController(rootViewController: PlaceholderViewController()), sender: self) } NotificationCenter.default.addObserver(self, selector: #selector(youTubePlaying), name: .onYouTubeWillStart, object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(cellsNeedReDraw), name: .cellsNeedReDraw, object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(subNeedsReload), name: .subNeedsReload, object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(reduceColorChanged), name: .reduceColorChanged, object: nil) flowLayout.delegate = self self.tableView = UICollectionView(frame: CGRect.zero, collectionViewLayout: flowLayout) @@ -477,6 +493,9 @@ class SingleSubredditViewController: MediaViewController, AutoplayScrollViewDele override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { super.viewWillTransition(to: size, with: coordinator) + if tableView == nil { + return + } inHeadView?.removeFromSuperview() fab?.removeFromSuperview() @@ -859,7 +878,7 @@ class SingleSubredditViewController: MediaViewController, AutoplayScrollViewDele func loadBubbles() { self.subLinks.removeAll() - if self.sub == ("all") || self.sub == ("frontpage") || self.sub == ("popular") || self.sub == ("friends") || self.sub.lowercased() == ("myrandom") || self.sub.lowercased() == ("random") || self.sub.lowercased() == ("randnsfw") || self.sub.hasPrefix("/m/") || self.sub.contains("+") { + if self.sub == ("all") || self.sub == ("frontpage") || self.sub == ("popular") || self.sub == ("friends") || self.sub.lowercased() == ("myrandom") || self.sub.lowercased() == ("random") || self.sub.lowercased() == ("randnsfw") || self.sub.hasPrefix("/m/") || self.sub.hasPrefix("m/") || self.sub.hasPrefix("u_") || self.sub.contains("+") { return } do { @@ -908,7 +927,7 @@ class SingleSubredditViewController: MediaViewController, AutoplayScrollViewDele if self.dataSource.loaded && !self.dataSource.loading { self.flowLayout.reset(modal: self.presentingViewController != nil, vc: self, isGallery: self.isGallery) self.tableView.reloadData() - if UIDevice.current.userInterfaceIdiom != .pad { + if !UIDevice.current.respectIpadLayout() { var newOffset = self.tableView.contentOffset newOffset.y -= self.headerHeight(false) self.tableView.setContentOffset(newOffset, animated: false) @@ -957,13 +976,25 @@ class SingleSubredditViewController: MediaViewController, AutoplayScrollViewDele let flexButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.flexibleSpace, target: nil, action: nil) - if parent is SplitMainViewController { - parent!.toolbarItems = [searchB, flexButton, moreB] + if UIDevice.current.isMac() { + if parent is SplitMainViewController { + parent!.navigationItem.leftBarButtonItems = [searchB, moreB] + } else { + navigationItem.leftBarButtonItems = [searchB, moreB] + } } else { - toolbarItems = [searchB, flexButton, moreB] + if parent is SplitMainViewController { + parent!.toolbarItems = [searchB, flexButton, moreB] + } else { + toolbarItems = [searchB, flexButton, moreB] + } } } + @objc func reduceColorChanged() { + reloadNeedingColor() + } + func reloadNeedingColor() { tableView.backgroundColor = UIColor.backgroundColor inHeadView?.backgroundColor = ColorUtil.getColorForSub(sub: sub, true) @@ -975,7 +1006,10 @@ class SingleSubredditViewController: MediaViewController, AutoplayScrollViewDele refreshControl.attributedTitle = NSAttributedString(string: "") refreshControl.addTarget(self, action: #selector(self.drefresh(_:)), for: UIControl.Event.valueChanged) - tableView.addSubview(refreshControl) // not required when using UITableViewController + if let refresh = refreshControl, !UIDevice.current.isMac() { + tableView.addSubview(refresh) + } + tableView.alwaysBounceVertical = true self.automaticallyAdjustsScrollViewInsets = false @@ -1101,7 +1135,7 @@ class SingleSubredditViewController: MediaViewController, AutoplayScrollViewDele } if self.subInfo!.over18 && !SettingValues.nsfwEnabled { DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 2) { - let alert = UIAlertController.init(title: "r/\(self.sub) is NSFW", message: "You must log into Reddit and enable NSFW content at Reddit.com to view this subreddit", preferredStyle: .alert) + let alert = UIAlertController.init(title: "\(self.sub.getSubredditFormatted()) is NSFW", message: "You must log into Reddit and enable NSFW content at Reddit.com to view this subreddit", preferredStyle: .alert) alert.addAction(UIAlertAction.init(title: "Close", style: .default, handler: { (_) in self.navigationController?.popViewController(animated: true) self.dismiss(animated: true, completion: nil) @@ -1188,7 +1222,7 @@ class SingleSubredditViewController: MediaViewController, AutoplayScrollViewDele BannerUtil.makeBanner(text: "Unsubscribed", color: ColorUtil.accentColorForSub(sub: sub), seconds: 3, context: self, top: true) subb.setImage(UIImage(sfString: SFSymbol.plusCircleFill, overrideString: "addcircle")?.navIcon(), for: UIControl.State.normal) } else { - let alrController = UIAlertController.init(title: "Follow r/\(sub)", message: nil, preferredStyle: .alert) + let alrController = UIAlertController.init(title: "Subscribe to \(sub.getSubredditFormatted())", message: nil, preferredStyle: .alert) if AccountController.isLoggedIn { let somethingAction = UIAlertAction(title: "Subscribe", style: UIAlertAction.Style.default, handler: { (_: UIAlertAction!) in Subscriptions.subscribe(self.sub, true, session: self.session!) @@ -1199,7 +1233,7 @@ class SingleSubredditViewController: MediaViewController, AutoplayScrollViewDele alrController.addAction(somethingAction) } - let somethingAction = UIAlertAction(title: "Casually subscribe", style: UIAlertAction.Style.default, handler: { (_: UIAlertAction!) in + let somethingAction = UIAlertAction(title: "Follow without Subscribing", style: UIAlertAction.Style.default, handler: { (_: UIAlertAction!) in Subscriptions.subscribe(self.sub, false, session: self.session!) self.subChanged = true BannerUtil.makeBanner(text: "r/\(self.sub) added to your subreddit list", color: ColorUtil.accentColorForSub(sub: self.sub), seconds: 3, context: self, top: true) @@ -1370,7 +1404,7 @@ class SingleSubredditViewController: MediaViewController, AutoplayScrollViewDele alert.setupTheme() alert.attributedTitle = NSAttributedString(string: "Content to hide on", attributes: [NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 17), NSAttributedString.Key.foregroundColor: UIColor.fontColor]) - alert.attributedMessage = NSAttributedString(string: "r/\(sub)", attributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 14), NSAttributedString.Key.foregroundColor: UIColor.fontColor]) + alert.attributedMessage = NSAttributedString(string: "\(sub.getSubredditFormatted())", attributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 14), NSAttributedString.Key.foregroundColor: UIColor.fontColor]) alert.contentView.addSubview(filterView) settings.didMove(toParent: alert) @@ -2099,7 +2133,7 @@ extension SingleSubredditViewController: SubmissionDataSouceDelegate { if self.navigationController?.modalPresentationStyle == .pageSheet && self.navigationController?.viewControllers.count == 1 && !(self.navigationController?.viewControllers[0] is MainViewController) { topOffset = 0 } - let headerHeight = (UIDevice.current.userInterfaceIdiom == .pad && SettingValues.appMode == .MULTI_COLUMN ? 0 : self.headerHeight(false)) + let headerHeight = (UIDevice.current.respectIpadLayout() && SettingValues.appMode == .MULTI_COLUMN ? 0 : self.headerHeight(false)) let paddingOffset = CGFloat(headerHeight == 0 ? -4 : 0) setOffset = paddingOffset + navOffset + topOffset + headerHeight @@ -2242,7 +2276,7 @@ extension SingleSubredditViewController { isAccent = false let margin: CGFloat = 10.0 - let rect = CGRect(x: margin, y: margin, width: UIScreen.main.traitCollection.userInterfaceIdiom == .pad ? 314 - margin * 4.0: alertController.view.bounds.size.width - margin * 4.0, height: 150) + let rect = CGRect(x: margin, y: margin, width: UIDevice.current.respectIpadLayout() ? 314 - margin * 4.0: alertController.view.bounds.size.width - margin * 4.0, height: 150) let MKColorPicker = ColorPickerView.init(frame: rect) MKColorPicker.scrollToPreselectedIndex = true MKColorPicker.delegate = self @@ -2322,7 +2356,7 @@ extension SingleSubredditViewController { isAccent = true let margin: CGFloat = 10.0 - let rect = CGRect(x: margin, y: margin, width: UIScreen.main.traitCollection.userInterfaceIdiom == .pad ? 314 - margin * 4.0: alertController.view.bounds.size.width - margin * 4.0, height: 150) + let rect = CGRect(x: margin, y: margin, width: UIDevice.current.respectIpadLayout() ? 314 - margin * 4.0: alertController.view.bounds.size.width - margin * 4.0, height: 150) let MKColorPicker = ColorPickerView.init(frame: rect) MKColorPicker.scrollToPreselectedIndex = true MKColorPicker.delegate = self @@ -2626,7 +2660,7 @@ extension SingleSubredditViewController: UICollectionViewDataSource { var numberOfColumns = CGFloat.zero let portraitCount = SettingValues.portraitMultiColumnCount - let pad = UIScreen.main.traitCollection.userInterfaceIdiom == .pad + let pad = UIDevice.current.respectIpadLayout() if SettingValues.appMode == .MULTI_COLUMN { if UIApplication.shared.statusBarOrientation.isPortrait { @@ -2717,7 +2751,7 @@ extension SingleSubredditViewController: LinkCellViewDelegate { } return }) - VCPresenter.showVC(viewController: comment, popupIfPossible: (UIDevice.current.userInterfaceIdiom == .pad && SettingValues.disablePopupIpad || UIDevice.current.userInterfaceIdiom != .pad) ? false : true, parentNavigationController: self.navigationController, parentViewController: self) + VCPresenter.showVC(viewController: comment, popupIfPossible: (UIDevice.current.respectIpadLayout() && SettingValues.disablePopupIpad || !UIDevice.current.respectIpadLayout()) ? false : true, parentNavigationController: self.navigationController, parentViewController: self) } } @@ -2800,7 +2834,7 @@ extension SingleSubredditViewController: SubmissionMoreDelegate { func subscribe(link: SubmissionObject) { let sub = link.subreddit - let alrController = UIAlertController.init(title: "Follow r/\(sub)", message: nil, preferredStyle: .alert) + let alrController = UIAlertController.init(title: "Subscribe to \(sub.getSubredditFormatted())", message: nil, preferredStyle: .alert) if AccountController.isLoggedIn { let somethingAction = UIAlertAction(title: "Subscribe", style: UIAlertAction.Style.default, handler: { (_: UIAlertAction!) in Subscriptions.subscribe(sub, true, session: self.session!) @@ -2810,10 +2844,10 @@ extension SingleSubredditViewController: SubmissionMoreDelegate { alrController.addAction(somethingAction) } - let somethingAction = UIAlertAction(title: "Casually subscribe", style: UIAlertAction.Style.default, handler: { (_: UIAlertAction!) in + let somethingAction = UIAlertAction(title: "Follow without Subscribing", style: UIAlertAction.Style.default, handler: { (_: UIAlertAction!) in Subscriptions.subscribe(sub, false, session: self.session!) self.subChanged = true - BannerUtil.makeBanner(text: "r/\(sub) added to your subreddit list", color: ColorUtil.accentColorForSub(sub: sub), seconds: 3, context: self, top: true) + BannerUtil.makeBanner(text: "\(sub.getSubredditFormatted()) added to your subreddit list", color: ColorUtil.accentColorForSub(sub: sub), seconds: 3, context: self, top: true) }) alrController.addAction(somethingAction) @@ -2962,7 +2996,7 @@ extension SingleSubredditViewController: SubmissionMoreDelegate { } actionSheetController.addAction(cancelActionButton) - cancelActionButton = UIAlertAction(title: "Posts from r/\(link.subreddit)", style: .default) { _ -> Void in + cancelActionButton = UIAlertAction(title: "Posts from \(link.subreddit.getSubredditFormatted())", style: .default) { _ -> Void in PostFilter.subreddits.append(link.subreddit as NSString) PostFilter.saveAndUpdate() self.dataSource.content = PostFilter.filter(self.dataSource.content, previous: nil, baseSubreddit: self.sub).map { $0 as! SubmissionObject } @@ -2987,7 +3021,8 @@ extension SingleSubredditViewController: UIGestureRecognizerDelegate { func setupGestures() { if cellGestureRecognizer != nil { - return + cellGestureRecognizer.view?.removeGestureRecognizer(cellGestureRecognizer) + cellGestureRecognizer = nil } cellGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(panCell(_:))) cellGestureRecognizer.delegate = self @@ -3028,7 +3063,7 @@ extension SingleSubredditViewController: UIGestureRecognizerDelegate { full.view?.removeGestureRecognizer(full) } - if UIDevice.current.userInterfaceIdiom == .pad { + if UIDevice.current.respectIpadLayout() { fullWidthBackGestureRecognizer = UISwipeGestureRecognizer(target: self, action: #selector(showParentMenu(_:))) guard let swipe = fullWidthBackGestureRecognizer as? UISwipeGestureRecognizer else { return } swipe.direction = .right @@ -3078,7 +3113,7 @@ extension SingleSubredditViewController: UIGestureRecognizerDelegate { return false } if translation.x < 0 { - if gestureRecognizer.location(in: tableView).x > tableView.frame.width * 0.5 || !SettingValues.submissionGestureMode.shouldPage() || (SettingValues.appMode == .MULTI_COLUMN && UIDevice.current.userInterfaceIdiom == .pad) { + if gestureRecognizer.location(in: tableView).x > tableView.frame.width * 0.5 || !SettingValues.submissionGestureMode.shouldPage() || (SettingValues.appMode == .MULTI_COLUMN && UIDevice.current.respectIpadLayout()) { return true } } else if !SettingValues.submissionGestureMode.shouldPage() && abs(translation.x) > abs(translation.y) { @@ -3428,7 +3463,7 @@ public class LinksHeaderCellView: UICollectionViewCell { $0.setTitleColor(.white, for: .selected) $0.titleLabel?.textAlignment = .center $0.titleLabel?.font = UIFont.systemFont(ofSize: 12) - $0.backgroundColor = ColorUtil.getNavColorForSub(sub: sub) ?? UIColor.navIconColor + $0.backgroundColor = ColorUtil.getNavColorForSub(sub: sub) ?? ColorUtil.accentColorForSub(sub: sub) $0.addTapGestureRecognizer { (_) in self.del?.doShow(url: link.link!, heroView: nil, finalSize: nil, heroVC: nil, link: SubmissionObject()) } @@ -3472,7 +3507,7 @@ public class LinksHeaderCellView: UICollectionViewCell { header.addSubview(imageView) imageView.clipsToBounds = true - if UIDevice.current.userInterfaceIdiom == .pad { + if UIDevice.current.respectIpadLayout() { imageView.verticalAnchors /==/ header.verticalAnchors imageView.horizontalAnchors /==/ header.horizontalAnchors + 4 imageView.layer.cornerRadius = 15 @@ -3511,7 +3546,7 @@ public class SubLinkItem { extension SingleSubredditViewController: TapBehindModalViewControllerDelegate { func shouldDismiss() -> Bool { - return UIDevice.current.userInterfaceIdiom == .pad + return UIDevice.current.respectIpadLayout() } } diff --git a/Slide for Reddit/SiriShortcuts.swift b/Slide for Reddit/SiriShortcuts.swift index c0e22d402..1f5c3a9cc 100644 --- a/Slide for Reddit/SiriShortcuts.swift +++ b/Slide for Reddit/SiriShortcuts.swift @@ -21,7 +21,7 @@ extension SingleSubredditViewController { let attributes = CSSearchableItemAttributeSet(itemContentType: kUTTypeItem as String) activity.title = subreddit activity.userInfo = ["TYPE": "SUBREDDIT"] - attributes.contentDescription = "Open r/\(subreddit) in Slide" + attributes.contentDescription = "Open \(subreddit.getSubredditFormatted()) in Slide" activity.contentAttributeSet = attributes return activity diff --git a/Slide for Reddit/Slide for Reddit.entitlements b/Slide for Reddit/Slide for Reddit.entitlements index 6eb5143f8..1515e5779 100644 --- a/Slide for Reddit/Slide for Reddit.entitlements +++ b/Slide for Reddit/Slide for Reddit.entitlements @@ -19,9 +19,17 @@ app-usage + com.apple.security.app-sandbox + com.apple.security.application-groups group.$(USR_DOMAIN).redditslide.prefs + com.apple.security.device.camera + + com.apple.security.network.client + + com.apple.security.personal-information.photos-library + diff --git a/Slide for Reddit/SplitMainViewController.swift b/Slide for Reddit/SplitMainViewController.swift index 3cfd63ff9..d18597acc 100644 --- a/Slide for Reddit/SplitMainViewController.swift +++ b/Slide for Reddit/SplitMainViewController.swift @@ -59,6 +59,7 @@ class SplitMainViewController: MainViewController { inHeadView.backgroundColor = .clear } } + override func doProfileIcon() { let account = ExpandedHitButton(type: .custom) let accountImage = UIImage(sfString: SFSymbol.personCropCircle, overrideString: "profile")?.navIcon() @@ -109,13 +110,13 @@ class SplitMainViewController: MainViewController { } override func doButtons() { - if menu.superview != nil && !MainViewController.needsReTheme { + if menu.superview != nil { // What was this for... && !MainViewController.needsReTheme { return } splitViewController?.navigationItem.hidesBackButton = true if #available(iOS 14.0, *) { - if UIDevice.current.userInterfaceIdiom == .pad { + if UIDevice.current.respectIpadLayout() { splitViewController?.showsSecondaryOnlyButton = false splitViewController?.navigationItem.hidesBackButton = true splitViewController?.navigationItem.backBarButtonItem = UIBarButtonItem() @@ -198,7 +199,7 @@ class SplitMainViewController: MainViewController { if self.navigationController?.viewControllers[0] is NavigationHomeViewController { self.navigationController?.popViewController(animated: true) } else if #available(iOS 14, *) { - if UIDevice.current.userInterfaceIdiom == .pad { + if UIDevice.current.respectIpadLayout() { self.splitViewController?.show(UISplitViewController.Column.primary) } else { self.navigationController?.popViewController(animated: true) @@ -273,7 +274,11 @@ class SplitMainViewController: MainViewController { NotificationCenter.default.addObserver(self, selector: #selector(autoCacheFinished(_:)), name: .autoCacheFinished, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(autoCacheProgress(_:)), name: .autoCacheProgress, object: nil) - if let splitViewController = splitViewController, (!UIApplication.shared.isSplitOrSlideOver || UIApplication.shared.isMac()) { + NotificationCenter.default.addObserver(self, selector: #selector(subredditOrderDidChange), name: .subredditOrderChanged, object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(resetTabBars), name: .tabBarsChanged, object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(onThemeChanged), name: .reduceColorChanged, object: nil) + + if let splitViewController = splitViewController, (!UIApplication.shared.isSplitOrSlideOver) { (UIApplication.shared.delegate as? AppDelegate)?.setupSplitLayout(splitViewController) } } @@ -282,7 +287,7 @@ class SplitMainViewController: MainViewController { @objc func onThemeChanged() { SingleSubredditViewController.cellVersion += 1 - MainViewController.needsReTheme = true + navigationController?.toolbar.barTintColor = UIColor.backgroundColor navigationController?.toolbar.tintColor = UIColor.fontColor self.parent?.navigationController?.toolbar.barTintColor = UIColor.foregroundColor @@ -316,7 +321,7 @@ class SplitMainViewController: MainViewController { vc.setupSwipeGesture() } else if SettingValues.submissionGestureMode == .HALF_FULL { // Always allow swipe back with paging disabled and not full vc.setupSwipeGesture() - } else if UIDevice.current.userInterfaceIdiom == .pad && !SettingValues.subredditBar && SettingValues.submissionGestureMode != .FULL { + } else if UIDevice.current.respectIpadLayout() && !SettingValues.subredditBar && SettingValues.submissionGestureMode != .FULL { vc.setupSwipeGesture() } @@ -370,7 +375,6 @@ class SplitMainViewController: MainViewController { setupBaseBarColors(ColorUtil.getColorForSub(sub: getSubredditVC()?.sub ?? "", true)) toolbar?.backgroundColor = UIColor.foregroundColor.add(overlay: UIColor.isLightTheme ? UIColor.black.withAlphaComponent(0.05) : UIColor.white.withAlphaComponent(0.05)) self.doButtons() - MainViewController.needsReTheme = false } var isReappear = false @@ -395,11 +399,8 @@ class SplitMainViewController: MainViewController { } } - if subChanged || SubredditReorderViewController.changed { - finalSubs = [] - finalSubs.append(contentsOf: Subscriptions.pinned) - finalSubs.append(contentsOf: Subscriptions.subreddits.sorted(by: { $0.caseInsensitiveCompare($1) == .orderedAscending }).filter({ return !Subscriptions.pinned.contains($0) })) - redoSubs() + if subChanged { + subredditOrderDidChange() } self.parent?.navigationController?.navigationBar.shadowImage = UIImage() @@ -410,6 +411,13 @@ class SplitMainViewController: MainViewController { setNeedsStatusBarAppearanceUpdate() } + @objc func subredditOrderDidChange() { + finalSubs = [] + finalSubs.append(contentsOf: Subscriptions.pinned) + finalSubs.append(contentsOf: Subscriptions.subreddits.sorted(by: { $0.caseInsensitiveCompare($1) == .orderedAscending }).filter({ return !Subscriptions.pinned.contains($0) })) + redoSubs() + } + override func viewWillAppear(_ animated: Bool) { if navToMux == nil { self.navToMux = self.navigationController?.navigationBar @@ -428,27 +436,25 @@ class SplitMainViewController: MainViewController { */ } - if MainViewController.needsRestart { - MainViewController.needsRestart = false - tabBar?.removeFromSuperview() - self.navigationItem.leftBarButtonItems = [] - self.navigationItem.rightBarButtonItems = [] - if SettingValues.subredditBar { - setupTabBar(finalSubs) - if SettingValues.submissionGestureMode.shouldPage() { - self.dataSource = self - } - } else { - self.navigationItem.titleView = nil - self.dataSource = nil - } - } else if MainViewController.needsReTheme { - doRetheme() - } didUpdate() setupBaseBarColors( ColorUtil.getColorForSub(sub: getSubredditVC()?.sub ?? "", true)) } + + @objc func resetTabBars() { + tabBar?.removeFromSuperview() + self.navigationItem.leftBarButtonItems = [] + self.navigationItem.rightBarButtonItems = [] + if SettingValues.subredditBar { + setupTabBar(finalSubs) + if SettingValues.submissionGestureMode.shouldPage() { + self.dataSource = self + } + } else { + self.navigationItem.titleView = nil + self.dataSource = nil + } + } override func hardReset(soft: Bool = false) { var keyWindow = UIApplication.shared.keyWindow @@ -531,7 +537,7 @@ class SplitMainViewController: MainViewController { if self.finalSubs.contains(subreddit) && !override { let index = self.finalSubs.firstIndex(of: subreddit) if index == nil { - if UIDevice.current.userInterfaceIdiom == .pad && SettingValues.disableSubredditPopupIpad { + if UIDevice.current.respectIpadLayout() && SettingValues.disableSubredditPopupIpad { if self.navigationController?.topViewController != self && !(self.navigationController?.topViewController is NavigationHomeViewController) { self.navigationController?.popToRootViewController(animated: false) } @@ -577,7 +583,7 @@ class SplitMainViewController: MainViewController { self.navigationController?.popToRootViewController(animated: false) } - if UIDevice.current.userInterfaceIdiom == .pad && SettingValues.disableSubredditPopupIpad { + if UIDevice.current.respectIpadLayout() && SettingValues.disableSubredditPopupIpad { VCPresenter.showVC(viewController: SingleSubredditViewController(subName: subreddit.replacingOccurrences(of: " ", with: ""), single: true), popupIfPossible: false, parentNavigationController: self.navigationController, parentViewController: self) } else { VCPresenter.openRedditLink("/r/" + subreddit.replacingOccurrences(of: " ", with: ""), self.navigationController, self) @@ -614,7 +620,6 @@ class SplitMainViewController: MainViewController { CachedTitle.titles.removeAll() view.backgroundColor = UIColor.backgroundColor splitViewController?.view.backgroundColor = UIColor.foregroundColor - SubredditReorderViewController.changed = false finalSubs = [] LinkCellView.cachedInternet = nil @@ -902,7 +907,7 @@ extension SplitMainViewController: NavigationHomeDelegate { } func random(_ vc: NavigationHomeViewController) { - Alamofire.request("https://www.reddit.com/r/random/about.json", method: .get).responseString { response in + AF.request("https://www.reddit.com/r/random/about.json", method: .get).responseString { response in do { guard let data = response.data else { BannerUtil.makeBanner(text: "Random subreddit not found", color: GMColor.red500Color(), seconds: 2, context: self.parent, top: true, callback: nil) @@ -1069,7 +1074,7 @@ extension SplitMainViewController: NavigationHomeDelegate { } } else { var is14Column = false - if #available(iOS 14, *), (SettingValues.appMode == .SPLIT || (UIApplication.shared.isSplitOrSlideOver && !UIApplication.shared.isMac())) && UIDevice.current.userInterfaceIdiom == .pad { + if #available(iOS 14, *), (SettingValues.appMode == .SPLIT || (UIApplication.shared.isSplitOrSlideOver && !UIDevice.current.isMacReal())) && UIDevice.current.respectIpadLayout() { is14Column = true } @@ -1082,7 +1087,7 @@ extension SplitMainViewController: NavigationHomeDelegate { } } else { UIView.animate(withDuration: 0.3, animations: { - if (SettingValues.appMode == .MULTI_COLUMN || SettingValues.appMode == .SINGLE) && UIDevice.current.userInterfaceIdiom == .pad { + if (SettingValues.appMode == .MULTI_COLUMN || SettingValues.appMode == .SINGLE) && UIDevice.current.respectIpadLayout() { UIView.animate(withDuration: 0.5, animations: { () -> Void in self.splitViewController?.preferredDisplayMode = .primaryHidden }, completion: { (_) in @@ -1109,7 +1114,7 @@ extension SplitMainViewController: NavigationHomeDelegate { } } else { var is14Column = false - if #available(iOS 14, *), (SettingValues.appMode == .SPLIT || (UIApplication.shared.isSplitOrSlideOver && !UIApplication.shared.isMac())) && UIDevice.current.userInterfaceIdiom == .pad { + if #available(iOS 14, *), (SettingValues.appMode == .SPLIT || (UIApplication.shared.isSplitOrSlideOver && !UIDevice.current.isMacReal())) && UIDevice.current.respectIpadLayout() { is14Column = true } @@ -1117,7 +1122,7 @@ extension SplitMainViewController: NavigationHomeDelegate { UIApplication.shared.sendAction(action, to: target, from: nil, for: nil) } else { UIView.animate(withDuration: 0.3, animations: { - if (SettingValues.appMode == .MULTI_COLUMN || SettingValues.appMode == .SINGLE) && UIDevice.current.userInterfaceIdiom == .pad && !SettingValues.desktopMode { + if (SettingValues.appMode == .MULTI_COLUMN || SettingValues.appMode == .SINGLE) && UIDevice.current.respectIpadLayout() && !SettingValues.desktopMode { UIView.animate(withDuration: 0.5, animations: { () -> Void in self.splitViewController?.preferredDisplayMode = .primaryHidden }, completion: { (_) in diff --git a/Slide for Reddit/String+Extensions.swift b/Slide for Reddit/String+Extensions.swift index c7f69b6d9..dafa0b019 100644 --- a/Slide for Reddit/String+Extensions.swift +++ b/Slide for Reddit/String+Extensions.swift @@ -67,3 +67,41 @@ extension String { return str } } + +extension String { + func getSubredditFormatted() -> String { + if self.hasPrefix("/m/") { + return self.replacingOccurrences(of: "/m/", with: "m/") + } + + if self.hasPrefix("u_") { + return self.replacingOccurrences(of: "u_", with: "u/") + } + + if self.hasPrefix("/r/") { + return self.replacingOccurrences(of: "/r/", with: "r/") + } + + if self.hasPrefix("r/") { + return self + } else { + return "r/\(self)" + } + } + + func getSubredditFormattedShort() -> String { + if self.hasPrefix("/m/") { + return self.replacingOccurrences(of: "/m/", with: "m/") + } + + if self.hasPrefix("u_") { + return self.replacingOccurrences(of: "u_", with: "u/") + } + + if self.hasPrefix("/r/") { + return self.replacingOccurrences(of: "/r/", with: "") + } + + return self + } +} diff --git a/Slide for Reddit/SubSidebarViewController.swift b/Slide for Reddit/SubSidebarViewController.swift index ccbfe0bd4..30325d4c4 100644 --- a/Slide for Reddit/SubSidebarViewController.swift +++ b/Slide for Reddit/SubSidebarViewController.swift @@ -83,21 +83,21 @@ class SubSidebarViewController: MediaViewController, UIGestureRecognizerDelegate @objc func doSub(_ changed: UISwitch) { if !changed.isOn { Subscriptions.unsubscribe(subreddit!.displayName, session: (UIApplication.shared.delegate as! AppDelegate).session!) - BannerUtil.makeBanner(text: "Unsubscribed from r/\(subreddit!.displayName)", color: ColorUtil.accentColorForSub(sub: subreddit!.displayName), seconds: 3, context: self, top: true) + BannerUtil.makeBanner(text: "Unsubscribed from \(subreddit!.displayName.getSubredditFormatted())", color: ColorUtil.accentColorForSub(sub: subreddit!.displayName), seconds: 3, context: self, top: true) } else { - let alrController = DragDownAlertMenu(title: "Follow \(subreddit!.displayName)", subtitle: "", icon: nil, themeColor: ColorUtil.accentColorForSub(sub: subreddit!.displayName), full: true) + let alrController = DragDownAlertMenu(title: "Subscribe to \(subreddit!.displayName.getSubredditFormatted())", subtitle: "", icon: nil, themeColor: ColorUtil.accentColorForSub(sub: subreddit!.displayName), full: true) if AccountController.isLoggedIn { alrController.addAction(title: "Subscribe", icon: nil) { Subscriptions.subscribe(self.subreddit!.displayName, true, session: (UIApplication.shared.delegate as! AppDelegate).session!) - BannerUtil.makeBanner(text: "Subscribed to r/\(self.subreddit!.displayName)", color: ColorUtil.accentColorForSub(sub: self.subreddit!.displayName), seconds: 3, context: self, top: true) + BannerUtil.makeBanner(text: "Subscribed to \(self.subreddit!.displayName.getSubredditFormatted())", color: ColorUtil.accentColorForSub(sub: self.subreddit!.displayName), seconds: 3, context: self, top: true) } } - alrController.addAction(title: "Casually subscribe", icon: nil) { + alrController.addAction(title: "Follow without Subscribing", icon: nil) { Subscriptions.subscribe(self.subreddit!.displayName, false, session: (UIApplication.shared.delegate as! AppDelegate).session!) - BannerUtil.makeBanner(text: "r/\(self.subreddit!.displayName) added to your subreddit list", color: ColorUtil.accentColorForSub(sub: self.subreddit!.displayName), seconds: 3, context: self, top: true) + BannerUtil.makeBanner(text: "\(self.subreddit!.displayName.getSubredditFormatted()) added to your subreddit list", color: ColorUtil.accentColorForSub(sub: self.subreddit!.displayName), seconds: 3, context: self, top: true) } alrController.show(self) diff --git a/Slide for Reddit/SubmissionsDataSource.swift b/Slide for Reddit/SubmissionsDataSource.swift index 832296b63..3c8ad8867 100644 --- a/Slide for Reddit/SubmissionsDataSource.swift +++ b/Slide for Reddit/SubmissionsDataSource.swift @@ -147,12 +147,12 @@ class SubmissionsDataSource { } if subreddit.lowercased() == "randnsfw" && !SettingValues.nsfwEnabled { if let delegate = delegate { - delegate.generalError(title: "r/\(self.subreddit) is NSFW", message: "You must log into Reddit and enable NSFW content at Reddit.com to view this subreddit") + delegate.generalError(title: "\(self.subreddit.getSubredditFormatted()) is NSFW", message: "You must log into Reddit and enable NSFW content at Reddit.com to view this subreddit") } return } else if subreddit.lowercased() == "myrandom" && !AccountController.isGold { if let delegate = delegate { - delegate.generalError(title: "r/\(self.subreddit) requires gold", message: "See reddit.com/gold/about for more details") + delegate.generalError(title: "\(self.subreddit.getSubredditFormatted()) requires a Reddit Premium subscription", message: "See reddit.com/gold/about for more details") } return } diff --git a/Slide for Reddit/SubredditCellView.swift b/Slide for Reddit/SubredditCellView.swift index 554046090..888135b1d 100644 --- a/Slide for Reddit/SubredditCellView.swift +++ b/Slide for Reddit/SubredditCellView.swift @@ -137,9 +137,9 @@ class SubredditCellView: UITableViewCell { self.sideView.isHidden = false self.icon.isHidden = false if !exists { - title.text = "Go to r/\(subreddit)" + title.text = "Go to \(subreddit.getSubredditFormattedShort())" } else { - title.text = subreddit + title.text = subreddit.getSubredditFormattedShort() } failedLabel?.removeFromSuperview() @@ -203,7 +203,7 @@ class SubredditCellView: UITableViewCell { self.icon.isHidden = false self.sideView.isHidden = true self.navController = nav - title.text = "Search " + (sub == nil ? "Reddit" : "r/\(self.subreddit)") + title.text = "Search " + (sub == nil ? "Reddit" : "\(self.subreddit.getSubredditFormatted())") self.icon.contentMode = .center self.icon.image = UIImage.init(sfString: SFSymbol.magnifyingglass, overrideString: "search")!.menuIcon() sideView.backgroundColor = ColorUtil.getColorForSub(sub: subreddit) @@ -284,7 +284,7 @@ class SubredditCellView: UITableViewCell { if let icon = Subscriptions.icon(for: submission.subreddit) { subDot.sd_setImage(with: URL(string: icon.unescapeHTML), completed: nil) } - subName.text = "r/\(submission.subreddit)" + subName.text = "\(submission.subreddit.getSubredditFormatted())" thumbView.contentMode = .scaleAspectFill if submission.hasBanner { diff --git a/Slide for Reddit/SubredditFindReturnViewController.swift b/Slide for Reddit/SubredditFindReturnViewController.swift index cb57be705..78dd254fe 100644 --- a/Slide for Reddit/SubredditFindReturnViewController.swift +++ b/Slide for Reddit/SubredditFindReturnViewController.swift @@ -118,7 +118,7 @@ class SubredditFindReturnViewController: UITableViewController, UISearchBarDeleg return } - let alrController = DragDownAlertMenu(title: "Follow r/\(sub)", subtitle: "", icon: nil, themeColor: ColorUtil.accentColorForSub(sub: sub), full: true) + let alrController = DragDownAlertMenu(title: "Subscribe to \(sub.getSubredditFormatted())", subtitle: "", icon: nil, themeColor: ColorUtil.accentColorForSub(sub: sub), full: true) if AccountController.isLoggedIn { alrController.addAction(title: "Subscribe", icon: nil) { @@ -133,7 +133,7 @@ class SubredditFindReturnViewController: UITableViewController, UISearchBarDeleg return } - alrController.addAction(title: "Casually subscribe", icon: nil) { + alrController.addAction(title: "Follow without Subscribing", icon: nil) { Subscriptions.subscribe(sub, false, session: (UIApplication.shared.delegate as! AppDelegate).session!) self.navigationController?.popViewController(animated: true) self.callback(sub) diff --git a/Slide for Reddit/SubredditHeaderView.swift b/Slide for Reddit/SubredditHeaderView.swift index 675df46e4..68c55226a 100644 --- a/Slide for Reddit/SubredditHeaderView.swift +++ b/Slide for Reddit/SubredditHeaderView.swift @@ -38,9 +38,9 @@ class SubredditHeaderView: UIView { case .success(let users): list.append(contentsOf: users) DispatchQueue.main.async { - let sheet = DragDownAlertMenu(title: "Moderators", subtitle: "r/\(self.subreddit!.displayName)", icon: nil, themeColor: ColorUtil.accentColorForSub(sub: self.subreddit!.displayName), full: false) + let sheet = DragDownAlertMenu(title: "Moderators", subtitle: "\(self.subreddit!.displayName.getSubredditFormatted())", icon: nil, themeColor: ColorUtil.accentColorForSub(sub: self.subreddit!.displayName), full: false) - sheet.addAction(title: "Message r/\(self.subreddit!.displayName) moderators", icon: UIImage(sfString: SFSymbol.shieldLefthalfFill, overrideString: "mod")?.menuIcon(), action: { + sheet.addAction(title: "Message \(self.subreddit!.displayName.getSubredditFormatted()) moderators", icon: UIImage(sfString: SFSymbol.shieldLefthalfFill, overrideString: "mod")?.menuIcon(), action: { VCPresenter.openRedditLink("https://www.reddit.com/message/compose?to=/r/\(self.subreddit!.displayName)", self.parentController?.navigationController, self.parentController) }) @@ -165,7 +165,7 @@ class SubredditHeaderView: UIView { @objc func flair(_ selector: UITableViewCell) { if let subName = subreddit?.displayName, let token = (UIApplication.shared.delegate as? AppDelegate)?.session?.token { let requestString = "https://www.reddit.com/r/\(subName)/api/user_flair_v2.json" - Alamofire.request(requestString, method: .get, headers: ["Authorization": "bearer \(token.accessToken)"]).responseString { [weak self] response in + AF.request(requestString, method: .get, headers: ["Authorization": "bearer \(token.accessToken)"]).responseString { [weak self] response in guard let self = self else { return } do { guard let data = response.data else { @@ -173,7 +173,7 @@ class SubredditHeaderView: UIView { } let json = try JSON(data: data) if let flairs = json.array { - let alert = DragDownAlertMenu(title: "Available flairs", subtitle: "r/\(self.subreddit!.displayName)", icon: nil) + let alert = DragDownAlertMenu(title: "Available flairs", subtitle: "\(self.subreddit!.displayName.getSubredditFormatted())", icon: nil) for item in flairs { if let richtext = item["richtext"].array?[0] { @@ -254,7 +254,7 @@ class SubredditHeaderView: UIView { } @objc func sort(_ selector: UITableViewCell) { - let actionSheetController = DragDownAlertMenu(title: "Default sorting for r/\(self.subreddit!.displayName)", subtitle: "Overrides the default in Settings > General", icon: nil, themeColor: ColorUtil.accentColorForSub(sub: self.subreddit!.displayName), full: true) + let actionSheetController = DragDownAlertMenu(title: "Default sorting for \(self.subreddit!.displayName.getSubredditFormatted())", subtitle: "Overrides the default in Settings > General", icon: nil, themeColor: ColorUtil.accentColorForSub(sub: self.subreddit!.displayName), full: true) let selected = UIImage(sfString: SFSymbol.checkmarkCircle, overrideString: "selected")!.menuIcon() @@ -348,7 +348,7 @@ class SubredditHeaderView: UIView { descHeight = info.estimatedHeight } - self.flair.textLabel?.text = "Your flair on r/\(subreddit.displayName)" + self.flair.textLabel?.text = "Your flair on \(subreddit.displayName.getSubredditFormatted())" } var subreddit: Subreddit? diff --git a/Slide for Reddit/SubredditReorderViewController.swift b/Slide for Reddit/SubredditReorderViewController.swift index 1d9bba6d5..f292db9d2 100644 --- a/Slide for Reddit/SubredditReorderViewController.swift +++ b/Slide for Reddit/SubredditReorderViewController.swift @@ -107,8 +107,6 @@ class SubredditReorderViewController: UITableViewController { var delete = UIButton() - public static var changed = false - override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { return UITableView.automaticDimension } @@ -130,11 +128,11 @@ class SubredditReorderViewController: UITableViewController { } func save(_ selector: AnyObject?) { - SubredditReorderViewController.changed = true Subscriptions.setPinned(name: AccountController.currentName, subs: pinned, completion: { Subscriptions.set(name: AccountController.currentName, subs: self.subs, completion: { }) }) + NotificationCenter.default.post(name: .subredditOrderChanged, object: nil) } override func tableView(_ tableView: UITableView, willBeginEditingRowAt indexPath: IndexPath) { @@ -398,3 +396,12 @@ class SubredditReorderViewController: UITableViewController { } } } + +extension Notification.Name { + static let subredditOrderChanged = Notification.Name("subreddit-order-changed") + static let cellsNeedReDraw = Notification.Name("cells-need-re-draw") + static let subNeedsReload = Notification.Name("sub-needs-reload") + static let tabBarsChanged = Notification.Name("tab-bars-changed") + static let settingsThemeNeedsRestart = Notification.Name("settings-theme-needs-restart") + static let reduceColorChanged = Notification.Name("reduce-color-changed") +} diff --git a/Slide for Reddit/SubredditThemeViewController.swift b/Slide for Reddit/SubredditThemeViewController.swift index e36879f32..719bca1d0 100644 --- a/Slide for Reddit/SubredditThemeViewController.swift +++ b/Slide for Reddit/SubredditThemeViewController.swift @@ -20,12 +20,11 @@ class SubredditThemeViewController: UITableViewController, ColorPickerViewDelega override var preferredStatusBarStyle: UIStatusBarStyle { if UIColor.isLightTheme && SettingValues.reduceColor { - if #available(iOS 13, *) { + if #available(iOS 13, *) { return .darkContent } else { return .default } - } else { return .lightContent } @@ -119,8 +118,6 @@ class SubredditThemeViewController: UITableViewController, ColorPickerViewDelega } } - public static var changed = false - override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { return UITableView.automaticDimension } @@ -300,7 +297,7 @@ class SubredditThemeViewController: UITableViewController, ColorPickerViewDelega isAccent = false let margin: CGFloat = 10.0 - let rect = CGRect(x: margin, y: margin, width: UIScreen.main.traitCollection.userInterfaceIdiom == .pad ? 314 - margin * 4.0: alertController.view.bounds.size.width - margin * 4.0, height: 150) + let rect = CGRect(x: margin, y: margin, width: UIDevice.current.respectIpadLayout() ? 314 - margin * 4.0: alertController.view.bounds.size.width - margin * 4.0, height: 150) let MKColorPicker = ColorPickerView.init(frame: rect) MKColorPicker.delegate = self MKColorPicker.colors = GMPalette.allColor() @@ -347,7 +344,7 @@ class SubredditThemeViewController: UITableViewController, ColorPickerViewDelega let alertController = UIAlertController(title: "\n\n\n\n\n\n\n\n", message: nil, preferredStyle: UIAlertController.Style.actionSheet) let margin: CGFloat = 10.0 - let rect = CGRect(x: margin, y: margin, width: UIScreen.main.traitCollection.userInterfaceIdiom == .pad ? 314 - margin * 4.0: alertController.view.bounds.size.width - margin * 4.0, height: 150) + let rect = CGRect(x: margin, y: margin, width: UIDevice.current.respectIpadLayout() ? 314 - margin * 4.0: alertController.view.bounds.size.width - margin * 4.0, height: 150) let MKColorPicker = ColorPickerView.init(frame: rect) MKColorPicker.delegate = self MKColorPicker.colors = GMPalette.allColorAccent() diff --git a/Slide for Reddit/SubredditToolbarSearchViewController.swift b/Slide for Reddit/SubredditToolbarSearchViewController.swift index 1f0bc6e94..b6878473d 100644 --- a/Slide for Reddit/SubredditToolbarSearchViewController.swift +++ b/Slide for Reddit/SubredditToolbarSearchViewController.swift @@ -104,7 +104,7 @@ class SubredditToolbarSearchViewController: UIViewController, UIGestureRecognize } if controller.navigationController?.viewControllers.count ?? 0 == 1 && controller.navigationController?.modalPresentationStyle ?? controller.modalPresentationStyle == .pageSheet { bottomOffset += 64 - if UIDevice.current.userInterfaceIdiom == .pad { + if UIDevice.current.respectIpadLayout() { bottomOffset += 24 } } @@ -693,7 +693,7 @@ class SubredditToolbarSearchViewController: UIViewController, UIGestureRecognize } func setupHeader(_ subreddit: String) { - let titleString = NSMutableAttributedString(string: "r/\(subreddit)", attributes: [NSAttributedString.Key.foregroundColor: UIColor.fontColor, NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 18)]) + let titleString = NSMutableAttributedString(string: "\(subreddit.getSubredditFormatted())", attributes: [NSAttributedString.Key.foregroundColor: UIColor.fontColor, NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 18)]) subTitleView.attributedText = titleString subTitleView.numberOfLines = 0 @@ -722,7 +722,7 @@ class SubredditToolbarSearchViewController: UIViewController, UIGestureRecognize } func setDescriptionLabel(_ subreddit: Subreddit) { - let titleString = NSMutableAttributedString(string: "r/\(subreddit.displayName)", attributes: [NSAttributedString.Key.foregroundColor: UIColor.fontColor, NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 18)]) + let titleString = NSMutableAttributedString(string: "\(subreddit.displayName.getSubredditFormatted())", attributes: [NSAttributedString.Key.foregroundColor: UIColor.fontColor, NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 18)]) titleString.appendString("\n") titleString.append(NSMutableAttributedString(string: "\(subreddit.accountsActive) HERE • \(subreddit.subscribers) SUBSCRIBERS", attributes: [NSAttributedString.Key.foregroundColor: UIColor.fontColor, NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 12)])) diff --git a/Slide for Reddit/Subscriptions.swift b/Slide for Reddit/Subscriptions.swift index bf1284fc0..7be951d00 100644 --- a/Slide for Reddit/Subscriptions.swift +++ b/Slide for Reddit/Subscriptions.swift @@ -135,9 +135,11 @@ class Subscriptions { public static func subscribe(_ name: String, _ subscribe: Bool, session: Session?) { var sub = Subscriptions.subreddits - SubredditReorderViewController.changed = true + sub.append(name) set(name: AccountController.currentName, subs: sub) { () in } + + NotificationCenter.default.post(name: .subredditOrderChanged, object: nil) if #available(iOS 10.0, *) { HapticUtility.hapticActionStrong() } else if SettingValues.hapticFeedback { @@ -158,8 +160,10 @@ class Subscriptions { var subs = Subscriptions.subreddits subs = subs.filter { $0 != name } setPinned(name: AccountController.currentName, subs: pinned.filter { $0 != name }, completion: {}) - SubredditReorderViewController.changed = true + set(name: AccountController.currentName, subs: subs) { () in } + + NotificationCenter.default.post(name: .subredditOrderChanged, object: nil) if #available(iOS 10.0, *) { HapticUtility.hapticActionStrong() } else if SettingValues.hapticFeedback { diff --git a/Slide for Reddit/SwipeDownModalVC.swift b/Slide for Reddit/SwipeDownModalVC.swift index b29db6172..ccaaa2133 100644 --- a/Slide for Reddit/SwipeDownModalVC.swift +++ b/Slide for Reddit/SwipeDownModalVC.swift @@ -40,7 +40,7 @@ class SwipeDownModalVC: ColorMuxPagingViewController { if #available(iOS 13.4, *) { panGestureRecognizer!.allowedScrollTypesMask = .continuous } - + panGestureRecognizer2!.direction = .horizontal panGestureRecognizer!.cancelsTouchesInView = false diff --git a/Slide for Reddit/SwipeForwardNavigationController.swift b/Slide for Reddit/SwipeForwardNavigationController.swift index 7bb2497b9..00693a54e 100644 --- a/Slide for Reddit/SwipeForwardNavigationController.swift +++ b/Slide for Reddit/SwipeForwardNavigationController.swift @@ -264,7 +264,7 @@ extension SwipeForwardNavigationController { let pushedViewController = pushableViewControllers.last if pushedViewController != nil && visibleViewController != nil && visibleViewController?.isBeingPresented == false && visibleViewController?.isBeingDismissed == false { - push(pushedViewController, animated: (UIApplication.shared.isSplitOrSlideOver && !UIApplication.shared.isMac()) ? false : true) { + push(pushedViewController, animated: (UIApplication.shared.isSplitOrSlideOver && !UIDevice.current.isMacReal()) ? false : true) { if !self.pushableViewControllers.isEmpty { self.pushableViewControllers.removeLast() callback?() diff --git a/Slide for Reddit/TabsContentPagingViewController.swift b/Slide for Reddit/TabsContentPagingViewController.swift index 6d12e9fb8..59e58a68b 100644 --- a/Slide for Reddit/TabsContentPagingViewController.swift +++ b/Slide for Reddit/TabsContentPagingViewController.swift @@ -123,7 +123,7 @@ class TabsContentPagingViewController: ColorMuxPagingViewController, UIPageViewC } let topAnchorOffset = (self.navigationController?.navigationBar.frame.size.height ?? 64) + (isModal13 ? 0 : UIApplication.shared.statusBarFrame.height) if #available(iOS 13, *) { - tabBar.topAnchor /==/ self.view.topAnchor + topAnchorOffset + tabBar.topAnchor /==/ self.view.safeTopAnchor } else { tabBar.topAnchor /==/ self.view.topAnchor } diff --git a/Slide for Reddit/TapBehindModalViewController.swift b/Slide for Reddit/TapBehindModalViewController.swift index d8c391722..85bb73307 100644 --- a/Slide for Reddit/TapBehindModalViewController.swift +++ b/Slide for Reddit/TapBehindModalViewController.swift @@ -23,7 +23,7 @@ class TapBehindModalViewController: SwipeForwardNavigationController { override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) - if self.tapOutsideRecognizer == nil && ((modalPresentationStyle == .pageSheet || modalPresentationStyle == .popover) || UIDevice.current.userInterfaceIdiom == .pad) { + if self.tapOutsideRecognizer == nil && ((modalPresentationStyle == .pageSheet || modalPresentationStyle == .popover) || UIDevice.current.respectIpadLayout()) { self.tapOutsideRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.handleTapBehind)) self.tapOutsideRecognizer.numberOfTapsRequired = 1 self.tapOutsideRecognizer.cancelsTouchesInView = false diff --git a/Slide for Reddit/TextDisplayStackView.swift b/Slide for Reddit/TextDisplayStackView.swift index 20d75cbcc..af18ec9e1 100644 --- a/Slide for Reddit/TextDisplayStackView.swift +++ b/Slide for Reddit/TextDisplayStackView.swift @@ -689,12 +689,13 @@ public class TextDisplayStackView: UIStackView { let imgPattern = "\\" if let regex = try? NSRegularExpression(pattern: imgPattern, options: .caseInsensitive) { - let modString = regex.stringByReplacingMatches(in: html, options: .withTransparentBounds, range: NSMakeRange(0, html.length), withTemplate: "Image") + let modString = regex.stringByReplacingMatches(in: html, options: .withTransparentBounds, range: NSRange(location: 0, length: html.length), withTemplate: "Image") preSeperated.append(modString) } else { preSeperated.append(html) } } + return preSeperated } diff --git a/Slide for Reddit/ThreadViewController.swift b/Slide for Reddit/ThreadViewController.swift index 8fb95ee8b..b14379093 100644 --- a/Slide for Reddit/ThreadViewController.swift +++ b/Slide for Reddit/ThreadViewController.swift @@ -79,8 +79,8 @@ class ThreadViewControler: MediaViewController, UICollectionViewDelegate, Wrappi self.navigationController?.delegate = self if !loaded && !loading { - self.tableView.contentOffset = CGPoint(x: 0, y: -self.refreshControl.frame.size.height) - refreshControl.beginRefreshing() + self.tableView.contentOffset = CGPoint(x: 0, y: -(self.refreshControl?.frame.size.height ?? 0)) + refreshControl?.beginRefreshing() } else { self.tableView.reloadData() } @@ -149,13 +149,19 @@ class ThreadViewControler: MediaViewController, UICollectionViewDelegate, Wrappi self.tableView.delegate = self self.tableView.dataSource = self - refreshControl = UIRefreshControl() - refreshControl.tintColor = UIColor.fontColor - - refreshControl.attributedTitle = NSAttributedString(string: "") - refreshControl.addTarget(self, action: #selector(self.drefresh(_:)), for: UIControl.Event.valueChanged) - tableView.addSubview(refreshControl) - refreshControl.centerAnchors /==/ tableView.centerAnchors + if !UIDevice.current.isMac() { + refreshControl = UIRefreshControl() + refreshControl?.tintColor = UIColor.fontColor + + refreshControl?.attributedTitle = NSAttributedString(string: "") + refreshControl?.addTarget(self, action: #selector(self.drefresh(_:)), for: UIControl.Event.valueChanged) + + if let refresh = refreshControl, !UIDevice.current.isMac() { + tableView.addSubview(refresh) + } + + refreshControl!.centerAnchors /==/ tableView.centerAnchors + } tableView.alwaysBounceVertical = true @@ -267,13 +273,13 @@ class ThreadViewControler: MediaViewController, UICollectionViewDelegate, Wrappi // TODO: - maybe add this later } - var refreshControl: UIRefreshControl! + var refreshControl: UIRefreshControl? func refresh() { loading = true emptyStateView.isHidden = true baseData.reset() - refreshControl.beginRefreshing() + refreshControl?.beginRefreshing() flowLayout.reset(modal: presentingViewController != nil, vc: self, isGallery: false) flowLayout.invalidateLayout() tableView.reloadData() @@ -292,14 +298,17 @@ class ThreadViewControler: MediaViewController, UICollectionViewDelegate, Wrappi } func endAndResetRefresh() { - self.refreshControl.endRefreshing() - self.refreshControl.removeFromSuperview() + if UIDevice.current.isMac() { + return + } + self.refreshControl?.endRefreshing() + self.refreshControl?.removeFromSuperview() self.refreshControl = UIRefreshControl() - self.refreshControl.tintColor = UIColor.fontColor + self.refreshControl?.tintColor = UIColor.fontColor - self.refreshControl.attributedTitle = NSAttributedString(string: "") - self.refreshControl.addTarget(self, action: #selector(self.drefresh(_:)), for: UIControl.Event.valueChanged) - self.tableView.addSubview(self.refreshControl) + self.refreshControl?.attributedTitle = NSAttributedString(string: "") + self.refreshControl?.addTarget(self, action: #selector(self.drefresh(_:)), for: UIControl.Event.valueChanged) + self.tableView.addSubview(self.refreshControl!) } var loading: Bool = false diff --git a/Slide for Reddit/TitleUITextView.swift b/Slide for Reddit/TitleUITextView.swift index b336f6e3f..8a081b5b0 100644 --- a/Slide for Reddit/TitleUITextView.swift +++ b/Slide for Reddit/TitleUITextView.swift @@ -97,6 +97,9 @@ class TitleUITextView: UITextView { delegate?.previewProfile(profile: profile) return } else if let url = highlight.userInfo["url"] as? URL { + if url.absoluteString.contains("ccrama.me") { + return + } delegate?.linkLongTapped(url: url) return } diff --git a/Slide for Reddit/ToolbarTextView.swift b/Slide for Reddit/ToolbarTextView.swift index 518d91fab..af272dbf1 100644 --- a/Slide for Reddit/ToolbarTextView.swift +++ b/Slide for Reddit/ToolbarTextView.swift @@ -248,7 +248,7 @@ public class ToolbarTextView: NSObject { }) if assets.count > 1 { - Alamofire.request("https://api.imgur.com/3/album", method: .post, parameters: nil, encoding: JSONEncoding.default, headers: ["Authorization": "Client-ID bef87913eb202e9"]) + AF.request("https://api.imgur.com/3/album", method: .post, parameters: nil, encoding: JSONEncoding.default, headers: ["Authorization": "Client-ID bef87913eb202e9"]) .responseJSON { response in print(response) if let status = response.response?.statusCode { @@ -415,8 +415,9 @@ public class ToolbarTextView: NSObject { } } } + - Alamofire.upload(multipartFormData: { (multipartFormData) in + AF.upload(multipartFormData: { (multipartFormData) in multipartFormData.append(data!, withName: "image", fileName: name, mimeType: mime! as String) for (key, value) in parameters { multipartFormData.append((value.data(using: .utf8))!, withName: key) @@ -424,29 +425,29 @@ public class ToolbarTextView: NSObject { if !album.isEmpty { multipartFormData.append(album.data(using: .utf8)!, withName: "album") } - }, to: "https://api.imgur.com/3/image", method: .post, headers: ["Authorization": "Client-ID bef87913eb202e9"], encodingCompletion: { (encodingResult) in - switch encodingResult { - case .success(let upload, _, _): - print("Success") - upload.uploadProgress { progress in - DispatchQueue.main.async { - print(progress.fractionCompleted) - self.progressBar.setProgress(Float(progress.fractionCompleted), animated: true) - } - } - upload.responseJSON { response in - debugPrint(response) - let link = JSON(response.value!)["data"]["link"].stringValue + }, to: "https://api.imgur.com/3/image", method: .post, headers: ["Authorization": "Client-ID bef87913eb202e9"]) + .uploadProgress(closure: { (progress) in + DispatchQueue.main.async { + print(progress.fractionCompleted) + self.progressBar.setProgress(Float(progress.fractionCompleted), animated: true) + } + }) + .responseJSON { (response) in + switch response.result { + case .success(let result): + debugPrint(result) + if let json = result as? NSDictionary, let link = (json["data"] as? NSDictionary)?["link"] as? String { print("Link is \(link)") if count == assets.count { completion(link) } + } else { + completion("Failure") } - case .failure: completion("Failure") } - }) + } }) } } @@ -469,7 +470,7 @@ public class ToolbarTextView: NSObject { }) if results.count > 1 { - Alamofire.request("https://api.imgur.com/3/album", method: .post, parameters: nil, encoding: JSONEncoding.default, headers: ["Authorization": "Client-ID bef87913eb202e9"]) + AF.request("https://api.imgur.com/3/album", method: .post, parameters: nil, encoding: JSONEncoding.default, headers: ["Authorization": "Client-ID bef87913eb202e9"]) .responseJSON { response in print(response) if let status = response.response?.statusCode { @@ -638,42 +639,41 @@ public class ToolbarTextView: NSObject { return } - Alamofire.upload(multipartFormData: { (multipartFormData) in + AF.upload(multipartFormData: { (multipartFormData) in multipartFormData.append(data, withName: "image", fileName: UUID().uuidString + ".jpeg", mimeType: "image/jpg") + if !album.isEmpty { multipartFormData.append(album.data(using: .utf8)!, withName: "album") } - }, to: "https://api.imgur.com/3/image", method: .post, headers: ["Authorization": "Client-ID bef87913eb202e9"], encodingCompletion: { (encodingResult) in - switch encodingResult { - case .success(let upload, _, _): - print("Success") - upload.uploadProgress { progress in - DispatchQueue.main.async { - print(progress.fractionCompleted) - self.progressBar.setProgress(Float(progress.fractionCompleted), animated: true) - } - } - upload.responseJSON { response in - if let val = response.value { - let json = JSON(val) - debugPrint(response) - let link = json["data"]["link"].stringValue - if link.isEmpty { - if json["data"]["error"].stringValue != "" { - tryUploadWithSize(size: size - 0.1) - return - } - } - print("Link is \(link)") - if count == results.count { - completion(link, true) + }, to: "https://api.imgur.com/3/image", method: .post, headers: ["Authorization": "Client-ID bef87913eb202e9"]) + .uploadProgress(closure: { (progress) in + DispatchQueue.main.async { + print(progress.fractionCompleted) + self.progressBar.setProgress(Float(progress.fractionCompleted), animated: true) + } + }) + .responseJSON { (response) in + switch response.result { + case .success(let result): + if let val = response.value { + let json = JSON(val) + debugPrint(response) + let link = json["data"]["link"].stringValue + if link.isEmpty { + if json["data"]["error"].stringValue != "" { + tryUploadWithSize(size: size - 0.1) + return } } + print("Link is \(link)") + if count == results.count { + completion(link, true) + } } case .failure: completion("Failure", false) } - }) + } } tryUploadWithSize(size: 1) diff --git a/Slide for Reddit/TrendingViewController.swift b/Slide for Reddit/TrendingViewController.swift index 23a6ca64b..de85ebe29 100644 --- a/Slide for Reddit/TrendingViewController.swift +++ b/Slide for Reddit/TrendingViewController.swift @@ -31,7 +31,7 @@ class TrendingViewController: UITableViewController { do { let requestString = "https://www.reddit.com/api/trending_searches_v1.json?always_show_media=1&api_type=json&expand_srs=1&feature=link_preview&from_detail=1&obey_over18=1&raw_json=1&sr_detail=1" - taskSearches = Alamofire.request(requestString, method: .get).responseString { response in + taskSearches = AF.request(requestString, method: .get).responseString { response in do { guard let data = response.data else { return @@ -66,7 +66,7 @@ class TrendingViewController: UITableViewController { } do { let requestString = "https://www.reddit.com/api/trending_subreddits.json" - taskSubs = Alamofire.request(requestString, method: .get).responseString { response in + taskSubs = AF.request(requestString, method: .get).responseString { response in do { guard let data = response.data else { return diff --git a/Slide for Reddit/UIAlert+Extensions.swift b/Slide for Reddit/UIAlert+Extensions.swift index bbc2df40f..dd262d0d4 100644 --- a/Slide for Reddit/UIAlert+Extensions.swift +++ b/Slide for Reddit/UIAlert+Extensions.swift @@ -92,7 +92,7 @@ extension UIAlertController { } } visualEffectView?.effect = UIBlurEffect(style: UIColor.isLightTheme ? UIBlurEffect.Style.light : UIBlurEffect.Style.dark) - if self.preferredStyle == .actionSheet && UIDevice.current.userInterfaceIdiom != .pad { + if self.preferredStyle == .actionSheet && !UIDevice.current.respectIpadLayout() { cancelActionView?.backgroundColor = UIColor.foregroundColor } } diff --git a/Slide for Reddit/UIApplication+Extensions.swift b/Slide for Reddit/UIApplication+Extensions.swift index 62ecf1d26..b2cdada0f 100644 --- a/Slide for Reddit/UIApplication+Extensions.swift +++ b/Slide for Reddit/UIApplication+Extensions.swift @@ -13,8 +13,11 @@ extension UIApplication { var statusBarView: UIView? { return statusBarUIView } - +} + +extension UIDevice { public func isMac() -> Bool { + return false //Disable new Mac features for now if #available(iOS 14.0, *) { return ProcessInfo.processInfo.isiOSAppOnMac || ProcessInfo.processInfo.isMacCatalystApp } else if #available(iOS 13.0, *) { @@ -24,6 +27,19 @@ extension UIApplication { } } + public func isMacReal() -> Bool { + if #available(iOS 14.0, *) { + return ProcessInfo.processInfo.isiOSAppOnMac || ProcessInfo.processInfo.isMacCatalystApp + } else if #available(iOS 13.0, *) { + return ProcessInfo.processInfo.isMacCatalystApp + } else { + return false + } + } + + public func respectIpadLayout() -> Bool { + return UIDevice.current.userInterfaceIdiom == .pad || isMacReal() + } } extension UIApplication { public var isSplitOrSlideOver: Bool { diff --git a/Slide for Reddit/VCPresenter.swift b/Slide for Reddit/VCPresenter.swift index 677bca260..4268780a7 100644 --- a/Slide for Reddit/VCPresenter.swift +++ b/Slide for Reddit/VCPresenter.swift @@ -39,16 +39,20 @@ public class VCPresenter { } } } - if (UIDevice.current.userInterfaceIdiom != .pad && viewController is PagingCommentViewController && !parentIs13) || (viewController is WebsiteViewController && parentNavigationController != nil) || viewController is SFHideSafariViewController || SettingValues.disable13Popup { - override13 = false + + if UIDevice.current.isMac() { + parentIs13 = false } + if (!UIDevice.current.respectIpadLayout() && viewController is PagingCommentViewController && !parentIs13) || (viewController is WebsiteViewController && parentNavigationController != nil) || viewController is SFHideSafariViewController || SettingValues.disable13Popup { + override13 = false + } // Yes, this logic is a mess. I need to redo it sometime... let respectedOverride13 = override13 var shouldPopup = popupIfPossible - if UIDevice.current.userInterfaceIdiom == .pad { + if UIDevice.current.respectIpadLayout() || UIDevice.current.isMac() { if viewController is SingleSubredditViewController && SettingValues.disableSubredditPopupIpad { shouldPopup = false } else if (viewController is CommentViewController || viewController is PagingCommentViewController) && SettingValues.disablePopupIpad { @@ -56,50 +60,89 @@ public class VCPresenter { } } - override13 = override13 && (UIDevice.current.userInterfaceIdiom == .pad || (viewController is UIPageViewController || viewController is SettingsViewController)) + override13 = override13 && (UIDevice.current.respectIpadLayout() || (viewController is UIPageViewController || viewController is SettingsViewController)) - if (viewController is PagingCommentViewController || viewController is CommentViewController || viewController is WebsiteViewController) && (parentViewController?.splitViewController != nil && UIDevice.current.userInterfaceIdiom == .pad && (SettingValues.appMode != .MULTI_COLUMN && SettingValues.appMode != .SINGLE)) && !(parentViewController is CommentViewController) && (!override13 || !parentIs13) { + if (viewController is PagingCommentViewController || viewController is CommentViewController || (viewController is WebsiteViewController && !((viewController as! WebsiteViewController).url?.absoluteString.contains("login.compact") ?? false))) && (parentViewController?.splitViewController != nil && UIDevice.current.respectIpadLayout() && (SettingValues.appMode != .MULTI_COLUMN && SettingValues.appMode != .SINGLE)) && !(parentViewController is CommentViewController) && (!override13 || !parentIs13) { (parentViewController!.splitViewController)?.showDetailViewController(SwipeForwardNavigationController(rootViewController: viewController), sender: nil) return - } else if ((!SettingValues.disablePopupIpad) && UIDevice.current.userInterfaceIdiom == .pad && shouldPopup) || ((parentNavigationController != nil && (override13 || parentNavigationController!.modalPresentationStyle != .pageSheet)) && shouldPopup && override13) || parentNavigationController == nil { + } else if ((!SettingValues.disablePopupIpad) && UIDevice.current.respectIpadLayout() && shouldPopup) || ((parentNavigationController != nil && (override13 || parentNavigationController!.modalPresentationStyle != .pageSheet)) && shouldPopup && override13) || parentNavigationController == nil { - if viewController is SingleSubredditViewController { - (viewController as! SingleSubredditViewController).isModal = true - } + if UIDevice.current.isMac(), #available(iOS 13, *) { + if viewController is SettingsViewController { + UIApplication.shared.requestSceneSessionActivation(nil, + userActivity: NSUserActivity(activityType: "settings"), + options: nil, + errorHandler: nil) + + } else if viewController is SingleSubredditViewController { + let activity = NSUserActivity(activityType: "subreddit") + activity.userInfo = ["subreddit": (viewController as! SingleSubredditViewController).sub] + UIApplication.shared.requestSceneSessionActivation(nil, + userActivity: activity, + options: nil, + errorHandler: nil) + + } else if viewController is InboxViewController { + let activity = NSUserActivity(activityType: "inbox") + UIApplication.shared.requestSceneSessionActivation(nil, + userActivity: activity, + options: nil, + errorHandler: nil) + + } else if viewController is ProfileViewController { + let activity = NSUserActivity(activityType: "profile") + activity.userInfo = ["profile": (viewController as! ProfileViewController).name] + UIApplication.shared.requestSceneSessionActivation(nil, + userActivity: activity, + options: nil, + errorHandler: nil) + } else if viewController is WebsiteViewController { + let activity = NSUserActivity(activityType: "website") + activity.userInfo = ["url": (viewController as! WebsiteViewController).url] + UIApplication.shared.requestSceneSessionActivation(nil, + userActivity: activity, + options: nil, + errorHandler: nil) + } + } else { + if viewController is SingleSubredditViewController { + (viewController as! SingleSubredditViewController).isModal = true + } - let newParent = TapBehindModalViewController.init(rootViewController: viewController) + let newParent = TapBehindModalViewController.init(rootViewController: viewController) - newParent.navigationBar.shadowImage = UIImage() - newParent.navigationBar.isTranslucent = false + newParent.navigationBar.shadowImage = UIImage() + newParent.navigationBar.isTranslucent = false - let button = UIButtonWithContext(buttonImage: UIImage(sfString: SFSymbol.xmark, overrideString: "close")) - button.parentController = newParent - button.imageView?.contentMode = UIView.ContentMode.scaleAspectFit - button.addTarget(self, action: #selector(VCPresenter.handleCloseNav(controller:)), for: .touchUpInside) + let button = UIButtonWithContext(buttonImage: UIImage(sfString: SFSymbol.xmark, overrideString: "close")) + button.parentController = newParent + button.imageView?.contentMode = UIView.ContentMode.scaleAspectFit + button.addTarget(self, action: #selector(VCPresenter.handleCloseNav(controller:)), for: .touchUpInside) - let barButton = UIBarButtonItem.init(customView: button) + let barButton = UIBarButtonItem.init(customView: button) - // Let's figure out how to present it - let small: Bool = shouldPopup && UIScreen.main.traitCollection.userInterfaceIdiom == .pad && UIApplication.shared.statusBarOrientation != .portrait + // Let's figure out how to present it + let small: Bool = shouldPopup && UIDevice.current.respectIpadLayout() && UIApplication.shared.statusBarOrientation != .portrait - if small || override13 || respectedOverride13 { - newParent.modalPresentationStyle = .pageSheet - if !override13 && !respectedOverride13 { + if small || override13 || respectedOverride13 { + newParent.modalPresentationStyle = .pageSheet + if !override13 && !respectedOverride13 { + newParent.modalTransitionStyle = .crossDissolve + } + } else { + newParent.modalPresentationStyle = .fullScreen newParent.modalTransitionStyle = .crossDissolve } - } else { - newParent.modalPresentationStyle = .fullScreen - newParent.modalTransitionStyle = .crossDissolve - } - viewController.navigationItem.leftBarButtonItems = [barButton] + viewController.navigationItem.leftBarButtonItems = [barButton] - parentViewController!.present(newParent, animated: true, completion: nil) - if viewController is SFHideSafariViewController { - newParent.setNavigationBarHidden(true, animated: false) - } - if !(viewController is SingleSubredditViewController) { - viewController.setupBaseBarColors() + parentViewController!.present(newParent, animated: true, completion: nil) + if viewController is SFHideSafariViewController { + newParent.setNavigationBarHidden(true, animated: false) + } + if !(viewController is SingleSubredditViewController) { + viewController.setupBaseBarColors() + } } } else { let button = UIButtonWithContext(buttonImage: UIImage(sfString: SFSymbol.chevronLeft, overrideString: "close")) diff --git a/Slide for Reddit/VideoMediaDownloader.swift b/Slide for Reddit/VideoMediaDownloader.swift index 7047a2f37..37888530e 100644 --- a/Slide for Reddit/VideoMediaDownloader.swift +++ b/Slide for Reddit/VideoMediaDownloader.swift @@ -51,11 +51,11 @@ class VideoMediaDownloader { } func testQuality(urlToLoad: String, quality: String, completion: @escaping(_ success: Bool, _ url: String) -> Void) { - Alamofire.request(urlToLoad.replacingOccurrences(of: "HLSPlaylist.m3u8", with: "DASH_\(quality)"), method: .get).responseString { response in + AF.request(urlToLoad.replacingOccurrences(of: "HLSPlaylist.m3u8", with: "DASH_\(quality)"), method: .get).responseString { response in if response.response?.statusCode == 200 { completion(response.response?.statusCode ?? 0 == 200, urlToLoad.replacingOccurrences(of: "HLSPlaylist.m3u8", with: "DASH_\(quality)")) } else { - Alamofire.request(urlToLoad.replacingOccurrences(of: "HLSPlaylist.m3u8", with: "DASH_\(quality).mp4"), method: .get).responseString { response in + AF.request(urlToLoad.replacingOccurrences(of: "HLSPlaylist.m3u8", with: "DASH_\(quality).mp4"), method: .get).responseString { response in completion(response.response?.statusCode ?? 0 == 200, urlToLoad.replacingOccurrences(of: "HLSPlaylist.m3u8", with: "DASH_\(quality).mp4")) } } @@ -93,7 +93,7 @@ class VideoMediaDownloader { self.completion(URL(fileURLWithPath: self.getKeyFromURL())) }) } else { - request = Alamofire.download(URL(string: baseURL)!, method: .get, to: { (_, _) -> (destinationURL: URL, options: DownloadRequest.DownloadOptions) in + request = AF.download(URL(string: baseURL)!, method: .get, to: { (_, _) -> (destinationURL: URL, options: DownloadRequest.Options) in return (URL(fileURLWithPath: self.videoType == .REDDIT ? self.getKeyFromURL().replacingOccurrences(of: ".mp4", with: "video.mp4") : self.getKeyFromURL()), [.createIntermediateDirectories]) }).downloadProgress() { progress in DispatchQueue.main.async { @@ -161,7 +161,7 @@ class VideoMediaDownloader { let localUrlV = URL.init(fileURLWithPath: key.replacingOccurrences(of: ".mp4", with: "video.mp4")) let localUrlAudio = URL.init(fileURLWithPath: key.replacingOccurrences(of: ".mp4", with: "audio.mp4")) - Alamofire.request(toLoadAudio).responseString { (response) in + AF.request(toLoadAudio).responseString { (response) in if response.response?.statusCode == 200 { // Audio exists, let's get it if let url = URL(string: toLoadAudio) { self.requestWithProgress(url: url, localUrlAudio: localUrlAudio) { (response) in @@ -184,7 +184,7 @@ class VideoMediaDownloader { self.doCopy(localUrlV, to: finalUrl) } } else if response.response?.statusCode ?? 0 > 400 { // Might exist elsewhere - Alamofire.request("\(toLoadAudioBase)/audio").responseString { (response) in + AF.request("\(toLoadAudioBase)/audio").responseString { (response) in if response.response?.statusCode == 200 { // Audio exists, let's get it if let url = URL(string: "\(toLoadAudioBase)/audio") { self.requestWithProgress(url: url, localUrlAudio: localUrlAudio) { (response) in @@ -216,8 +216,8 @@ class VideoMediaDownloader { } } - func requestWithProgress(url: URL, localUrlAudio: URL, callback: @escaping (DownloadResponse) -> Void) { - self.request = Alamofire.download(url, method: .get, to: { (_, _) -> (destinationURL: URL, options: DownloadRequest.DownloadOptions) in + func requestWithProgress(url: URL, localUrlAudio: URL, callback: @escaping (AFDownloadResponse) -> Void) { + self.request = AF.download(url, method: .get, to: { (_, _) -> (destinationURL: URL, options: DownloadRequest.Options) in return (localUrlAudio, [.removePreviousFile, .createIntermediateDirectories]) }).downloadProgress() { progress in DispatchQueue.main.async { diff --git a/Slide for Reddit/VideoMediaViewController.swift b/Slide for Reddit/VideoMediaViewController.swift index 0db75f8bd..b2e709119 100644 --- a/Slide for Reddit/VideoMediaViewController.swift +++ b/Slide for Reddit/VideoMediaViewController.swift @@ -11,7 +11,9 @@ import Anchorage import AVFoundation import SDCAlertView import SDWebImage -import SubtleVolume +#if os(iOS) + import SubtleVolume +#endif import Then import UIKit @@ -32,7 +34,8 @@ class VideoMediaViewController: EmbeddableMediaViewController, UIGestureRecogniz }, completion: nil) } } - let volume = SubtleVolume(style: SubtleVolumeStyle.rounded) + + var volume: SubtleVolume? let volumeHeight: CGFloat = 3 var setOnce = false @@ -89,6 +92,8 @@ class VideoMediaViewController: EmbeddableMediaViewController, UIGestureRecogniz var fastForwardImageView = UIImageView() var rewindImageView = UIImageView() + private var volumeObserver: NSKeyValueObservation! + override func viewDidLoad() { super.viewDidLoad() @@ -106,30 +111,35 @@ class VideoMediaViewController: EmbeddableMediaViewController, UIGestureRecogniz strongSelf.handleHideUI(hideTitle: true) }) - volume.barTintColor = .white - volume.barBackgroundColor = UIColor.white.withAlphaComponent(0.3) - volume.animation = .slideDown - - var is13 = false if #available(iOS 13, *) { - is13 = true - } - if !((parent?.parent) is ShadowboxLinkViewController) && !is13 { - view.addSubview(volume) - volume.delegate = self - NotificationCenter.default.addObserver(volume, selector: #selector(SubtleVolume.resume), name: UIApplication.didBecomeActiveNotification, object: nil) + + } else { + if !((parent?.parent) is ShadowboxLinkViewController) { + volume = SubtleVolume(style: SubtleVolumeStyle.rounded) + volume!.barTintColor = .white + volume!.barBackgroundColor = UIColor.white.withAlphaComponent(0.3) + volume!.animation = .slideDown + view.addSubview(volume!) + volume!.delegate = self + NotificationCenter.default.addObserver(volume!, selector: #selector(SubtleVolume.resume), name: UIApplication.didBecomeActiveNotification, object: nil) + } } } override func viewDidLayoutSubviews() { - layoutVolume() + if #available(iOS 13, *) { + } else { + layoutVolume() + } } func layoutVolume() { let volumeYPadding: CGFloat = 10 let volumeXPadding = UIScreen.main.bounds.width * 0.4 / 2 - volume.superview?.bringSubviewToFront(volume) - volume.frame = CGRect(x: safeAreaInsets.left + volumeXPadding, y: safeAreaInsets.top + volumeYPadding, width: UIScreen.main.bounds.width - (volumeXPadding * 2) - safeAreaInsets.left - safeAreaInsets.right, height: volumeHeight) + if let volume = volume { + volume.superview?.bringSubviewToFront(volume) + volume.frame = CGRect(x: safeAreaInsets.left + volumeXPadding, y: safeAreaInsets.top + volumeYPadding, width: UIScreen.main.bounds.width - (volumeXPadding * 2) - safeAreaInsets.left - safeAreaInsets.right, height: volumeHeight) + } } func stopDisplayLink() { @@ -152,6 +162,7 @@ class VideoMediaViewController: EmbeddableMediaViewController, UIGestureRecogniz override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) + volumeObserver?.invalidate() VideoMediaViewController.soundLocked = false } @@ -453,6 +464,13 @@ class VideoMediaViewController: EmbeddableMediaViewController, UIGestureRecogniz @objc func handleHideUI(hideTitle: Bool) { if !self.scrubber.isHidden || hideTitle { + if SettingValues.tapExitMedia { + if let parent = parent as? ModalMediaViewController { + parent.exit() + return + } + } + if let parent = parent as? ModalMediaViewController { parent.fullscreen(self, hideTitle) } @@ -581,11 +599,11 @@ class VideoMediaViewController: EmbeddableMediaViewController, UIGestureRecogniz } func testQuality(urlToLoad: String, quality: String, completion: @escaping(_ success: Bool, _ url: String) -> Void) { - Alamofire.request(urlToLoad.replacingOccurrences(of: "HLSPlaylist.m3u8", with: "DASH_\(quality)"), method: .get).responseString { response in + AF.request(urlToLoad.replacingOccurrences(of: "HLSPlaylist.m3u8", with: "DASH_\(quality)"), method: .get).responseString { response in if response.response?.statusCode == 200 { completion(response.response?.statusCode ?? 0 == 200, urlToLoad.replacingOccurrences(of: "HLSPlaylist.m3u8", with: "DASH_\(quality)")) } else { - Alamofire.request(urlToLoad.replacingOccurrences(of: "HLSPlaylist.m3u8", with: "DASH_\(quality).mp4"), method: .get).responseString { response in + AF.request(urlToLoad.replacingOccurrences(of: "HLSPlaylist.m3u8", with: "DASH_\(quality).mp4"), method: .get).responseString { response in completion(response.response?.statusCode ?? 0 == 200, urlToLoad.replacingOccurrences(of: "HLSPlaylist.m3u8", with: "DASH_\(quality).mp4")) } } @@ -620,7 +638,7 @@ class VideoMediaViewController: EmbeddableMediaViewController, UIGestureRecogniz print("Downloading " + toLoad) let fileURLPath = self.videoType == .REDDIT ? self.getKeyFromURL().replacingOccurrences(of: ".mp4", with: "video.mp4") : self.getKeyFromURL() - request = Alamofire.download(toLoad, method: .get, to: { (_, _) -> (destinationURL: URL, options: DownloadRequest.DownloadOptions) in + request = AF.download(toLoad, method: .get, to: { (_, _) -> (destinationURL: URL, options: DownloadRequest.Options) in return (URL(fileURLWithPath: fileURLPath), [.createIntermediateDirectories]) }).downloadProgress() { progress in DispatchQueue.main.async { @@ -658,7 +676,7 @@ class VideoMediaViewController: EmbeddableMediaViewController, UIGestureRecogniz let localUrlV = URL.init(fileURLWithPath: videoLocation) let localUrlAudio = URL.init(fileURLWithPath: key.replacingOccurrences(of: ".mp4", with: "audio.mp4")) - Alamofire.request(toLoadAudio).responseString { (response) in + AF.request(toLoadAudio).responseString { (response) in if response.response?.statusCode == 200 { // Audio exists, let's get it self.requestWithProgress(url: finalUrl, localUrlAudio: localUrlAudio) { (response) in if (response.error as NSError?)?.code == NSURLErrorCancelled { // Cancelled, exit @@ -676,7 +694,7 @@ class VideoMediaViewController: EmbeddableMediaViewController, UIGestureRecogniz } } else if response.response?.statusCode ?? 0 > 400 { // Might exist elsewhere - Alamofire.request("\(toLoadAudioBase)/audio").responseString { (response) in + AF.request("\(toLoadAudioBase)/audio").responseString { (response) in if response.response?.statusCode == 200 { // Audio exists, let's get it self.requestWithProgress(url: finalUrl, localUrlAudio: localUrlAudio) { (response) in if (response.error as NSError?)?.code == NSURLErrorCancelled { // Cancelled, exit @@ -715,8 +733,8 @@ class VideoMediaViewController: EmbeddableMediaViewController, UIGestureRecogniz } } - func requestWithProgress(url: URL, localUrlAudio: URL, callback: @escaping (DownloadResponse) -> Void) { - self.request = Alamofire.download(url, method: .get, to: { (_, _) -> (destinationURL: URL, options: DownloadRequest.DownloadOptions) in + func requestWithProgress(url: URL, localUrlAudio: URL, callback: @escaping (DownloadResponse) -> Void) { + self.request = AF.download(url, method: .get, to: { (_, _) -> (destinationURL: URL, options: DownloadRequest.Options) in return (localUrlAudio, [.removePreviousFile, .createIntermediateDirectories]) }).downloadProgress() { progress in DispatchQueue.main.async { @@ -733,7 +751,7 @@ class VideoMediaViewController: EmbeddableMediaViewController, UIGestureRecogniz DispatchQueue.global(qos: .background).async { do { try AVAudioSession.sharedInstance().setCategory(.ambient, options: [.mixWithOthers]) - try AVAudioSession.sharedInstance().setActive(true) + try AVAudioSession.sharedInstance().setActive(true, options: .notifyOthersOnDeactivation) } catch let error as NSError { print(error) } @@ -1060,9 +1078,6 @@ extension VideoMediaViewController { extension VideoMediaViewController { @objc func displayLinkDidUpdate(displaylink: CADisplayLink) { if isYoutubeView { - if youtubeMute && muteButton.isHidden && SettingValues.muteYouTube { - muteButton.isHidden = false - } if !sliderBeingUsed { youtubeView.getCurrentTime { [weak self] (currentTime: Float, error: Error?) in if error == nil { @@ -1074,10 +1089,8 @@ extension VideoMediaViewController { let hasAudioTracks = isYoutubeView || (videoView.player?.currentItem?.tracks.count ?? 1) > 1 - if hasAudioTracks { - if (videoView.player?.isMuted ?? youtubeMute) && muteButton.isHidden && (isYoutubeView ? SettingValues.muteYouTube : SettingValues.muteVideosInModal) { - muteButton.isHidden = false - } + if hasAudioTracks && muteButton.isHidden { + muteButton.isHidden = false } if !setOnce || lastTracks != hasAudioTracks { @@ -1106,6 +1119,14 @@ extension VideoMediaViewController { NSLog(error.localizedDescription) } } + + volumeObserver = AVAudioSession.sharedInstance().observe(\.outputVolume) { [weak self] (_, _) in + guard let self = self else { return } + + if self.videoView.player?.isMuted ?? false || self.youtubeMute { + self.unmute() + } + } } guard let player = videoView.player else { @@ -1146,7 +1167,7 @@ extension VideoMediaViewController: WKYTPlayerViewDelegate { } } - try AVAudioSession.sharedInstance().setActive(true) + try AVAudioSession.sharedInstance().setActive(true, options: .notifyOthersOnDeactivation) } catch let error as NSError { print(error) } diff --git a/Slide for Reddit/VideoScrubberView.swift b/Slide for Reddit/VideoScrubberView.swift index d37de2a7d..6f48f95e5 100644 --- a/Slide for Reddit/VideoScrubberView.swift +++ b/Slide for Reddit/VideoScrubberView.swift @@ -69,17 +69,16 @@ class VideoScrubberView: UIView { super.init(frame: frame) slider.tintColor = ColorUtil.accentColorForSub(sub: "") -// slider.setThumbImage(UIImage(named: "circle")?.getCopy(withSize: .square(size: 72), withColor: slider.tintColor), for: .normal) slider.minimumValue = 0 slider.maximumValue = 1 slider.isContinuous = true -// slider.setThumbImage(UIImage(), for: .normal) -// slider.setMinimumTrackImage(UIImage.image(with: slider.tintColor).getCopy(withSize: .square(size: 72)), for: .normal) -// slider.setMaximumTrackImage(UIImage.image(with: slider.tintColor.withAlphaComponent(0.4)).getCopy(withSize: .square(size: 72)), for: .normal) -// slider.thumbTintColor = ColorUtil.accentColorForSub(sub: "") - slider.minimumTrackTintColor = ColorUtil.accentColorForSub(sub: "") - slider.maximumTrackTintColor = ColorUtil.accentColorForSub(sub: "").withAlphaComponent(0.4) - slider.setThumbImage(UIImage(named: "circle")?.getCopy(withSize: CGSize.square(size: 20), withColor: .white), for: .normal) + + if !UIDevice.current.isMac() { + slider.minimumTrackTintColor = ColorUtil.accentColorForSub(sub: "") + slider.maximumTrackTintColor = ColorUtil.accentColorForSub(sub: "").withAlphaComponent(0.4) + + slider.setThumbImage(UIImage(named: "circle")?.getCopy(withSize: CGSize.square(size: 20), withColor: .white), for: .normal) + } self.addSubview(slider) self.addSubview(playButton) @@ -88,15 +87,6 @@ class VideoScrubberView: UIView { slider.heightAnchor /==/ 24 slider.bottomAnchor /==/ self.bottomAnchor - 4 slider.leftAnchor /==/ timeTotalLabel.rightAnchor + 8 - - // timeElapsedLabel.font = UIFont.boldSystemFont(ofSize: 12) - // timeElapsedLabel.textAlignment = .center - // timeElapsedLabel.textColor = UIColor.white - // self.addSubview(timeElapsedLabel) - // timeElapsedLabel.centerYAnchor /==/ slider.centerYAnchor - // timeElapsedLabel.leftAnchor />=/ slider.leftAnchor ~ .high -// timeElapsedRightConstraint = timeElapsedLabel.rightAnchor /==/ CGFloat(slider.thumbCenterX - 16) ~ .low -// slider timeTotalLabel.font = UIFont.monospacedDigitSystemFont(ofSize: 12, weight: UIFont.Weight(rawValue: 10)) timeTotalLabel.textAlignment = .center @@ -172,7 +162,9 @@ extension VideoScrubberView { @objc func sliderDidBeginDragging(_ sender: ThickSlider) { delegate?.sliderDidBeginDragging() - slider.setThumbImage(largeThumbImage, for: .normal) + if !UIDevice.current.isMac() { + slider.setThumbImage(largeThumbImage, for: .normal) + } UIView.animate(withDuration: 0.3) { self.playButton.isHidden = true } @@ -180,7 +172,9 @@ extension VideoScrubberView { @objc func sliderDidEndDragging(_ sender: ThickSlider) { delegate?.sliderDidEndDragging() - slider.setThumbImage(smallThumbImage, for: .normal) + if !UIDevice.current.isMac() { + slider.setThumbImage(smallThumbImage, for: .normal) + } UIView.animate(withDuration: 0.3) { self.playButton.isHidden = false } diff --git a/Slide for Reddit/VideoSource.swift b/Slide for Reddit/VideoSource.swift index 58acb8494..37edcdae0 100644 --- a/Slide for Reddit/VideoSource.swift +++ b/Slide for Reddit/VideoSource.swift @@ -117,6 +117,7 @@ class StreamableVideoSource: VideoSource { let hash = url.substring(url.lastIndexOf("/")! + 1, length: url.length - (url.lastIndexOf("/")! + 1)) let finalURL = URL(string: "https://api.streamable.com/videos/" + hash) + if finalURL == nil { failure?() return nil @@ -158,6 +159,9 @@ class StreamableVideoSource: VideoSource { } } catch let error as NSError { print(error) + DispatchQueue.main.async { + failure?() + } } } } diff --git a/Slide for Reddit/WebsiteViewController.swift b/Slide for Reddit/WebsiteViewController.swift index 23fc2c3bf..a87f13693 100644 --- a/Slide for Reddit/WebsiteViewController.swift +++ b/Slide for Reddit/WebsiteViewController.swift @@ -89,7 +89,11 @@ class WebsiteViewController: MediaViewController, WKNavigationDelegate { items.append(forwardB) items.append(space) - toolbarItems = items + if UIDevice.current.isMac() { + navigationItem.rightBarButtonItems = items + } else { + toolbarItems = items + } } @objc func goBack() { @@ -294,7 +298,7 @@ class WebsiteViewController: MediaViewController, WKNavigationDelegate { } func loadUrl() { - if url?.host == "twitter.com" && UIDevice.current.userInterfaceIdiom == .pad { + if url?.host == "twitter.com" && UIDevice.current.respectIpadLayout() { webView.customUserAgent = "Googlebot/2.1 (+http://www.google.com/bot.html)" } let myURLRequest: URLRequest = URLRequest(url: url!) @@ -373,7 +377,7 @@ class WebsiteViewController: MediaViewController, WKNavigationDelegate { if #available(iOS 13.0, *) { // Let Reddit create new reddit_session Cookie from data returned from Apple Login let jsonData = try JSONSerialization.data(withJSONObject: params, options: .withoutEscapingSlashes) - Alamofire.request("https://www.reddit.com/account/identity_provider_login", method: .post, parameters: [:], encoding: String(data: jsonData, encoding: .utf8)!, headers: nil).responseJSON { (response) in + AF.request("https://www.reddit.com/account/identity_provider_login", method: .post, parameters: [:], encoding: String(data: jsonData, encoding: .utf8)!, headers: nil).responseJSON { (response) in switch response.result { case .success(let JSON): let token = (JSON as? [String: Any])?["token"] as? String ?? "" @@ -450,7 +454,7 @@ class WebsiteViewController: MediaViewController, WKNavigationDelegate { // Get user csrf token for Alamofire, which will be used to authorize next @objc func loginWithApple() { - Alamofire.request("https://www.reddit.com/account/login/?mobile_ui=on&experiment_mweb_sso_login_link=enabled&experiment_mweb_google_onetap=onetap_auto&experiment_mweb_am_refactoring=enabled", method: .get, parameters: [:], encoding: URLEncoding.default, headers: nil).response { (response) in + AF.request("https://www.reddit.com/account/login/?mobile_ui=on&experiment_mweb_sso_login_link=enabled&experiment_mweb_google_onetap=onetap_auto&experiment_mweb_am_refactoring=enabled", method: .get, parameters: [:], encoding: URLEncoding.default, headers: nil).response { (response) in if let data = response.data, let stringBody = String(data: data, encoding: .utf8) { // Get token out of body HTML diff --git a/Slide for Reddit/WrappingFlowLayout.swift b/Slide for Reddit/WrappingFlowLayout.swift index 91aedf8a9..ad7b7a8f4 100644 --- a/Slide for Reddit/WrappingFlowLayout.swift +++ b/Slide for Reddit/WrappingFlowLayout.swift @@ -48,11 +48,11 @@ class WrappingFlowLayout: UICollectionViewLayout { cache = [] contentHeight = 0 var portraitCount = SettingValues.portraitMultiColumnCount - let pad = UIScreen.main.traitCollection.userInterfaceIdiom == .pad + let pad = UIDevice.current.respectIpadLayout() - if SettingValues.appMode == .MULTI_COLUMN { - if UIApplication.shared.statusBarOrientation.isPortrait || (vc.presentingViewController != nil && (vc.modalPresentationStyle == .pageSheet || vc.modalPresentationStyle == .fullScreen)) { - if UIScreen.main.traitCollection.userInterfaceIdiom != .pad { + if SettingValues.appMode == .MULTI_COLUMN || SettingValues.appMode == .TRIPLE_MULTI_COLUMN { + if (UIApplication.shared.statusBarOrientation.isPortrait && !UIDevice.current.isMacReal()) || (vc.presentingViewController != nil && (vc.modalPresentationStyle == .pageSheet || vc.modalPresentationStyle == .fullScreen)) { + if !pad { numberOfColumns = SettingValues.portraitMultiColumnCount } else { if SettingValues.disableMulticolumnCollections && vc is ContentListingViewController { @@ -68,7 +68,7 @@ class WrappingFlowLayout: UICollectionViewLayout { numberOfColumns = 1 } - if !UIApplication.shared.isMac() { + if !UIDevice.current.isMacReal() { if pad && UIApplication.shared.keyWindow?.frame != UIScreen.main.bounds || UIApplication.shared.isSplitOrSlideOver { numberOfColumns = 1 } @@ -92,6 +92,7 @@ class WrappingFlowLayout: UICollectionViewLayout { if isGallery { numberOfColumns = SettingValues.galleryCount } + cellPadding = (numberOfColumns > 1 && (SettingValues.postViewMode != .LIST) && (SettingValues.postViewMode != .COMPACT)) ? CGFloat(3) : ((SettingValues.postViewMode == .LIST) ? CGFloat(1) : CGFloat(0)) prepare() } diff --git a/WidgetConfigIntent/WidgetConfigIntent.entitlements b/WidgetConfigIntent/WidgetConfigIntent.entitlements index 86d745ebf..41aeeed9d 100644 --- a/WidgetConfigIntent/WidgetConfigIntent.entitlements +++ b/WidgetConfigIntent/WidgetConfigIntent.entitlements @@ -2,9 +2,13 @@ + com.apple.security.app-sandbox + com.apple.security.application-groups - group.$(USR_DOMAIN).redditslide.prefs - + group.$(USR_DOMAIN).redditslide.prefs + + com.apple.security.network.client + diff --git a/fastlane/Fastfile b/fastlane/Fastfile index 276a7c583..ee92d3711 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -11,7 +11,7 @@ # # Uncomment the line if you want fastlane to automatically update itself -# update_fastlane +update_fastlane default_platform(:ios) diff --git a/fastlane/Matchfile b/fastlane/Matchfile index f05510f02..7fd0b6d0d 100644 --- a/fastlane/Matchfile +++ b/fastlane/Matchfile @@ -4,6 +4,7 @@ storage_mode("git") type("development") # The default type, can be: appstore, adhoc, enterprise or development +platform( "ios", "macos") # app_identifier(["tools.fastlane.app", "tools.fastlane.app2"]) # username("user@fastlane.tools") # Your Apple Developer Portal username diff --git a/fastlane/report.xml b/fastlane/report.xml index f00d9cc7a..a8e789231 100644 --- a/fastlane/report.xml +++ b/fastlane/report.xml @@ -5,29 +5,17 @@ - + - + - - - - - - - - - - - - - + diff --git a/slide_ios_rounded.png b/slide_ios_rounded.png deleted file mode 100644 index 5951d2c83..000000000 Binary files a/slide_ios_rounded.png and /dev/null differ