diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 665c689d..449f199b 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -5,7 +5,7 @@ # the repo. Unless a later match takes precedence, # @global-owner1 and @global-owner2 will be requested for # review when someone opens a pull request. -* @ehpanda-maintainers +# * @global-owner1 @global-owner2 # Order is important; the last matching pattern takes the most # precedence. When someone opens a pull request that only @@ -22,7 +22,7 @@ # be identified in the format @org/team-name. Teams must have # explicit write access to the repository. In this example, # the octocats team in the octo-org organization owns all .txt files. -# *.txt @octo-org/octocats +* @EhPanda-Team/ehpanda-maintainers # In this example, @doctocat owns any files in the build/logs # directory at the root of the repository and any of its diff --git a/.github/workflows/dependencies.yml b/.github/workflows/dependencies.yml index 85197711..ead627b2 100644 --- a/.github/workflows/dependencies.yml +++ b/.github/workflows/dependencies.yml @@ -8,7 +8,7 @@ permissions: pull-requests: write jobs: dependencies: - runs-on: macos-15 + runs-on: macos-26 steps: - uses: actions/checkout@v4 with: @@ -19,7 +19,7 @@ jobs: with: forceResolution: true failWhenOutdated: false - xcodePath: '/Applications/Xcode_16.2.app' + xcodePath: '/Applications/Xcode_26.0.1.app' - name: Create Pull Request if: steps.resolution.outputs.dependenciesChanged == 'true' uses: peter-evans/create-pull-request@v7 diff --git a/.github/workflows/deploy-pre-release.yml b/.github/workflows/deploy-pre-release.yml index 36a5fb52..571d459f 100644 --- a/.github/workflows/deploy-pre-release.yml +++ b/.github/workflows/deploy-pre-release.yml @@ -15,7 +15,7 @@ on: required: true type: string env: - DEVELOPER_DIR: /Applications/Xcode_26_beta.app + DEVELOPER_DIR: /Applications/Xcode_26.0.1.app SCHEME_NAME: 'EhPanda' ALTSTORE_JSON_PATH: './AltStore.json' BUILDS_PATH: '/tmp/action-builds' @@ -26,7 +26,7 @@ env: jobs: Deploy: - runs-on: macos-15 + runs-on: macos-26 if: github.event_name == 'workflow_dispatch' steps: - name: Checkout @@ -36,14 +36,19 @@ jobs: git config user.name "github-actions[bot]" git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - name: Install iOS 26 Platform - run: xcodebuild -downloadPlatform iOS + uses: nick-fields/retry@v3 + with: + retry_on: error + max_attempts: 10 + timeout_minutes: 999 + command: xcodebuild -downloadPlatform iOS - name: Show Xcode version run: xcodebuild -version - name: Run tests run: xcodebuild clean test -skipMacroValidation -scheme ${{ env.SCHEME_NAME }} - -destination 'platform=iOS Simulator,name=iPhone 16 Pro' + -destination 'platform=iOS Simulator,name=iPhone Air' - name: Bump version id: bump-version uses: yanamura/ios-bump-version@v1 diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index c95fb1db..37e75998 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -5,8 +5,8 @@ on: - main types: [closed] env: - DEVELOPER_DIR: /Applications/Xcode_16.2.app - APP_VERSION: '2.7.10' + DEVELOPER_DIR: /Applications/Xcode_26.0.1.app + APP_VERSION: '2.8.0' SCHEME_NAME: 'EhPanda' ALTSTORE_JSON_PATH: './AltStore.json' BUILDS_PATH: '/tmp/action-builds' @@ -19,8 +19,11 @@ env: jobs: Deploy: - runs-on: macos-15 - if: github.event.pull_request.merged == true && github.event.pull_request.user.login == 'chihchy' + runs-on: macos-26 + if: | + github.event.pull_request.merged == true && ( + github.event.pull_request.user.login == 'aalberrty' || + github.event.pull_request.user.login == 'chihchy') steps: - name: Checkout uses: actions/checkout@v4 @@ -28,13 +31,20 @@ jobs: run: | git config user.name "github-actions[bot]" git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + - name: Install iOS 26 Platform + uses: nick-fields/retry@v3 + with: + retry_on: error + max_attempts: 10 + timeout_minutes: 999 + command: xcodebuild -downloadPlatform iOS - name: Show Xcode version run: xcodebuild -version - name: Run tests run: xcodebuild clean test -skipMacroValidation -scheme ${{ env.SCHEME_NAME }} - -destination 'platform=iOS Simulator,name=iPhone 16 Pro' + -destination 'platform=iOS Simulator,name=iPhone Air' - name: Bump version id: bump-version uses: yanamura/ios-bump-version@v1 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5015dbcb..e960930e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -2,18 +2,25 @@ name: Test on: [push, workflow_dispatch] env: SCHEME_NAME: 'EhPanda' - DEVELOPER_DIR: /Applications/Xcode_16.2.app + DEVELOPER_DIR: /Applications/Xcode_26.0.1.app jobs: Test: - runs-on: macos-15 + runs-on: macos-26 if: ${{ !contains(github.event.head_commit.message, '[skip test]') }} steps: - name: Checkout uses: actions/checkout@v4 + - name: Install iOS 26 Platform + uses: nick-fields/retry@v3 + with: + retry_on: error + max_attempts: 10 + timeout_minutes: 999 + command: xcodebuild -downloadPlatform iOS - name: Show Xcode version run: xcodebuild -version - name: Run tests run: xcodebuild clean test -skipMacroValidation -scheme ${{ env.SCHEME_NAME }} - -destination 'platform=iOS Simulator,name=iPhone 16 Pro' + -destination 'platform=iOS Simulator,name=iPhone Air' diff --git a/EhPanda.xcodeproj/project.pbxproj b/EhPanda.xcodeproj/project.pbxproj index 5ad090cb..38e9dc45 100644 --- a/EhPanda.xcodeproj/project.pbxproj +++ b/EhPanda.xcodeproj/project.pbxproj @@ -214,14 +214,10 @@ ABC3C78F2593699B00E0C11B /* ViewModifiers.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC3C7762593699A00E0C11B /* ViewModifiers.swift */; }; ABC4A0792751B40E00968A4F /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = ABC4A0782751B40E00968A4F /* Kingfisher */; }; ABC681F326898D46007BBD69 /* Model.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = ABC681F126898D46007BBD69 /* Model.xcdatamodeld */; }; - ABC732C127B8962000D47DA9 /* LiveTextHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC732C027B8962000D47DA9 /* LiveTextHandler.swift */; }; ABC732C527B9024500D47DA9 /* LiveText.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC732C427B9024500D47DA9 /* LiveText.swift */; }; ABC732C727B90F0900D47DA9 /* LiveTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC732C627B90F0900D47DA9 /* LiveTextView.swift */; }; ABC8355D27B118330091DCDB /* DetailSearchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC8355C27B118330091DCDB /* DetailSearchView.swift */; }; ABC8355F27B118370091DCDB /* DetailSearchReducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC8355E27B118370091DCDB /* DetailSearchReducer.swift */; }; - ABC8356127B357C50091DCDB /* GestureHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC8356027B357C50091DCDB /* GestureHandler.swift */; }; - ABC8356327B366760091DCDB /* PageHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC8356227B366760091DCDB /* PageHandler.swift */; }; - ABC8356527B36E550091DCDB /* AutoPlayHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABC8356427B36E550091DCDB /* AutoPlayHandler.swift */; }; ABCA93BE26918DE100A98BC6 /* Persistence.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABCA93BD26918DE100A98BC6 /* Persistence.swift */; }; ABCA93C02691925900A98BC6 /* GalleryMO+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABCA93BF2691925900A98BC6 /* GalleryMO+CoreDataClass.swift */; }; ABCA93C22691929D00A98BC6 /* GalleryDetailMO+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABCA93C12691929D00A98BC6 /* GalleryDetailMO+CoreDataClass.swift */; }; @@ -280,6 +276,10 @@ EA0C925E2C3EB49500D211F6 /* README.jpn.md in Resources */ = {isa = PBXBuildFile; fileRef = EA0C92582C3EB49500D211F6 /* README.jpn.md */; }; EA2E2E7F2A1F7E500038A261 /* SettingReducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA2E2E7E2A1F7E500038A261 /* SettingReducer.swift */; }; EA2E2E822A1FA1060038A261 /* SearchReducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA2E2E812A1FA1050038A261 /* SearchReducer.swift */; }; + EA5AA4A72EA9149E00BC2B5C /* PageHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA5AA4A62EA9149E00BC2B5C /* PageHandler.swift */; }; + EA5AA4A82EA9149E00BC2B5C /* LiveTextHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA5AA4A52EA9149E00BC2B5C /* LiveTextHandler.swift */; }; + EA5AA4A92EA9149E00BC2B5C /* GestureHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA5AA4A42EA9149E00BC2B5C /* GestureHandler.swift */; }; + EA5AA4AA2EA9149E00BC2B5C /* AutoPlayHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA5AA4A32EA9149E00BC2B5C /* AutoPlayHandler.swift */; }; EA698C032CCDD2FB0058BC19 /* EquatableVoid.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA698C022CCDD2FB0058BC19 /* EquatableVoid.swift */; }; EA698C092CCDE7090058BC19 /* IdentifiableBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA698C082CCDE7050058BC19 /* IdentifiableBox.swift */; }; EAE63E2129E2A6330048C601 /* SwiftyBeaver in Frameworks */ = {isa = PBXBuildFile; productRef = EAE63E2029E2A6330048C601 /* SwiftyBeaver */; }; @@ -527,14 +527,10 @@ ABC3C7762593699A00E0C11B /* ViewModifiers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ViewModifiers.swift; sourceTree = ""; }; ABC4A07A2753084100968A4F /* Model 5.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "Model 5.xcdatamodel"; sourceTree = ""; }; ABC681F226898D46007BBD69 /* Model.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = Model.xcdatamodel; sourceTree = ""; }; - ABC732C027B8962000D47DA9 /* LiveTextHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LiveTextHandler.swift; sourceTree = ""; }; ABC732C427B9024500D47DA9 /* LiveText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiveText.swift; sourceTree = ""; }; ABC732C627B90F0900D47DA9 /* LiveTextView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiveTextView.swift; sourceTree = ""; }; ABC8355C27B118330091DCDB /* DetailSearchView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DetailSearchView.swift; sourceTree = ""; }; ABC8355E27B118370091DCDB /* DetailSearchReducer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DetailSearchReducer.swift; sourceTree = ""; }; - ABC8356027B357C50091DCDB /* GestureHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GestureHandler.swift; sourceTree = ""; }; - ABC8356227B366760091DCDB /* PageHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PageHandler.swift; sourceTree = ""; }; - ABC8356427B36E550091DCDB /* AutoPlayHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutoPlayHandler.swift; sourceTree = ""; }; ABCA93BD26918DE100A98BC6 /* Persistence.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Persistence.swift; sourceTree = ""; }; ABCA93BF2691925900A98BC6 /* GalleryMO+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "GalleryMO+CoreDataClass.swift"; sourceTree = ""; }; ABCA93C12691929D00A98BC6 /* GalleryDetailMO+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "GalleryDetailMO+CoreDataClass.swift"; sourceTree = ""; }; @@ -606,6 +602,10 @@ EA0C92582C3EB49500D211F6 /* README.jpn.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; name = README.jpn.md; path = READMEs/README.jpn.md; sourceTree = ""; }; EA2E2E7E2A1F7E500038A261 /* SettingReducer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingReducer.swift; sourceTree = ""; }; EA2E2E812A1FA1050038A261 /* SearchReducer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SearchReducer.swift; sourceTree = ""; }; + EA5AA4A32EA9149E00BC2B5C /* AutoPlayHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutoPlayHandler.swift; sourceTree = ""; }; + EA5AA4A42EA9149E00BC2B5C /* GestureHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GestureHandler.swift; sourceTree = ""; }; + EA5AA4A52EA9149E00BC2B5C /* LiveTextHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiveTextHandler.swift; sourceTree = ""; }; + EA5AA4A62EA9149E00BC2B5C /* PageHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PageHandler.swift; sourceTree = ""; }; EA698C022CCDD2FB0058BC19 /* EquatableVoid.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EquatableVoid.swift; sourceTree = ""; }; EA698C082CCDE7050058BC19 /* IdentifiableBox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdentifiableBox.swift; sourceTree = ""; }; /* End PBXFileReference section */ @@ -710,13 +710,13 @@ AB24C561276757A30085C33A /* Support */ = { isa = PBXGroup; children = ( + EA5AA4A32EA9149E00BC2B5C /* AutoPlayHandler.swift */, + EA5AA4A42EA9149E00BC2B5C /* GestureHandler.swift */, + EA5AA4A52EA9149E00BC2B5C /* LiveTextHandler.swift */, + EA5AA4A62EA9149E00BC2B5C /* PageHandler.swift */, ABC732C627B90F0900D47DA9 /* LiveTextView.swift */, AB69CB8126B3DAF400699359 /* ControlPanel.swift */, AB69CB7F26B3DABC00699359 /* AdvancedList.swift */, - ABC8356227B366760091DCDB /* PageHandler.swift */, - ABC8356027B357C50091DCDB /* GestureHandler.swift */, - ABC732C027B8962000D47DA9 /* LiveTextHandler.swift */, - ABC8356427B36E550091DCDB /* AutoPlayHandler.swift */, ); path = Support; sourceTree = ""; @@ -1855,7 +1855,6 @@ AB86ABF92782EC0D00E61E6A /* AboutView.swift in Sources */, AB7BF2BA27A96562001865A3 /* Gallery.swift in Sources */, AB0929BE2780032400F107CA /* EhSettingReducer.swift in Sources */, - ABC8356127B357C50091DCDB /* GestureHandler.swift in Sources */, AB0929D42781EDDC00F107CA /* UserDefaultsClient.swift in Sources */, AB0929D82782A83A00F107CA /* AuthorizationClient.swift in Sources */, ABF45AEF25F3313D00ECB568 /* TorrentsView.swift in Sources */, @@ -1900,7 +1899,6 @@ AB7BF2AB27A642FB001865A3 /* BrowsingCountry.swift in Sources */, ABD49D60277C7722003D1A07 /* TabBarView.swift in Sources */, AB26F59027ABF21000AB3468 /* Model5toModel6.xcmappingmodel in Sources */, - ABC8356327B366760091DCDB /* PageHandler.swift in Sources */, AB706FA5278C3DDE0025A48A /* PreviewsView.swift in Sources */, ABF45AE725F3313D00ECB568 /* RatingView.swift in Sources */, AB2CED64268AB6AE003130F7 /* GalleryMO+CoreDataProperties.swift in Sources */, @@ -1940,7 +1938,6 @@ AB706F8A278A4CC50025A48A /* PopularReducer.swift in Sources */, ABD49D64277C7AD5003D1A07 /* TabBarReducer.swift in Sources */, ABF45AF025F3313D00ECB568 /* CommentsView.swift in Sources */, - ABC8356527B36E550091DCDB /* AutoPlayHandler.swift in Sources */, ABBB2671279AFA61007B6149 /* EnvironmentKeys.swift in Sources */, AB7BF2DA27AA78CF001865A3 /* Reducer_Extension.swift in Sources */, ABBD2B602768D7AD0072AED2 /* GalleryRankingCell.swift in Sources */, @@ -1957,7 +1954,6 @@ EA698C092CCDE7090058BC19 /* IdentifiableBox.swift in Sources */, AB0CFBD727C3B2D0004BD372 /* TagDetailView.swift in Sources */, AB38A0CB25CA993D00764D64 /* ColorCodable.swift in Sources */, - ABC732C127B8962000D47DA9 /* LiveTextHandler.swift in Sources */, ABBB2675279B933D007B6149 /* ReadingReducer.swift in Sources */, ABF45AF425F3313D00ECB568 /* WebView.swift in Sources */, AB7B29F626AC741600EE1F14 /* GenericList.swift in Sources */, @@ -2000,6 +1996,10 @@ ABBB2638278FBD2F007B6149 /* SwiftUINavigation_Extension.swift in Sources */, AB10117E26986B7D00C2C1A9 /* GalleryStateMO+CoreDataProperties.swift in Sources */, AB26F59627ACCA1800AB3468 /* AppEnv.swift in Sources */, + EA5AA4A72EA9149E00BC2B5C /* PageHandler.swift in Sources */, + EA5AA4A82EA9149E00BC2B5C /* LiveTextHandler.swift in Sources */, + EA5AA4A92EA9149E00BC2B5C /* GestureHandler.swift in Sources */, + EA5AA4AA2EA9149E00BC2B5C /* AutoPlayHandler.swift in Sources */, ABF45AE525F3313D00ECB568 /* PostCommentView.swift in Sources */, AB358313269D7E89009466A5 /* DFRequest.swift in Sources */, AB706F90278A5F680025A48A /* AppDelegateClient.swift in Sources */, @@ -2096,7 +2096,7 @@ INFOPLIST_FILE = ShareExtension/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = ShareExtension; INFOPLIST_KEY_NSHumanReadableCopyright = ""; - IPHONEOS_DEPLOYMENT_TARGET = 17.0; + IPHONEOS_DEPLOYMENT_TARGET = 26.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -2124,7 +2124,7 @@ INFOPLIST_FILE = ShareExtension/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = ShareExtension; INFOPLIST_KEY_NSHumanReadableCopyright = ""; - IPHONEOS_DEPLOYMENT_TARGET = 17.0; + IPHONEOS_DEPLOYMENT_TARGET = 26.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -2274,7 +2274,7 @@ DEVELOPMENT_TEAM = 9SKQ7QTZ74; ENABLE_PREVIEWS = YES; INFOPLIST_FILE = EhPanda/App/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 17.0; + IPHONEOS_DEPLOYMENT_TARGET = 26.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -2303,7 +2303,7 @@ DEVELOPMENT_TEAM = 9SKQ7QTZ74; ENABLE_PREVIEWS = YES; INFOPLIST_FILE = EhPanda/App/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 17.0; + IPHONEOS_DEPLOYMENT_TARGET = 26.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -2327,7 +2327,7 @@ CURRENT_PROJECT_VERSION = 156; DEVELOPMENT_TEAM = 9SKQ7QTZ74; GENERATE_INFOPLIST_FILE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 17.0; + IPHONEOS_DEPLOYMENT_TARGET = 26.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -2354,7 +2354,7 @@ CURRENT_PROJECT_VERSION = 156; DEVELOPMENT_TEAM = 9SKQ7QTZ74; GENERATE_INFOPLIST_FILE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 17.0; + IPHONEOS_DEPLOYMENT_TARGET = 26.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", diff --git a/EhPanda.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/EhPanda.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 00000000..0c67376e --- /dev/null +++ b/EhPanda.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,5 @@ + + + + + diff --git a/EhPanda.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/EhPanda.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 66fbb20b..a94821f1 100644 --- a/EhPanda.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/EhPanda.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -24,8 +24,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/pointfreeco/combine-schedulers", "state" : { - "revision" : "9fa31f4403da54855f1e2aeaeff478f4f0e40b13", - "version" : "1.0.2" + "revision" : "5928286acce13def418ec36d05a001a9641086f2", + "version" : "1.0.3" } }, { @@ -78,8 +78,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/pointfreeco/swift-case-paths", "state" : { - "revision" : "bc92c4b27f9a84bfb498cdbfdf35d5a357e9161f", - "version" : "1.5.6" + "revision" : "6989976265be3f8d2b5802c722f9ba168e227c71", + "version" : "1.7.2" } }, { @@ -87,8 +87,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/pointfreeco/swift-clocks", "state" : { - "revision" : "b9b24b69e2adda099a1fa381cda1eeec272d5b53", - "version" : "1.0.5" + "revision" : "cc46202b53476d64e824e0b6612da09d84ffde8e", + "version" : "1.0.6" } }, { @@ -96,8 +96,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-collections", "state" : { - "revision" : "671108c96644956dddcd89dd59c203dcdb36cec7", - "version" : "1.1.4" + "revision" : "7b847a3b7008b2dc2f47ca3110d8c782fb2e5c7e", + "version" : "1.3.0" } }, { @@ -105,8 +105,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/pointfreeco/swift-composable-architecture", "state" : { - "revision" : "d602618c628e5123f66643437151079d3664970d", - "version" : "1.17.0" + "revision" : "a9c3fecb5d31fc8aad5d8ba5d830924966d7fb15", + "version" : "1.23.0" } }, { @@ -114,8 +114,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/pointfreeco/swift-concurrency-extras", "state" : { - "revision" : "163409ef7dae9d960b87f34b51587b6609a76c1f", - "version" : "1.3.0" + "revision" : "5a3825302b1a0d744183200915a47b508c828e6f", + "version" : "1.3.2" } }, { @@ -132,8 +132,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/pointfreeco/swift-dependencies", "state" : { - "revision" : "5526c8a27675dc7b18d6fa643abfb64bcb200b77", - "version" : "1.6.2" + "revision" : "a10f9feeb214bc72b5337b6ef6d5a029360db4cc", + "version" : "1.10.0" } }, { @@ -141,8 +141,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/pointfreeco/swift-identified-collections", "state" : { - "revision" : "2f5ab6e091dd032b63dacbda052405756010dc3b", - "version" : "1.1.0" + "revision" : "322d9ffeeba85c9f7c4984b39422ec7cc3c56597", + "version" : "1.1.1" } }, { @@ -150,8 +150,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/pointfreeco/swift-navigation", "state" : { - "revision" : "16a27ab7ae0abfefbbcba73581b3e2380b47a579", - "version" : "2.2.2" + "revision" : "bf498690e1f6b4af790260f542e8428a4ba10d78", + "version" : "2.6.0" } }, { @@ -159,8 +159,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/pointfreeco/swift-perception", "state" : { - "revision" : "8d52279b9809ef27eabe7d5420f03734528f19da", - "version" : "1.4.1" + "revision" : "4f47ebafed5f0b0172cf5c661454fa8e28fb2ac4", + "version" : "2.0.9" } }, { @@ -168,8 +168,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/pointfreeco/swift-sharing", "state" : { - "revision" : "b68bf99b05cb974392f6ffa380351e9b7391e233", - "version" : "1.1.0" + "revision" : "3bfc408cc2d0bee2287c174da6b1c76768377818", + "version" : "2.7.4" } }, { @@ -177,8 +177,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/swiftlang/swift-syntax", "state" : { - "revision" : "0687f71944021d616d34d922343dcef086855920", - "version" : "600.0.1" + "revision" : "4799286537280063c85a32f09884cfbca301b1a1", + "version" : "602.0.0" } }, { @@ -249,8 +249,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/pointfreeco/xctest-dynamic-overlay", "state" : { - "revision" : "a3f634d1a409c7979cabc0a71b3f26ffa9fc8af1", - "version" : "1.4.3" + "revision" : "4c27acf5394b645b70d8ba19dc249c0472d5f618", + "version" : "1.7.0" } } ], diff --git a/EhPanda/App/Generated/Strings.swift b/EhPanda/App/Generated/Strings.swift index 7202a961..1af4a177 100644 --- a/EhPanda/App/Generated/Strings.swift +++ b/EhPanda/App/Generated/Strings.swift @@ -90,6 +90,8 @@ internal enum L10n { } internal enum CodeLevelContributor { internal enum Link { + /// https://github.com/aalberrty + internal static let aalberrty = L10n.tr("Constant", "app.code_level_contributor.link.aalberrty", fallback: "https://github.com/aalberrty") /// https://github.com/chihchy internal static let chihchy = L10n.tr("Constant", "app.code_level_contributor.link.chihchy", fallback: "https://github.com/chihchy") /// https://github.com/Jimmy-Prime @@ -100,6 +102,8 @@ internal enum L10n { internal static let xioxin = L10n.tr("Constant", "app.code_level_contributor.link.xioxin", fallback: "https://github.com/xioxin") } internal enum Text { + /// Zack Asahina + internal static let aalberrty = L10n.tr("Constant", "app.code_level_contributor.text.aalberrty", fallback: "Zack Asahina") /// Chihchy internal static let chihchy = L10n.tr("Constant", "app.code_level_contributor.text.chihchy", fallback: "Chihchy") /// Jimmy Prime @@ -1961,12 +1965,6 @@ internal enum L10n { } } internal enum PostCommentView { - internal enum Button { - /// Cancel - internal static let cancel = L10n.tr("Localizable", "post_comment_view.button.cancel", fallback: "Cancel") - /// Post - internal static let post = L10n.tr("Localizable", "post_comment_view.button.post", fallback: "Post") - } internal enum Title { /// Edit comment internal static let editComment = L10n.tr("Localizable", "post_comment_view.title.edit_comment", fallback: "Edit comment") @@ -1997,12 +1995,6 @@ internal enum L10n { /// Quick search internal static let quickSearch = L10n.tr("Localizable", "quick_search_view.title.quick_search", fallback: "Quick search") } - internal enum ToolbarItem { - internal enum Button { - /// Confirm - internal static let confirm = L10n.tr("Localizable", "quick_search_view.toolbar_item.button.confirm", fallback: "Confirm") - } - } } internal enum ReadingSettingView { internal enum Section { diff --git a/EhPanda/App/Info.plist b/EhPanda/App/Info.plist index 925f724b..97c0ccff 100644 --- a/EhPanda/App/Info.plist +++ b/EhPanda/App/Info.plist @@ -26,25 +26,25 @@ AppIcon_Developer - AppIcon_StandWithUkraine2022 + AppIcon_NotMyPresident CFBundleIconFiles - AppIcon_StandWithUkraine2022 + AppIcon_NotMyPresident - AppIcon_Ukiyoe + AppIcon_StandWithUkraine2022 CFBundleIconFiles - AppIcon_Ukiyoe + AppIcon_StandWithUkraine2022 - AppIcon_NotMyPresident + AppIcon_Ukiyoe CFBundleIconFiles - AppIcon_NotMyPresident + AppIcon_Ukiyoe @@ -76,6 +76,14 @@ AppIcon_Developer_iPad_Pro + AppIcon_NotMyPresident + + CFBundleIconFiles + + AppIcon_NotMyPresident_iPad + AppIcon_NotMyPresident_iPad_Pro + + AppIcon_StandWithUkraine2022 CFBundleIconFiles @@ -92,14 +100,6 @@ AppIcon_Ukiyoe_iPad_Pro - AppIcon_NotMyPresident - - CFBundleIconFiles - - AppIcon_NotMyPresident_iPad - AppIcon_NotMyPresident_iPad_Pro - - CFBundlePrimaryIcon diff --git a/EhPanda/App/Tools/Clients/FileClient.swift b/EhPanda/App/Tools/Clients/FileClient.swift index 7ee659b6..f82d9b31 100644 --- a/EhPanda/App/Tools/Clients/FileClient.swift +++ b/EhPanda/App/Tools/Clients/FileClient.swift @@ -32,7 +32,7 @@ extension FileClient { let logs: [Log] = fileNames.compactMap { name in guard let fileURL = FileUtil.logsDirectoryURL?.appendingPathComponent(name), - let content = try? String(contentsOf: fileURL) + let content = try? String(contentsOf: fileURL, encoding: .utf8) else { return nil } return Log( diff --git a/EhPanda/App/Tools/ColorCodable.swift b/EhPanda/App/Tools/ColorCodable.swift index 01ec6843..4e50b0bc 100644 --- a/EhPanda/App/Tools/ColorCodable.swift +++ b/EhPanda/App/Tools/ColorCodable.swift @@ -44,7 +44,7 @@ private extension Color { } } -extension Color: Codable { +extension Color: @retroactive Codable { enum CodingKeys: String, CodingKey { case red, green, blue } diff --git a/EhPanda/App/Tools/Utilities/DeviceUtil.swift b/EhPanda/App/Tools/Utilities/DeviceUtil.swift index 531f900a..3a64e266 100644 --- a/EhPanda/App/Tools/Utilities/DeviceUtil.swift +++ b/EhPanda/App/Tools/Utilities/DeviceUtil.swift @@ -36,12 +36,12 @@ struct DeviceUtil { static var isLandscape: Bool { [.landscapeLeft, .landscapeRight] - .contains(keyWindow?.windowScene?.interfaceOrientation) + .contains(keyWindow?.windowScene?.effectiveGeometry.interfaceOrientation) } static var isPortrait: Bool { [.portrait, .portraitUpsideDown] - .contains(keyWindow?.windowScene?.interfaceOrientation) + .contains(keyWindow?.windowScene?.effectiveGeometry.interfaceOrientation) } static var windowW: CGFloat { diff --git a/EhPanda/App/de.lproj/Localizable.strings b/EhPanda/App/de.lproj/Localizable.strings index 43db93b8..b505d8d4 100644 --- a/EhPanda/App/de.lproj/Localizable.strings +++ b/EhPanda/App/de.lproj/Localizable.strings @@ -147,7 +147,6 @@ "quick_search_view.title.content" = "Content"; "quick_search_view.title.name" = "Name"; "quick_search_view.placeholder.optional" = "Optional"; -"quick_search_view.toolbar_item.button.confirm" = "Confirm"; // MARK: SettingView "setting_view.title.setting" = "Einstellungen"; @@ -338,8 +337,6 @@ // MARK: PostCommentView "post_comment_view.title.post_comment" = "Kommentar abgeben"; "post_comment_view.title.edit_comment" = "Kommentar bearbeiten"; -"post_comment_view.button.cancel" = "Abbrechen"; -"post_comment_view.button.post" = "Senden"; // MARK: PreviewsView "previews_view.title.previews" = "Vorschau"; diff --git a/EhPanda/App/en.lproj/Constant.strings b/EhPanda/App/en.lproj/Constant.strings index 29f37839..c08edd41 100644 --- a/EhPanda/App/en.lproj/Constant.strings +++ b/EhPanda/App/en.lproj/Constant.strings @@ -34,10 +34,12 @@ // Code level contributor "app.code_level_contributor.link.chihchy" = "https://github.com/chihchy"; +"app.code_level_contributor.link.aalberrty" = "https://github.com/aalberrty"; "app.code_level_contributor.link.Jimmy-Prime" = "https://github.com/Jimmy-Prime"; "app.code_level_contributor.link.xioxin" = "https://github.com/xioxin"; "app.code_level_contributor.link.vvbbnn00" = "https://github.com/vvbbnn00"; "app.code_level_contributor.text.chihchy" = "Chihchy"; +"app.code_level_contributor.text.aalberrty" = "Zack Asahina"; "app.code_level_contributor.text.Jimmy-Prime" = "Jimmy Prime"; "app.code_level_contributor.text.xioxin" = "xioxin"; "app.code_level_contributor.text.vvbbnn00" = "vvbbnn00"; diff --git a/EhPanda/App/en.lproj/Localizable.strings b/EhPanda/App/en.lproj/Localizable.strings index bc56f1d1..a3ca9bac 100644 --- a/EhPanda/App/en.lproj/Localizable.strings +++ b/EhPanda/App/en.lproj/Localizable.strings @@ -147,7 +147,6 @@ "quick_search_view.title.content" = "Content"; "quick_search_view.title.name" = "Name"; "quick_search_view.placeholder.optional" = "Optional"; -"quick_search_view.toolbar_item.button.confirm" = "Confirm"; // MARK: SettingView "setting_view.title.setting" = "Setting"; @@ -338,8 +337,6 @@ // MARK: PostCommentView "post_comment_view.title.post_comment" = "Post comment"; "post_comment_view.title.edit_comment" = "Edit comment"; -"post_comment_view.button.cancel" = "Cancel"; -"post_comment_view.button.post" = "Post"; // MARK: PreviewsView "previews_view.title.previews" = "Previews"; diff --git a/EhPanda/App/ja.lproj/Localizable.strings b/EhPanda/App/ja.lproj/Localizable.strings index 362be102..fa68dba1 100644 --- a/EhPanda/App/ja.lproj/Localizable.strings +++ b/EhPanda/App/ja.lproj/Localizable.strings @@ -147,7 +147,6 @@ "quick_search_view.title.content" = "内容"; "quick_search_view.title.name" = "名前"; "quick_search_view.placeholder.optional" = "任意"; -"quick_search_view.toolbar_item.button.confirm" = "確認"; // MARK: SettingView "setting_view.title.setting" = "設定"; @@ -338,8 +337,6 @@ // MARK: PostCommentView "post_comment_view.title.post_comment" = "コメントを書く"; "post_comment_view.title.edit_comment" = "コメントを編集"; -"post_comment_view.button.cancel" = "キャンセル"; -"post_comment_view.button.post" = "投稿"; // MARK: PreviewsView "previews_view.title.previews" = "プレビュー"; diff --git a/EhPanda/App/ko.lproj/Localizable.strings b/EhPanda/App/ko.lproj/Localizable.strings index 5d652367..b9266898 100644 --- a/EhPanda/App/ko.lproj/Localizable.strings +++ b/EhPanda/App/ko.lproj/Localizable.strings @@ -147,7 +147,6 @@ "quick_search_view.title.content" = "Content"; "quick_search_view.title.name" = "Name"; "quick_search_view.placeholder.optional" = "Optional"; -"quick_search_view.toolbar_item.button.confirm" = "확인"; // MARK: SettingView "setting_view.title.setting" = "설정"; @@ -338,8 +337,6 @@ // MARK: PostCommentView "post_comment_view.title.post_comment" = "평가 남기기"; "post_comment_view.title.edit_comment" = "평가 수정"; -"post_comment_view.button.cancel" = "취소"; -"post_comment_view.button.post" = "등록"; // MARK: PreviewsView "previews_view.title.previews" = "미리보기"; diff --git a/EhPanda/App/zh-Hans.lproj/Localizable.strings b/EhPanda/App/zh-Hans.lproj/Localizable.strings index b6ecccdf..19a4d6b0 100644 --- a/EhPanda/App/zh-Hans.lproj/Localizable.strings +++ b/EhPanda/App/zh-Hans.lproj/Localizable.strings @@ -147,7 +147,6 @@ "quick_search_view.title.content" = "内容"; "quick_search_view.title.name" = "名称"; "quick_search_view.placeholder.optional" = "可选"; -"quick_search_view.toolbar_item.button.confirm" = "确认"; // MARK: SettingView "setting_view.title.setting" = "设置"; @@ -338,8 +337,6 @@ // MARK: PostCommentView "post_comment_view.title.post_comment" = "发布评论"; "post_comment_view.title.edit_comment" = "编辑评论"; -"post_comment_view.button.cancel" = "取消"; -"post_comment_view.button.post" = "发布"; // MARK: PreviewsView "previews_view.title.previews" = "预览"; diff --git a/EhPanda/App/zh-Hant-HK.lproj/Localizable.strings b/EhPanda/App/zh-Hant-HK.lproj/Localizable.strings index c0d19029..948d5eb2 100644 --- a/EhPanda/App/zh-Hant-HK.lproj/Localizable.strings +++ b/EhPanda/App/zh-Hant-HK.lproj/Localizable.strings @@ -147,7 +147,6 @@ "quick_search_view.title.content" = "搜尋內容"; "quick_search_view.title.name" = "名稱"; "quick_search_view.placeholder.optional" = "(可選)"; -"quick_search_view.toolbar_item.button.confirm" = "確定"; // MARK: SettingView "setting_view.title.setting" = "設定"; @@ -338,9 +337,6 @@ // MARK: PostCommentView "post_comment_view.title.post_comment" = "發表留言"; "post_comment_view.title.edit_comment" = "編輯留言"; -"post_comment_view.button.cancel" = "取消"; -"post_comment_view.button.post" = "發表"; - // MARK: PreviewsView "previews_view.title.previews" = "預覽"; diff --git a/EhPanda/App/zh-Hant-TW.lproj/Localizable.strings b/EhPanda/App/zh-Hant-TW.lproj/Localizable.strings index a035bada..0c4f150d 100644 --- a/EhPanda/App/zh-Hant-TW.lproj/Localizable.strings +++ b/EhPanda/App/zh-Hant-TW.lproj/Localizable.strings @@ -147,7 +147,6 @@ "quick_search_view.title.content" = "搜尋內容"; "quick_search_view.title.name" = "名稱"; "quick_search_view.placeholder.optional" = "(可選)"; -"quick_search_view.toolbar_item.button.confirm" = "確定"; // MARK: SettingView "setting_view.title.setting" = "設定"; @@ -338,8 +337,6 @@ // MARK: PostCommentView "post_comment_view.title.post_comment" = "發表留言"; "post_comment_view.title.edit_comment" = "編輯留言"; -"post_comment_view.button.cancel" = "取消"; -"post_comment_view.button.post" = "發表"; // MARK: PreviewsView "previews_view.title.previews" = "預覽"; diff --git a/EhPanda/App/zh-Hant.lproj/Localizable.strings b/EhPanda/App/zh-Hant.lproj/Localizable.strings index 67060d21..ad77e167 100644 --- a/EhPanda/App/zh-Hant.lproj/Localizable.strings +++ b/EhPanda/App/zh-Hant.lproj/Localizable.strings @@ -147,7 +147,6 @@ "quick_search_view.title.content" = "搜尋內容"; "quick_search_view.title.name" = "名稱"; "quick_search_view.placeholder.optional" = "(可選)"; -"quick_search_view.toolbar_item.button.confirm" = "確定"; // MARK: SettingView "setting_view.title.setting" = "設定"; @@ -338,8 +337,6 @@ // MARK: PostCommentView "post_comment_view.title.post_comment" = "發表留言"; "post_comment_view.title.edit_comment" = "編輯留言"; -"post_comment_view.button.cancel" = "取消"; -"post_comment_view.button.post" = "發表"; // MARK: PreviewsView "previews_view.title.previews" = "預覽"; diff --git a/EhPanda/View/Detail/Archives/ArchivesView.swift b/EhPanda/View/Detail/Archives/ArchivesView.swift index 81966f7b..828e681b 100644 --- a/EhPanda/View/Detail/Archives/ArchivesView.swift +++ b/EhPanda/View/Detail/Archives/ArchivesView.swift @@ -164,19 +164,28 @@ private struct HathArchiveGrid: View { var body: some View { VStack(spacing: 10) { - Text(archive.resolution.value).font(.title3.bold()) + Text(archive.resolution.value) + .font(.title3.bold()) + VStack { - Text(archive.fileSize).fontWeight(.medium).font(.caption) - Text(archive.price).foregroundColor(fileSizeColor).font(.caption2) + Text(archive.fileSize) + .fontWeight(.medium) + .font(.caption) + + Text(archive.price) + .foregroundColor(fileSizeColor) + .font(.caption2) } .lineLimit(1) } .foregroundColor(foregroundColor) .frame(width: width, height: height) - .contentShape(Rectangle()).overlay( + .contentShape(.rect) + .overlay( RoundedRectangle(cornerRadius: 10) .stroke(borderColor, lineWidth: 1) ) + .glassEffect(.clear.interactive(), in: .rect(cornerRadius: 10)) } } @@ -205,19 +214,23 @@ private struct DownloadButton: View { } var body: some View { - HStack { - Spacer() - Text(L10n.Localizable.ArchivesView.Button.downloadToHathClient) - .font(.headline).foregroundColor(textColor) - Spacer() - } - .frame(height: 50).background(backgroundColor) - .cornerRadius(30).padding(paddingInsets) - .onTapGesture { if !isDisabled { action() }} - .onLongPressGesture( - minimumDuration: 0, maximumDistance: 50, - pressing: { isPressing = $0 }, perform: {} - ) + Text(L10n.Localizable.ArchivesView.Button.downloadToHathClient) + .font(.headline) + .foregroundStyle(textColor) + .frame(maxWidth: .infinity) + .frame(height: 50) + .background(backgroundColor) + .animation(.default, value: backgroundColor) + .clipShape(.rect(cornerRadius: 30)) + .glassEffect(.regular.interactive()) + .padding(paddingInsets) + .onTapGesture(perform: { if !isDisabled { action() }}) + .onLongPressGesture( + minimumDuration: 0, + maximumDistance: 50, + pressing: { isPressing = $0 }, + perform: {} + ) } } diff --git a/EhPanda/View/Detail/Components/PostCommentView.swift b/EhPanda/View/Detail/Components/PostCommentView.swift index b298271b..f99e998d 100644 --- a/EhPanda/View/Detail/Components/PostCommentView.swift +++ b/EhPanda/View/Detail/Components/PostCommentView.swift @@ -34,19 +34,19 @@ struct PostCommentView: View { var body: some View { NavigationView { VStack { - TextEditor(text: $content).focused($isTextEditorFocused).padding() + TextEditor(text: $content) + .focused($isTextEditorFocused) + .padding() + Spacer() } .toolbar { ToolbarItem(placement: .cancellationAction) { - Button(L10n.Localizable.PostCommentView.Button.cancel, action: cancelAction) + Button(role: .close, action: cancelAction) } ToolbarItem(placement: .confirmationAction) { - Button( - L10n.Localizable.PostCommentView.Button.post, - action: postAction - ) - .disabled(content.isEmpty) + Button(role: .confirm, action: postAction) + .disabled(content.isEmpty) } } .navigationBarTitleDisplayMode(.inline) diff --git a/EhPanda/View/Detail/DetailView.swift b/EhPanda/View/Detail/DetailView.swift index 6c58532d..21d5d72f 100644 --- a/EhPanda/View/Detail/DetailView.swift +++ b/EhPanda/View/Detail/DetailView.swift @@ -325,34 +325,48 @@ private struct HeaderSection: View { var body: some View { HStack { KFImage(gallery.coverURL) - .placeholder { Placeholder(style: .activity(ratio: Defaults.ImageSize.headerAspect)) } - .defaultModifier().scaledToFit() + .placeholder({ Placeholder(style: .activity(ratio: Defaults.ImageSize.headerAspect)) }) + .defaultModifier() + .scaledToFit() .frame( width: Defaults.ImageSize.headerW, height: Defaults.ImageSize.headerH ) + VStack(alignment: .leading) { Button(action: showFullTitleAction) { Text(title) - .font(.title3.bold()).multilineTextAlignment(.leading) - .tint(.primary).lineLimit(showFullTitle ? nil : 3) + .font(.title3.bold()) + .multilineTextAlignment(.leading) + .tint(.primary) + .lineLimit(showFullTitle ? nil : 3) .fixedSize(horizontal: false, vertical: true) } + Button(gallery.uploader ?? "", action: navigateUploaderAction) - .lineLimit(1).font(.callout).foregroundStyle(.secondary) + .lineLimit(1) + .font(.callout) + .foregroundStyle(.secondary) + Spacer() + HStack { CategoryLabel( - text: gallery.category.value, color: gallery.color, - font: .headline, insets: .init(top: 2, leading: 4, bottom: 2, trailing: 4), + text: gallery.category.value, + color: gallery.color, + font: .headline, + insets: .init(top: 2, leading: 4, bottom: 2, trailing: 4), cornerRadius: 3 ) + Spacer() + ZStack { Button(action: unfavorAction) { Image(systemSymbol: .heartFill) } .opacity(galleryDetail.isFavorited ? 1 : 0) + Menu { ForEach(0..<10) { index in Button(user.getFavoriteCategory(index: index)) { @@ -364,15 +378,19 @@ private struct HeaderSection: View { } .opacity(galleryDetail.isFavorited ? 0 : 1) } - .imageScale(.large).foregroundStyle(.tint) + .imageScale(.large) + .foregroundStyle(.tint) + .buttonStyle(.glass(.regular.interactive())) .disabled(!CookieUtil.didLogin) + Button(action: navigateReadingAction) { Text(L10n.Localizable.DetailView.Button.read) .bold().textCase(.uppercase).font(.headline) .foregroundColor(.white).padding(.vertical, -2) .padding(.horizontal, 2).lineLimit(1) } - .buttonStyle(.borderedProminent).buttonBorderShape(.capsule) + .buttonStyle(.glassProminent) + .buttonBorderShape(.capsule) } .minimumScaleFactor(0.5) } @@ -854,15 +872,21 @@ private struct CommentButton: View { } var body: some View { + let shape = RoundedRectangle(cornerRadius: 15) + Button(action: action) { HStack { - Spacer() Image(systemSymbol: .squareAndPencil) - Text(L10n.Localizable.DetailView.Button.postComment).bold() - Spacer() + + Text(L10n.Localizable.DetailView.Button.postComment) + .bold() } - .padding().background(backgroundColor).cornerRadius(15) + .padding() + .frame(maxWidth: .infinity) + .background(backgroundColor) + .clipShape(shape) } + .glassEffect(.clear.interactive(), in: shape) } } diff --git a/EhPanda/View/Reading/ReadingView.swift b/EhPanda/View/Reading/ReadingView.swift index 0590064f..504213a3 100644 --- a/EhPanda/View/Reading/ReadingView.swift +++ b/EhPanda/View/Reading/ReadingView.swift @@ -49,8 +49,8 @@ struct ReadingView: View { doubleTapScaleFactor: $setting.doubleTapScaleFactor ) .toolbar { - CustomToolbarItem(placement: .cancellationAction) { - if !DeviceUtil.isPad && DeviceUtil.isLandscape { + if !DeviceUtil.isPad && DeviceUtil.isLandscape { + CustomToolbarItem(placement: .cancellationAction) { Button { store.send(.setNavigation(nil)) } label: { diff --git a/EhPanda/View/Reading/Support/AdvancedList.swift b/EhPanda/View/Reading/Support/AdvancedList.swift index 608ac388..22eb2bcf 100644 --- a/EhPanda/View/Reading/Support/AdvancedList.swift +++ b/EhPanda/View/Reading/Support/AdvancedList.swift @@ -9,6 +9,7 @@ import SwiftUIPager struct AdvancedList: View where PageView: View, Element: Equatable, ID: Hashable, G: Gesture { @State var performingChanges = false + @State var scrollPositionID: Int? private let pagerModel: Page private let data: [Element] @@ -35,23 +36,16 @@ where PageView: View, Element: Equatable, ID: Hashable, G: Gesture { ScrollView(showsIndicators: false) { LazyVStack(spacing: spacing) { ForEach(data, id: id) { index in - let longPress = longPressGesture(index: index) - let gestures = longPress.simultaneously(with: gesture) - content(index).gesture(gestures) + content(index) + .gesture(gesture) } } - .onAppear { tryScrollTo(id: pagerModel.index + 1, proxy: proxy) } + .scrollTargetLayout() + .onAppear(perform: { tryScrollTo(id: pagerModel.index + 1, proxy: proxy) }) } - .onChange(of: pagerModel.index) { _, newValue in - tryScrollTo(id: newValue + 1, proxy: proxy) - } - } - } - - private func longPressGesture(index: Element) -> some Gesture { - LongPressGesture(minimumDuration: 0, maximumDistance: .infinity) - .onEnded { _ in - if let index = index as? Int { + .scrollPosition(id: $scrollPositionID, anchor: .center) + .onScrollPhaseChange { _, newValue in + if newValue == .idle, let index = scrollPositionID { performingChanges = true pagerModel.update(.new(index: index - 1)) DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) { @@ -59,13 +53,15 @@ where PageView: View, Element: Equatable, ID: Hashable, G: Gesture { } } } + .onChange(of: pagerModel.index) { _, newValue in + tryScrollTo(id: newValue + 1, proxy: proxy) + } + } } private func tryScrollTo(id: Int, proxy: ScrollViewProxy) { if !performingChanges { - AppUtil.dispatchMainSync { - proxy.scrollTo(id, anchor: .center) - } + scrollPositionID = id } } } diff --git a/EhPanda/View/Reading/Support/AutoPlayHandler.swift b/EhPanda/View/Reading/Support/AutoPlayHandler.swift index c45f6027..660f96d9 100644 --- a/EhPanda/View/Reading/Support/AutoPlayHandler.swift +++ b/EhPanda/View/Reading/Support/AutoPlayHandler.swift @@ -2,8 +2,6 @@ // AutoPlayHandler.swift // EhPanda // -// Created by 荒木辰造 on R 4/02/09. -// import SwiftUI diff --git a/EhPanda/View/Reading/Support/ControlPanel.swift b/EhPanda/View/Reading/Support/ControlPanel.swift index fa531a14..f0fcdf0b 100644 --- a/EhPanda/View/Reading/Support/ControlPanel.swift +++ b/EhPanda/View/Reading/Support/ControlPanel.swift @@ -117,82 +117,103 @@ private struct UpperPanel: View { } var body: some View { - ZStack { - HStack { + HStack { + HStack(spacing: 16) { Button(action: dismissAction) { Image(systemSymbol: .xmark) + .font(.title2) + .frame(width: 44, height: 44) } - .font(.title2).padding(.leading, 20) - Spacer() - Slider(value: .constant(0)).opacity(0) - Spacer() - HStack(spacing: 20) { - Button { - enablesLiveText.toggle() - } label: { - Image(systemSymbol: .viewfinderCircle) - .symbolVariant(enablesLiveText ? .fill : .none) - } - if DeviceUtil.isLandscape && setting.readingDirection != .vertical { - Menu { - Button { - setting.enablesDualPageMode.toggle() - } label: { - Text(L10n.Localizable.ReadingView.ToolbarItem.Title.dualPageMode) - if setting.enablesDualPageMode { - Image(systemSymbol: .checkmark) - } - } - Button { - setting.exceptCover.toggle() - } label: { - Text(L10n.Localizable.ReadingView.ToolbarItem.Title.exceptTheCover) - if setting.exceptCover { - Image(systemSymbol: .checkmark) - } - } - .disabled(!setting.enablesDualPageMode) + .glassEffect(.regular.interactive()) + + Text(title) + .font(.title2) + .fontWeight(.bold) + .monospacedDigit() + .lineLimit(1) + .padding(.horizontal, 16) + .padding(.vertical, 8) + .glassEffect(.regular.interactive()) + } + + Spacer() + + HStack(spacing: 20) { + Button { + enablesLiveText.toggle() + } label: { + Image(systemSymbol: .viewfinderCircle) + .symbolVariant(enablesLiveText ? .fill : .none) + .font(.title2) + } + + if DeviceUtil.isLandscape && setting.readingDirection != .vertical { + Menu { + Button { + setting.enablesDualPageMode.toggle() } label: { - Image(systemSymbol: .rectangleSplit2x1) - .symbolVariant(setting.enablesDualPageMode ? .fill : .none) + Text(L10n.Localizable.ReadingView.ToolbarItem.Title.dualPageMode) + if setting.enablesDualPageMode { + Image(systemSymbol: .checkmark) + } } - } - Menu { - Text(L10n.Localizable.ReadingView.ToolbarItem.Title.autoPlay).foregroundColor(.secondary) - ForEach(AutoPlayPolicy.allCases) { policy in - Button { - autoPlayPolicy = policy - } label: { - Text(policy.value) - if autoPlayPolicy == policy { - Image(systemSymbol: .checkmark) - } + Button { + setting.exceptCover.toggle() + } label: { + Text(L10n.Localizable.ReadingView.ToolbarItem.Title.exceptTheCover) + if setting.exceptCover { + Image(systemSymbol: .checkmark) } } + .disabled(!setting.enablesDualPageMode) } label: { - Image(systemSymbol: .timer) + Image(systemSymbol: .rectangleSplit2x1) + .symbolVariant(setting.enablesDualPageMode ? .fill : .none) + .font(.title2) } - ToolbarFeaturesMenu { - Button(action: retryAllFailedImagesAction) { - Image(systemSymbol: .exclamationmarkArrowTriangle2Circlepath) - Text(L10n.Localizable.ReadingView.ToolbarItem.Button.retryAllFailedImages) - } - Button(action: reloadAllImagesAction) { - Image(systemSymbol: .arrowCounterclockwise) - Text(L10n.Localizable.ReadingView.ToolbarItem.Button.reloadAllImages) - } - Button(action: navigateSettingAction) { - Image(systemSymbol: .gear) - Text(L10n.Localizable.ReadingView.ToolbarItem.Button.readingSetting) + } + + Menu { + Text(L10n.Localizable.ReadingView.ToolbarItem.Title.autoPlay).foregroundColor(.secondary) + ForEach(AutoPlayPolicy.allCases) { policy in + Button { + autoPlayPolicy = policy + } label: { + Text(policy.value) + if autoPlayPolicy == policy { + Image(systemSymbol: .checkmark) + } } } - .padding(.trailing, 20) + } label: { + Image(systemSymbol: .timer) + .font(.title2) + } + .buttonStyle(.borderless) + + ToolbarFeaturesMenu { + Button(action: retryAllFailedImagesAction) { + Image(systemSymbol: .exclamationmarkArrowTriangle2Circlepath) + Text(L10n.Localizable.ReadingView.ToolbarItem.Button.retryAllFailedImages) + } + Button(action: reloadAllImagesAction) { + Image(systemSymbol: .arrowCounterclockwise) + Text(L10n.Localizable.ReadingView.ToolbarItem.Button.reloadAllImages) + } + Button(action: navigateSettingAction) { + Image(systemSymbol: .gear) + Text(L10n.Localizable.ReadingView.ToolbarItem.Button.readingSetting) + } } + .buttonStyle(.borderless) .font(.title2) } - Text(title).bold().lineLimit(1).padding() + .padding(.vertical, 12) + .padding(.horizontal, 20) + .glassEffect(.regular.interactive()) } - .background(.thinMaterial) + .foregroundStyle(.primary) + .padding(.horizontal, 20) } } @@ -226,32 +247,51 @@ private struct LowerPanel: View { var body: some View { VStack(spacing: 30) { Button(action: dismissAction) { - Image(systemSymbol: .xmark).foregroundColor(.primary).padding() - .background(.ultraThinMaterial).cornerRadius(.infinity) + Image(systemSymbol: .xmark) + .foregroundColor(.primary) + .font(.title2) + .frame(width: 44, height: 44) } - .gesture(dismissGesture).opacity(showsSliderPreview ? 0 : 1) + .glassEffect(.regular.interactive()) + .gesture(dismissGesture) + .opacity(showsSliderPreview ? 0 : 1) + VStack(spacing: 0) { SliderPreivew( showsSliderPreview: $showsSliderPreview, - sliderValue: $sliderValue, previewURLs: previewURLs, range: range, - isReversed: isReversed, fetchPreviewURLsAction: fetchPreviewURLsAction + sliderValue: $sliderValue, + previewURLs: previewURLs, + range: range, + isReversed: isReversed, + fetchPreviewURLsAction: fetchPreviewURLsAction ) - VStack { - HStack { - Text(isReversed ? "\(Int(range.upperBound))" : "\(Int(range.lowerBound))") - .fontWeight(.medium).font(.caption).padding() - Slider( - value: $sliderValue, in: range, step: 1, - onEditingChanged: { showsSliderPreview = $0 } - ) - .rotationEffect(.init(degrees: isReversed ? 180 : 0)) - Text(isReversed ? "\(Int(range.lowerBound))" : "\(Int(range.upperBound))") - .fontWeight(.medium).font(.caption).padding() - } - .padding(.horizontal).padding(.bottom) + + HStack { + Text(isReversed ? "\(Int(range.upperBound))" : "\(Int(range.lowerBound))") + .fontWeight(.medium) + .font(.caption) + .padding() + + Slider( + value: $sliderValue, + in: range, + onEditingChanged: { if !$0 { showsSliderPreview = false } } + ) + .frame(width: DeviceUtil.windowW * 0.6) + .rotationEffect(.init(degrees: isReversed ? 180 : 0)) + .simultaneousGesture( + LongPressGesture(minimumDuration: .infinity, maximumDistance: .infinity) + .onChanged({ if $0 { showsSliderPreview = true } }) + ) + + Text(isReversed ? "\(Int(range.lowerBound))" : "\(Int(range.upperBound))") + .fontWeight(.medium) + .font(.caption) + .padding() } } - .background(.thinMaterial) + .glassEffect(in: .rect(cornerRadius: 16)) + .padding(.horizontal, SliderPreivew.outerPadding) } } } @@ -265,10 +305,15 @@ private struct SliderPreivew: View { private let isReversed: Bool private let fetchPreviewURLsAction: (Int) -> Void + static let outerPadding: CGFloat = 8 + init( - showsSliderPreview: Binding, sliderValue: Binding, - previewURLs: [Int: URL], range: ClosedRange, - isReversed: Bool, fetchPreviewURLsAction: @escaping (Int) -> Void + showsSliderPreview: Binding, + sliderValue: Binding, + previewURLs: [Int: URL], + range: ClosedRange, + isReversed: Bool, + fetchPreviewURLsAction: @escaping (Int) -> Void ) { _showsSliderPreview = showsSliderPreview _sliderValue = sliderValue @@ -284,15 +329,15 @@ private struct SliderPreivew: View { let (url, modifier) = PreviewResolver.getPreviewConfigs(originalURL: previewURLs[index]) VStack { KFImage.url(url, cacheKey: previewURLs[index]?.absoluteString) - .placeholder { - Placeholder(style: .activity( - ratio: Defaults.ImageSize.previewAspect - )) - } + .placeholder({ Placeholder(style: .activity(ratio: Defaults.ImageSize.previewAspect)) }) .fade(duration: 0.25) - .imageModifier(modifier).resizable().scaledToFit() + .imageModifier(modifier) + .resizable() + .scaledToFit() .frame(width: previewWidth, height: showsSliderPreview ? previewHeight : 0) - Text("\(index)").font(DeviceUtil.isPadWidth ? .callout : .caption) + + Text("\(index)") + .font(DeviceUtil.isPadWidth ? .callout : .caption) .foregroundColor(index == Int(sliderValue) ? .accentColor : .secondary) } .onAppear { @@ -303,7 +348,9 @@ private struct SliderPreivew: View { .opacity(checkIndex(index) ? 1 : 0) } } - .opacity(showsSliderPreview ? 1 : 0).padding(.vertical, verticalPadding) + .opacity(showsSliderPreview ? 1 : 0) + .padding(.vertical, verticalPadding) + .padding(.horizontal, horizontalPadding) .frame(height: showsSliderPreview ? previewHeight + verticalPadding * 2 : 0) } } @@ -312,6 +359,7 @@ private extension SliderPreivew { var verticalPadding: CGFloat { DeviceUtil.isPadWidth ? 30 : 20 } + var horizontalPadding: CGFloat { verticalPadding * 0.5 } var previewsCount: Int { DeviceUtil.isPadWidth ? DeviceUtil.isLandscape ? 7 : 5 : 3 } @@ -332,7 +380,7 @@ private extension SliderPreivew { var previewWidth: CGFloat { guard previewsCount > 0 else { return 0 } let count = CGFloat(previewsCount) - let spacing = (count + 1) * previewSpacing + let spacing = (count + 1) * previewSpacing + horizontalPadding * 2 + Self.outerPadding * 2 return (DeviceUtil.windowW - spacing) / count } func checkIndex(_ index: Int) -> Bool { diff --git a/EhPanda/View/Reading/Support/GestureHandler.swift b/EhPanda/View/Reading/Support/GestureHandler.swift index af9d5916..c3b88c58 100644 --- a/EhPanda/View/Reading/Support/GestureHandler.swift +++ b/EhPanda/View/Reading/Support/GestureHandler.swift @@ -2,8 +2,6 @@ // GestureHandler.swift // EhPanda // -// Created by 荒木辰造 on R 4/02/09. -// import SwiftUI diff --git a/EhPanda/View/Reading/Support/LiveTextHandler.swift b/EhPanda/View/Reading/Support/LiveTextHandler.swift index 9a9451f4..28266c85 100644 --- a/EhPanda/View/Reading/Support/LiveTextHandler.swift +++ b/EhPanda/View/Reading/Support/LiveTextHandler.swift @@ -2,8 +2,6 @@ // LiveTextHandler.swift // EhPanda // -// Created by xioxin on 2022/2/12. -// // swiftlint:disable line_length // Refercence // https://www.codeproject.com/Articles/15573/2D-Polygon-Collision-Detection diff --git a/EhPanda/View/Reading/Support/PageHandler.swift b/EhPanda/View/Reading/Support/PageHandler.swift index 1b03eea6..2a06f489 100644 --- a/EhPanda/View/Reading/Support/PageHandler.swift +++ b/EhPanda/View/Reading/Support/PageHandler.swift @@ -2,8 +2,6 @@ // PageHandler.swift // EhPanda // -// Created by 荒木辰造 on R 4/02/09. -// import SwiftUI diff --git a/EhPanda/View/Search/SearchRootView.swift b/EhPanda/View/Search/SearchRootView.swift index 033346cd..e2cd9eb3 100644 --- a/EhPanda/View/Search/SearchRootView.swift +++ b/EhPanda/View/Search/SearchRootView.swift @@ -92,7 +92,13 @@ struct SearchRootView: View { .autoBlur(radius: blurRadius).environment(\.inSheet, true).navigationViewStyle(.stack) } } else { - content + // Workaround: Prevent the title disappearing issue. + if store.historyKeywords.isEmpty && store.historyGalleries.isEmpty { + content + .navigationSubtitle(Text(" ")) + } else { + content + } } } } @@ -214,10 +220,9 @@ private struct QuickSearchWordsSection: View { } private var keywords: [WrappedKeyword] { - quickSearchWords.map { word in - .init(keyword: word.content, displayText: word.name) - } - .removeDuplicates() + quickSearchWords + .map({ .init(keyword: $0.content, displayText: $0.name) }) + .removeDuplicates() } var body: some View { @@ -245,7 +250,7 @@ private struct HistoryKeywordsSection: View { var body: some View { SubSection(title: L10n.Localizable.SearchView.Section.Title.recentlySearched, showAll: false) { DoubleVerticalKeywordsStack( - keywords: keywords.map({ WrappedKeyword(keyword: $0) }), + keywords: keywords.map(WrappedKeyword.init), searchAction: searchAction, removeAction: removeAction ) @@ -345,16 +350,23 @@ private struct KeywordCell: View { self.removeAction = removeAction } + var title: String { + wrappedKeyword.displayText.isEmpty ? wrappedKeyword.keyword : wrappedKeyword.displayText + } + var body: some View { HStack(spacing: 20) { Button { searchAction(wrappedKeyword.keyword) } label: { Image(systemSymbol: .magnifyingglass) - Text(wrappedKeyword.displayText ?? wrappedKeyword.keyword).lineLimit(1) - Spacer() + + Text(title) + .frame(maxWidth: .infinity, alignment: .leading) + .lineLimit(1) } .tint(.primary) + if removeAction != nil { Button { removeAction?(wrappedKeyword.keyword) @@ -400,7 +412,16 @@ private struct HistoryGalleriesSection: View { // MARK: Definition private struct WrappedKeyword: Hashable { let keyword: String - var displayText: String? + let displayText: String + + init(keyword: String, displayText: String) { + self.keyword = keyword + self.displayText = displayText + } + + init(keyword: String) { + self.init(keyword: keyword, displayText: .init()) + } } struct SearchRootView_Previews: PreviewProvider { diff --git a/EhPanda/View/Search/Support/QuickSearchView.swift b/EhPanda/View/Search/Support/QuickSearchView.swift index c2ec2137..5c60c160 100644 --- a/EhPanda/View/Search/Support/QuickSearchView.swift +++ b/EhPanda/View/Search/Support/QuickSearchView.swift @@ -187,9 +187,7 @@ extension QuickSearchView { private func toolbar() -> some ToolbarContent { CustomToolbarItem { - Button(action: confirmAction) { - Text(L10n.Localizable.QuickSearchView.ToolbarItem.Button.confirm).bold() - } + Button(role: .confirm, action: confirmAction) } } } diff --git a/EhPanda/View/Setting/AccountSetting/AccountSettingView.swift b/EhPanda/View/Setting/AccountSetting/AccountSettingView.swift index cce5ff1d..09b2d9b9 100644 --- a/EhPanda/View/Setting/AccountSetting/AccountSettingView.swift +++ b/EhPanda/View/Setting/AccountSetting/AccountSettingView.swift @@ -63,6 +63,7 @@ struct AccountSettingView: View { ) .sheet(item: $store.route.sending(\.setNavigation).webView, id: \.absoluteString) { url in WebView(url: url) + .ignoresSafeArea(edges: .bottom) .autoBlur(radius: blurRadius) } .onAppear { store.send(.loadCookies) } diff --git a/EhPanda/View/Setting/Components/AboutView.swift b/EhPanda/View/Setting/Components/AboutView.swift index 8f5afcdf..9b6c91ec 100644 --- a/EhPanda/View/Setting/Components/AboutView.swift +++ b/EhPanda/View/Setting/Components/AboutView.swift @@ -15,15 +15,6 @@ struct AboutView: View { } var body: some View { - HStack { - VStack(alignment: .leading) { - Text(L10n.Constant.App.copyright) - Text(version) - } - .foregroundStyle(.gray).font(.caption2.bold()) - Spacer() - } - .padding(.horizontal) Form { Section { ForEach(contacts) { contact in @@ -52,6 +43,18 @@ struct AboutView: View { } } .navigationTitle(L10n.Localizable.AboutView.Title.ehPanda) + .toolbar { + ToolbarItem(placement: .largeSubtitle) { + VStack(alignment: .leading) { + Text(L10n.Constant.App.copyright) + Text(version) + } + .foregroundStyle(.gray) + .font(.caption2.bold()) + .frame(maxWidth: .infinity, alignment: .leading) + .padding(.vertical, 4) + } + } } // MARK: Contacts @@ -104,6 +107,10 @@ struct AboutView: View { urlString: L10n.Constant.App.CodeLevelContributor.Link.chihchy, text: L10n.Constant.App.CodeLevelContributor.Text.chihchy ), + .init( + urlString: L10n.Constant.App.CodeLevelContributor.Link.aalberrty, + text: L10n.Constant.App.CodeLevelContributor.Text.aalberrty + ), .init( urlString: L10n.Constant.App.CodeLevelContributor.Link.jimmyPrime, text: L10n.Constant.App.CodeLevelContributor.Text.jimmyPrime diff --git a/EhPanda/View/Setting/Components/LaboratorySettingView.swift b/EhPanda/View/Setting/Components/LaboratorySettingView.swift index ec0e4d81..15a75877 100644 --- a/EhPanda/View/Setting/Components/LaboratorySettingView.swift +++ b/EhPanda/View/Setting/Components/LaboratorySettingView.swift @@ -53,18 +53,23 @@ struct LaboratoryCell: View { var body: some View { HStack { - Spacer() - Group { - Image(systemSymbol: symbol) - Text(title).bold() - } - .foregroundColor(contentColor).font(.title2) - Spacer() + Image(systemSymbol: symbol) + + Text(title) + .bold() } - .contentShape(Rectangle()).onTapGesture { isOn.toggle() } - .minimumScaleFactor(0.75).padding(.vertical, 20) - .background(bgColor).cornerRadius(15).lineLimit(1) + .foregroundStyle(contentColor) + .font(.title2) + .frame(maxWidth: .infinity) + .contentShape(.rect) + .onTapGesture(perform: { isOn.toggle() }) + .minimumScaleFactor(0.75) + .padding(.vertical, 20) + .background(bgColor) + .cornerRadius(15) + .lineLimit(1) .animation(.default, value: isOn) + .glassEffect(.regular.interactive(), in: .rect(cornerRadius: 15)) } } diff --git a/EhPanda/View/Setting/EhSetting/EhSettingView.swift b/EhPanda/View/Setting/EhSetting/EhSettingView.swift index 9c6f4643..e64686f2 100644 --- a/EhPanda/View/Setting/EhSetting/EhSettingView.swift +++ b/EhPanda/View/Setting/EhSetting/EhSettingView.swift @@ -23,7 +23,7 @@ struct EhSettingView: View { // MARK: EhSettingView var body: some View { ZStack { - // workaround: Stay if-else approach + // Workaround: Stay if-else approach if store.loadingState == .loading || store.submittingState == .loading { LoadingView() .tint(nil) @@ -51,6 +51,7 @@ struct EhSettingView: View { } .sheet(item: $store.route.sending(\.setNavigation).webView, id: \.absoluteString) { url in WebView(url: url) + .ignoresSafeArea(edges: .bottom) .autoBlur(radius: blurRadius) } .toolbar(content: toolbar) @@ -197,7 +198,6 @@ private struct EhProfileSection: View { .onChange(of: ehProfile) { _, newValue in performEhProfileAction(nil, nil, newValue.value) } - .textCase(nil) Section { SettingTextField(text: $editingProfileName, width: nil, alignment: .leading, background: .clear) @@ -243,7 +243,6 @@ private struct ImageLoadSettingsSection: View { } footer: { Text(ehSetting.loadThroughHathSetting.description) } - .textCase(nil) Section( L10n.Localizable.EhSettingView.Description.browsingCountry( @@ -259,7 +258,6 @@ private struct ImageLoadSettingsSection: View { } } } - .textCase(nil) } } @@ -285,7 +283,6 @@ private struct ImageSizeSettingsSection: View { .newlineBold() .appending(L10n.Localizable.EhSettingView.Description.imageResolution) } - .textCase(nil) if let useOriginalImagesBinding = Binding($ehSetting.useOriginalImages) { Section(L10n.Localizable.EhSettingView.Section.Title.originalImages) { @@ -294,7 +291,6 @@ private struct ImageSizeSettingsSection: View { isOn: useOriginalImagesBinding ) } - .textCase(nil) } Section(L10n.Localizable.EhSettingView.Description.imageSize) { @@ -310,7 +306,6 @@ private struct ImageSizeSettingsSection: View { value: $ehSetting.imageSizeHeight, range: 0...65535, unit: "px" ) } - .textCase(nil) } } @@ -336,7 +331,6 @@ private struct GalleryNameDisplaySection: View { .newlineBold() .appending(L10n.Localizable.EhSettingView.Description.galleryName) } - .textCase(nil) } } @@ -362,7 +356,6 @@ private struct ArchiverSettingsSection: View { .newlineBold() .appending(L10n.Localizable.EhSettingView.Description.archiverBehavior) } - .textCase(nil) } } @@ -386,7 +379,6 @@ private struct FrontPageSettingsSection: View { .newlineBold() .appending(L10n.Localizable.EhSettingView.Description.galleryCategory) } - .textCase(nil) Section(L10n.Localizable.EhSettingView.Description.displayMode) { Picker(L10n.Localizable.EhSettingView.Title.displayMode, selection: $ehSetting.displayMode) { @@ -397,7 +389,6 @@ private struct FrontPageSettingsSection: View { } .pickerStyle(.menu) } - .textCase(nil) Section(L10n.Localizable.EhSettingView.Section.Title.showSearchRangeIndicator) { Toggle( @@ -405,7 +396,6 @@ private struct FrontPageSettingsSection: View { isOn: $ehSetting.showSearchRangeIndicator ) } - .textCase(nil) } } @@ -428,7 +418,6 @@ private struct OptionalUIElementsSection: View { .newlineBold() .appending(L10n.Localizable.EhSettingView.Description.optionalUIElements) } - .textCase(nil) } } @@ -465,7 +454,6 @@ private struct FavoritesSection: View { .newlineBold() .appending(L10n.Localizable.EhSettingView.Description.favoriteCategories) } - .textCase(nil) Section(L10n.Localizable.EhSettingView.Description.favoritesSortOrder) { Picker( @@ -479,7 +467,6 @@ private struct FavoritesSection: View { } .pickerStyle(.menu) } - .textCase(nil) } } @@ -507,7 +494,6 @@ private struct RatingsSection: View { .newlineBold() .appending(L10n.Localizable.EhSettingView.Description.ratingsColor) } - .textCase(nil) } } @@ -530,7 +516,6 @@ private struct TagFilteringThresholdSection: View { .newlineBold() .appending(L10n.Localizable.EhSettingView.Description.tagFilteringThreshold) } - .textCase(nil) } } @@ -553,7 +538,6 @@ private struct TagWatchingThresholdSection: View { .newlineBold() .appending(L10n.Localizable.EhSettingView.Description.tagWatchingThreshold) } - .textCase(nil) } } @@ -575,7 +559,6 @@ private struct FilteredRemovalCountSection: View { Text(L10n.Localizable.EhSettingView.Section.Title.filteredRemovalCount).newlineBold() + Text(L10n.Localizable.EhSettingView.Description.filteredRemovalCount) } - .textCase(nil) } } @@ -631,7 +614,6 @@ private struct ExcludedLanguagesSection: View { .newlineBold() .appending(L10n.Localizable.EhSettingView.Description.excludedLanguages) } - .textCase(nil) } } @@ -712,7 +694,6 @@ private struct ExcludedUploadersSection: View { .localizedKey ) } - .textCase(nil) } } @@ -738,7 +719,6 @@ private struct SearchResultCountSection: View { .newlineBold() .appending(L10n.Localizable.EhSettingView.Description.resultCount) } - .textCase(nil) } } @@ -769,7 +749,6 @@ private struct ThumbnailSettingsSection: View { } footer: { Text(ehSetting.thumbnailLoadTiming.description) } - .textCase(nil) Section(L10n.Localizable.EhSettingView.Description.thumbnailConfiguration) { LabeledContent(L10n.Localizable.EhSettingView.Title.thumbnailSize) { @@ -798,7 +777,6 @@ private struct ThumbnailSettingsSection: View { .frame(width: 200) } } - .textCase(nil) } } @@ -823,7 +801,6 @@ private struct CoverScalingSection: View { .newlineBold() .appending(L10n.Localizable.EhSettingView.Description.coverScaleFactor) } - .textCase(nil) } } @@ -848,7 +825,6 @@ private struct ViewportOverrideSection: View { .newlineBold() .appending(L10n.Localizable.EhSettingView.Description.virtualWidth) } - .textCase(nil) } } @@ -874,14 +850,17 @@ private struct ValuePicker: View { Slider( value: $value, in: range, - step: 1, - minimumValueLabel: Text(String(Int(range.lowerBound)) + unit) - .fontWeight(.medium) - .font(.callout), - maximumValueLabel: Text(String(Int(range.upperBound)) + unit) - .fontWeight(.medium) - .font(.callout), - label: EmptyView.init + label: EmptyView.init, + minimumValueLabel: { + Text(String(Int(range.lowerBound)) + unit) + .fontWeight(.medium) + .font(.callout) + }, + maximumValueLabel: { + Text(String(Int(range.upperBound)) + unit) + .fontWeight(.medium) + .font(.callout) + } ) } } @@ -918,7 +897,6 @@ private struct GalleryCommentsSection: View { } .pickerStyle(.menu) } - .textCase(nil) } } @@ -940,7 +918,6 @@ private struct GalleryTagsSection: View { } .pickerStyle(.menu) } - .textCase(nil) } } @@ -965,7 +942,6 @@ private struct GalleryPageThumbnailLabelingSection: View { } .pickerStyle(.menu) } - .textCase(nil) } } @@ -1004,7 +980,6 @@ private struct MultiplePageViewerSection: View { isOn: multiplePageViewerShowPaneBinding ) } - .textCase(nil) } } } diff --git a/EhPanda/View/Setting/GeneralSetting/GeneralSettingView.swift b/EhPanda/View/Setting/GeneralSetting/GeneralSettingView.swift index aeec5944..017f2520 100644 --- a/EhPanda/View/Setting/GeneralSetting/GeneralSettingView.swift +++ b/EhPanda/View/Setting/GeneralSetting/GeneralSettingView.swift @@ -68,16 +68,23 @@ struct GeneralSettingView: View { Section(L10n.Localizable.GeneralSettingView.Section.Title.tags) { HStack { Text(L10n.Localizable.GeneralSettingView.Title.enablesTagsExtension) - Spacer() + .frame(maxWidth: .infinity, alignment: .leading) + ZStack { - Image(systemSymbol: .exclamationmarkTriangleFill).foregroundStyle(.yellow) + Image(systemSymbol: .exclamationmarkTriangleFill) + .foregroundStyle(.yellow) .opacity( translatesTags && tagTranslatorEmpty && tagTranslatorLoadingState != .loading ? 1 : 0 ) - ProgressView().tint(nil).opacity(tagTranslatorLoadingState == .loading ? 1 : 0) + ProgressView() + .tint(nil) + .opacity(tagTranslatorLoadingState == .loading ? 1 : 0) } - Toggle("", isOn: $enablesTagsExtension).frame(width: 50) + + Toggle("", isOn: $enablesTagsExtension) + .frame(width: 50) + .padding(.leading, 20) } if enablesTagsExtension && !tagTranslatorEmpty { Toggle(L10n.Localizable.GeneralSettingView.Title.translatesTags, isOn: $translatesTags) diff --git a/EhPanda/View/Setting/Login/LoginView.swift b/EhPanda/View/Setting/Login/LoginView.swift index 4b0c9e72..7825edb9 100644 --- a/EhPanda/View/Setting/Login/LoginView.swift +++ b/EhPanda/View/Setting/Login/LoginView.swift @@ -27,16 +27,22 @@ struct LoginView: View { WaveForm(color: Color(.systemGray2).opacity(0.2), amplify: 100, isReversed: true) WaveForm(color: Color(.systemGray).opacity(0.2), amplify: 120, isReversed: false) } - .offset(y: proxy.size.height * 0.3).drawingGroup() + .offset(y: proxy.size.height * 0.3) + .drawingGroup() + VStack(spacing: 15) { Group { LoginTextField( - focusedField: $focusedField, text: $store.username, - description: L10n.Localizable.LoginView.Title.username, isPassword: false + focusedField: $focusedField, + text: $store.username, + description: L10n.Localizable.LoginView.Title.username, + isPassword: false ) LoginTextField( - focusedField: $focusedField, text: $store.password, - description: L10n.Localizable.LoginView.Title.password, isPassword: true + focusedField: $focusedField, + text: $store.password, + description: L10n.Localizable.LoginView.Title.password, + isPassword: true ) } .padding(.horizontal, proxy.size.width * 0.2) @@ -44,17 +50,21 @@ struct LoginView: View { Button { store.send(.login) } label: { - Image(systemSymbol: .chevronForwardCircleFill) + Image(systemSymbol: .chevronForward) + .padding() + .clipShape(.circle) } .overlay { ProgressView() .tint(nil) .opacity(store.loginState == .loading ? 1 : 0) } - .imageScale(.large) - .font(.largeTitle) - .foregroundColor(store.loginButtonColor) - .disabled(store.loginButtonDisabled).padding(.top, 30) + .font(.title) + .foregroundStyle(store.loginButtonColor) + .disabled(store.loginButtonDisabled) + .glassEffect(.regular.interactive(), in: .circle) + .clipShape(.circle) + .padding(.top, 30) } } } @@ -63,6 +73,7 @@ struct LoginView: View { WebView(url: route.wrappedValue) { store.send(.loginDone(.success(nil))) } + .ignoresSafeArea(edges: .bottom) .autoBlur(radius: blurRadius) } .onSubmit { @@ -100,10 +111,6 @@ private struct LoginTextField: View { private let description: String private let isPassword: Bool - private var backgroundColor: Color { - colorScheme == .light ? Color(.systemGray6) : Color(.systemGray5) - } - init( focusedField: FocusState.Binding, text: Binding, description: String, isPassword: Bool @@ -116,7 +123,10 @@ private struct LoginTextField: View { var body: some View { VStack(alignment: .leading, spacing: 8) { - Text(description).font(.caption).foregroundStyle(.secondary) + Text(description) + .font(.caption) + .foregroundStyle(.secondary) + Group { if isPassword { SecureField("", text: $text) @@ -125,10 +135,13 @@ private struct LoginTextField: View { } } .focused(focusedField.projectedValue, equals: isPassword ? .password : .username) - .textContentType(isPassword ? .password : .username).submitLabel(isPassword ? .done : .next) - .textInputAutocapitalization(.none).disableAutocorrection(true) - .keyboardType(isPassword ? .asciiCapable : .default).padding(10) - .background(backgroundColor.opacity(0.75).cornerRadius(8)) + .textContentType(isPassword ? .password : .username) + .submitLabel(isPassword ? .done : .next) + .textInputAutocapitalization(.none) + .disableAutocorrection(true) + .keyboardType(isPassword ? .asciiCapable : .default) + .padding(10) + .glassEffect(.regular.tint(Color(.systemGray5)), in: .rect(cornerRadius: 8)) } } } diff --git a/EhPanda/View/Support/Components/AlertView.swift b/EhPanda/View/Support/Components/AlertView.swift index 3bb57300..06481449 100644 --- a/EhPanda/View/Support/Components/AlertView.swift +++ b/EhPanda/View/Support/Components/AlertView.swift @@ -121,9 +121,12 @@ struct AlertViewButton: View { var body: some View { Button(action: action) { - Text(title).foregroundColor(.primary.opacity(0.7)).textCase(.uppercase) + Text(title) + .foregroundColor(.primary.opacity(0.7)) + .textCase(.uppercase) } - .buttonStyle(.bordered).buttonBorderShape(.capsule) + .buttonBorderShape(.capsule) + .buttonStyle(.glass) } } diff --git a/EhPanda/View/Support/Components/ToolbarItems.swift b/EhPanda/View/Support/Components/ToolbarItems.swift index 7139d358..ef4d850e 100644 --- a/EhPanda/View/Support/Components/ToolbarItems.swift +++ b/EhPanda/View/Support/Components/ToolbarItems.swift @@ -23,10 +23,11 @@ struct CustomToolbarItem: ToolbarContent { var body: some ToolbarContent { ToolbarItem(placement: placement) { - HStack { + HStack(spacing: 14) { content } - .foregroundColor(tint).disabled(disabled) + .foregroundColor(tint) + .disabled(disabled) } } } diff --git a/README.md b/README.md index 5fb894eb..ca0249a8 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ https://ehpanda.app: [main.js](https://github.com/EhPanda-Team/ehpanda-website/b 2. Use some software like [AltStore](https://altstore.io) to install the ipa file on your device. ## System Requirements -This app requires iOS / iPadOS 17.0 or later. +This app requires iOS / iPadOS 26.0 or later. ## Content & Copyright The content in this application is derived from E-Hentai, which is user-generated content. diff --git a/READMEs/README.chs.md b/READMEs/README.chs.md index 468d79cb..298fee04 100644 --- a/READMEs/README.chs.md +++ b/READMEs/README.chs.md @@ -29,7 +29,7 @@ https://ehpanda.app: [main.js](https://github.com/EhPanda-Team/ehpanda-website/b 2. 使用 [AltStore](https://altstore.io) 这类软件将 ipa 文件安装到你的设备。 ## 系统要求 -请确保你的设备系统为 iOS / iPadOS 17.0 以上。 +请确保你的设备系统为 iOS / iPadOS 26.0 以上。 ## 内容及其著作权 本应用程序中的内容均来自 E-Hentai,而 E-Hentai 的内容均为用户生成内容。 diff --git a/READMEs/README.cht.md b/READMEs/README.cht.md index 53b3bb86..d9101b2d 100644 --- a/READMEs/README.cht.md +++ b/READMEs/README.cht.md @@ -29,7 +29,7 @@ https://ehpanda.app: [main.js](https://github.com/EhPanda-Team/ehpanda-website/b 2. 使用 [AltStore](https://altstore.io) 這類軟件將 ipa 文件安裝到你的裝置。 ## 系統需求 -須使用 iOS / iPadOS 17.0 或以上版本。 +須使用 iOS / iPadOS 26.0 或以上版本。 ## 內容及其著作權 本應用程式內的內容均來自 E-Hentai,而 E-Hentai 的內容均為用戶生成內容。 diff --git a/READMEs/README.de.md b/READMEs/README.de.md index 8c966c03..e337f0e9 100644 --- a/READMEs/README.de.md +++ b/READMEs/README.de.md @@ -29,7 +29,7 @@ https://ehpanda.app: [main.js](https://github.com/EhPanda-Team/ehpanda-website/b 2. Nutze eine Programm zur Installation von nicht im Appstore gelisteten Dateien wie z.B. [AltStore](https://altstore.io) um die IPA-Datei zu installieren. ## Systemanforderungen -Diese App erfordert iOS / iPadOS 17.0 oder neuer. +Diese App erfordert iOS / iPadOS 26.0 oder neuer. ## Inhalte & Copyright Der Inhalt der von dieser App verwaltet wird, wird von E-Hentai geladen. Hierbei handelt es sich um von anderen Nutzern generierten Inhalt. diff --git a/READMEs/README.jpn.md b/READMEs/README.jpn.md index 32da5083..64d6a06a 100644 --- a/READMEs/README.jpn.md +++ b/READMEs/README.jpn.md @@ -29,7 +29,7 @@ https://ehpanda.app: [main.js](https://github.com/EhPanda-Team/ehpanda-website/b 2. [AltStore](https://altstore.io) とかで ipa ファイルをデバイスにインストール。 ## 必要システム構成 -iOS・iPadOS 17.0 以上が必要です。 +iOS・iPadOS 26.0 以上が必要です。 ## コンテンツとその著作権 本アプリの内容はすべて E-Hentai 由来のもので、E-Hentai の内容もまたすべてユーザー生成コンテンツです。 diff --git a/READMEs/README.ko.md b/READMEs/README.ko.md index b9b593fe..540177a5 100644 --- a/READMEs/README.ko.md +++ b/READMEs/README.ko.md @@ -29,7 +29,7 @@ https://ehpanda.app: [main.js](https://github.com/EhPanda-Team/ehpanda-website/b 2. [AltStore](https://altstore.io)를 사용해서 ipa 파일을 설치할 수 있습니다. ## 시스템 요구 사항 -iOS / iPadOS 버전이 17.0 이상인지 확인해주세요. +iOS / iPadOS 버전이 26.0 이상인지 확인해주세요. ## 컨텐츠와 저작권 이 앱의 내용은 E-Hentai을 통해 제공되고, E-Hentai의 모든 내용은 앱 이용자가 만듭니다. diff --git a/ShareExtension/Info.plist b/ShareExtension/Info.plist index 6c33430d..4c8c1c00 100644 --- a/ShareExtension/Info.plist +++ b/ShareExtension/Info.plist @@ -2,6 +2,8 @@ + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) NSExtension NSExtensionAttributes @@ -17,7 +19,5 @@ NSExtensionPrincipalClass $(PRODUCT_MODULE_NAME).ShareViewController - CFBundleShortVersionString - 2.7.10