diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 00000000..fb74d205 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,30 @@ +## Issue + +- close #TBD + +## Overview + +TBD + +## Details (Optional) + +TBD + +## Screenshots (Optional) + +|Before|After| +|:--:|:--:| +|TBD|TBD| + +## Checklist + +- [ ] Format code with SwiftLint (⌘B in Xcode) +- [ ] Resolve Xcode warning + +## What to check (Optional) + +- [ ] TBD + +## Reference(s) (Optional) + +- https://example.com diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 89ff90a5..bd1c41b9 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -8,244 +8,134 @@ on: paths-ignore: - Docs/** - README.md + - README.ja.md - LICENSE - - Rambafile pull_request: - branches: - # - !main - - develop paths-ignore: - Docs/** - README.md + - README.ja.md - LICENSE - - Rambafile + workflow_dispatch: + +permissions: + contents: read env: - DEVELOPER_DIR: /Applications/Xcode_13.0.app + DEVELOPER_DIR: /Applications/Xcode_14.1.app jobs: build: - runs-on: macos-11 + name: build for ${{ matrix.environment }} + runs-on: macos-12 + strategy: + fail-fast: false + matrix: + environment: ["develop", "production"] steps: # チェックアウト - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - # Bundlerで管理しているライブラリのキャッシュ - - name: Cache Gems - uses: actions/cache@v2 - with: - path: vendor/bundle - key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }} - restore-keys: | - ${{ runner.os }}-gems- - - # Bundlerで管理しているライブラリのインストール - - name: Install Bundled Gems - run: make install-bundler - - # SwiftPMで管理しているCLIツールのキャッシュ - - name: Cache CLI tools managed by SwiftPM - uses: actions/cache@v2 - id: cli-tools-cache - with: - path: Tools/UhooiPicBookTools/.build - key: ${{ runner.os }}-spm-${{ hashFiles('**/Tools/UhooiPicBookTools/Package.resolved') }} - restore-keys: | - ${{ runner.os }}-spm- - - # SwiftPMで管理しているCLIツールのビルド - - name: Build CLI tools managed by SwiftPM - if: steps.cli-tools-cache.outputs.cache-hit != 'true' - run: make build-cli-tools - - # Mockoloのキャッシュ - - name: Cache Mockolo - uses: actions/cache@v2 - id: mockolo-cache - with: - path: Tools/UhooiPicBookMockolo/.build - key: ${{ runner.os }}-spm-${{ hashFiles('**/Tools/UhooiPicBookMockolo/Package.resolved') }} - restore-keys: | - ${{ runner.os }}-spm- - - # Mockoloのビルド - - name: Build Mockolo - if: steps.mockolo-cache.outputs.cache-hit != 'true' - run: make build-mockolo - - # Firebase SDKのダウンロード - - name: Download Firebase SDK - run: make download-firebase-sdk - - # ライセンス情報の生成 - - name: Generate licenses - run: make generate-licenses - - # プロジェクトファイルの生成 - - name: Generate Xcode project for develop - run: make generate-xcodeproj-develop - - # SwiftPMで管理しているライブラリのキャッシュ - - name: Cache libraries managed by SwiftPM - uses: actions/cache@v2 - with: - path: SourcePackages - key: ${{ runner.os }}-swiftpm-${{ hashFiles('**/UhooiPicBook.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved') }} - restore-keys: | - ${{ runner.os }}-swiftpm- + # セットアップ + - uses: ./.github/workflows/templates/setup-ios # ビルド - - name: Xcode build - run: make build-debug + - name: Xcode build for ${{ matrix.environment }} + run: | + make build-debug-${{ matrix.environment }} # ビルドログのアップロード - name: Upload build log Artifact - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 if: failure() with: name: xcodebuild-logs - path: xcodebuild_build.log + path: | + Reports/*_Build.log if-no-files-found: ignore retention-days: 14 test: - runs-on: macos-11 + name: test for ${{ matrix.name }} + runs-on: macos-12 + strategy: + fail-fast: false + matrix: + name: ["develop", "production", "app-module"] steps: # チェックアウト - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - # Bundlerで管理しているライブラリのキャッシュ - - name: Cache Gems - uses: actions/cache@v2 - with: - path: vendor/bundle - key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }} - restore-keys: | - ${{ runner.os }}-gems- - - # Bundlerで管理しているライブラリのインストール - - name: Install Bundled Gems - run: make install-bundler - - # SwiftPMで管理しているCLIツールのキャッシュ - - name: Cache CLI tools managed by SwiftPM - uses: actions/cache@v2 - id: cli-tools-cache - with: - path: Tools/UhooiPicBookTools/.build - key: ${{ runner.os }}-spm-${{ hashFiles('**/Tools/UhooiPicBookTools/Package.resolved') }} - restore-keys: | - ${{ runner.os }}-spm- - - # SwiftPMで管理しているCLIツールのビルド - - name: Build CLI tools managed by SwiftPM - if: steps.cli-tools-cache.outputs.cache-hit != 'true' - run: make build-cli-tools - - # Mockoloのキャッシュ - - name: Cache Mockolo - uses: actions/cache@v2 - id: mockolo-cache - with: - path: Tools/UhooiPicBookMockolo/.build - key: ${{ runner.os }}-spm-${{ hashFiles('**/Tools/UhooiPicBookMockolo/Package.resolved') }} - restore-keys: | - ${{ runner.os }}-spm- - - # Mockoloのビルド - - name: Build Mockolo - if: steps.mockolo-cache.outputs.cache-hit != 'true' - run: make build-mockolo - - # Firebase SDKのダウンロード - - name: Download Firebase SDK - run: make download-firebase-sdk - - # ライセンス情報の生成 - - name: Generate licenses - run: make generate-licenses - - # プロジェクトファイルの生成 - - name: Generate Xcode project for develop - run: make generate-xcodeproj-develop - - # SwiftPMで管理しているライブラリのキャッシュ - - name: Cache libraries managed by SwiftPM - uses: actions/cache@v2 - with: - path: SourcePackages - key: ${{ runner.os }}-swiftpm-${{ hashFiles('**/UhooiPicBook.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved') }} - restore-keys: | - ${{ runner.os }}-swiftpm- + # セットアップ + - uses: ./.github/workflows/templates/setup-ios + + # モックの生成 + - name: Generate mocks with Mockolo + run: make generate-mocks # 単体テストの実行 - name: Xcode test - run: make test + run: | + make test-debug-${{ matrix.name }} + + # テスト結果のアップロード + - name: Upload test results Artifact + uses: actions/upload-artifact@v3 + if: success() || failure() + with: + name: test-results + path: | + Reports/*.xcresult + if-no-files-found: error + retention-days: 14 # 単体テストログのアップロード - name: Upload test log Artifact - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 if: failure() with: name: xcodebuild-logs - path: xcodebuild_test.log + path: | + Reports/*_Test.log if-no-files-found: ignore retention-days: 14 - # コードカバレッジをHTML形式で取得 - - name: Get code coverage for HTML - run: make get-coverage-html + show-test-results: + runs-on: macos-12 + permissions: + checks: write + needs: test - # コードカバレッジのアップロード - - name: Upload test results and code coverage Artifact - uses: actions/upload-artifact@v2 + steps: + # チェックアウト + - uses: actions/checkout@v3 + + # テスト結果のダウンロード + - name: Download test results artifact + uses: actions/download-artifact@v3 with: - name: results - path: | - html_report/**/* - if-no-files-found: warn - retention-days: 14 + name: test-results + path: Reports - # コードカバレッジをCobertura形式で取得 - - name: Get code coverage for Cobertura - run: make get-coverage-cobertura + # テスト結果のマージ + - name: Merge test results + run: make merge-test-results - # コードカバレッジをCodecovへアップロード - - name: Upload code coverage to Codecov - run: make upload-coverage - env: - CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + # テスト結果の表示とアップロード + - uses: kishikawakatsumi/xcresulttool@v1 + if: success() || failure() + with: + path: Reports/TestResults.xcresult info: - runs-on: macos-11 + runs-on: macos-12 steps: # チェックアウト - - uses: actions/checkout@v2 - - # Xcodeの一覧出力 - - name: Show Xcode list - run: ls /Applications | grep 'Xcode' - - # Xcodeのバージョン出力 - - name: Show Xcode version - run: xcodebuild -version - - # Makeのバージョン出力 - - name: Show Make version - run: make --version - - # Rubyのバージョン出力 - - name: Show Ruby version - run: ruby --version - - # Bundlerのバージョン出力 - - name: Show Bundler version - run: bundle version + - uses: actions/checkout@v3 - # 端末の一覧出力 - - name: Show devices - run: make show-devices + # 情報の出力 + - uses: ./.github/workflows/templates/output-info diff --git a/.github/workflows/opened-issue.yml b/.github/workflows/opened-issue.yml index 74690c60..692ff17e 100644 --- a/.github/workflows/opened-issue.yml +++ b/.github/workflows/opened-issue.yml @@ -5,15 +5,17 @@ on: types: - opened +permissions: + issues: write + jobs: comment: runs-on: ubuntu-latest steps: - - uses: actions/github-script@v2 + - uses: actions/github-script@v6 with: - github-token: ${{secrets.GITHUB_TOKEN}} script: | - github.issues.createComment({ + github.rest.issues.createComment({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, @@ -23,11 +25,10 @@ jobs: apply-label: runs-on: ubuntu-latest steps: - - uses: actions/github-script@v2 + - uses: actions/github-script@v6 with: - github-token: ${{secrets.GITHUB_TOKEN}} script: | - github.issues.addLabels({ + github.rest.issues.addLabels({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, diff --git a/.github/workflows/swiftlint.yml b/.github/workflows/swiftlint.yml index e7b086b0..1d3ba8f0 100644 --- a/.github/workflows/swiftlint.yml +++ b/.github/workflows/swiftlint.yml @@ -7,11 +7,14 @@ on: - '.swiftlint.yml' - '**/*.swift' +permissions: + contents: read + jobs: - SwiftLint: + swiftlint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: GitHub Action for SwiftLint uses: norio-nomura/action-swiftlint@3.2.1 diff --git a/.github/workflows/templates/output-info/action.yml b/.github/workflows/templates/output-info/action.yml new file mode 100644 index 00000000..cdcb7bfb --- /dev/null +++ b/.github/workflows/templates/output-info/action.yml @@ -0,0 +1,26 @@ +name: "Output info" +description: "Output the information of each tool" + +runs: + using: "composite" + steps: + # Xcodeの一覧出力 + - name: Show Xcode list + run: ls /Applications | grep 'Xcode' + shell: bash + + # Xcodeのバージョン出力 + - name: Show Xcode version + run: xcodebuild -version + shell: bash + + # Makeのバージョン出力 + - name: Show Make version + run: make --version + shell: bash + + # 端末の一覧出力 + - name: Show devices + run: make show-devices + shell: bash + diff --git a/.github/workflows/templates/setup-ios/action.yml b/.github/workflows/templates/setup-ios/action.yml new file mode 100644 index 00000000..d609771d --- /dev/null +++ b/.github/workflows/templates/setup-ios/action.yml @@ -0,0 +1,48 @@ +name: "Setup for iOS" +description: "Install dependencies and prepared development configuration for iOS" + +runs: + using: "composite" + steps: + # Swiftプロジェクトのビルドの高速化 + - name: Enable faster builds for Swift projects + run: defaults write com.apple.dt.XCBuild EnableSwiftBuildSystemIntegration 1 + shell: bash + + # コマンドラインツールのインストール(Xcode 13.3.1でビルドエラーが発生するワークアラウンド) + # ref: https://developer.apple.com/forums/thread/703233 + - name: Install Command Line Tools for Xcode + run: sudo xcode-select -s /Library/Developer/CommandLineTools + shell: bash + + # SwiftPMで管理しているCLIツールのキャッシュ + - name: Cache CLI tools managed by SwiftPM + uses: actions/cache@v3 + id: cli-tools-cache + with: + path: Tools/UhooiPicBookTools/.build + key: ${{ runner.os }}-spm-${{ hashFiles('**/Tools/UhooiPicBookTools/Package.resolved') }} + + # SwiftPMで管理しているCLIツールのビルド + - name: Build CLI tools managed by SwiftPM + if: steps.cli-tools-cache.outputs.cache-hit != 'true' + run: make build-cli-tools + shell: bash + + # Firebase SDKのダウンロード + - name: Download Firebase SDK + run: make download-firebase-sdk + shell: bash + + # ライセンス情報の生成 + - name: Generate licenses + run: make generate-licenses + shell: bash + + # SwiftPMで管理しているライブラリのキャッシュ + - name: Cache libraries managed by SwiftPM + uses: actions/cache@v3 + with: + path: SourcePackages + key: ${{ runner.os }}-spm-${{ hashFiles('**/UhooiPicBook.xcworkspace/xcshareddata/swiftpm/Package.resolved') }} + diff --git a/.gitignore b/.gitignore index 16fdbfcb..a3f6d99f 100644 --- a/.gitignore +++ b/.gitignore @@ -40,11 +40,11 @@ playground.xcworkspace # Packages/ # Package.pins # Package.resolved -*.xcodeproj +# *.xcodeproj # # Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata # hence it is not needed unless you have added a package configuration file to your project -# .swiftpm +.swiftpm .build/ @@ -57,7 +57,7 @@ playground.xcworkspace Pods/ # # Add this line if you want to avoid checking in source code from the Xcode workspace -*.xcworkspace +# *.xcworkspace # Carthage # @@ -89,16 +89,11 @@ fastlane/test_output iOSInjectionProject/ -# Genrated -*.generated.swift -MockResults.swift - -# Bundler -vendor/bundle/ -.bundle/ +# Project dependencies are resolved by the workspace +*.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved -# Generamba -Templates/ +# Mockolo +MockResults.swift # LicensePlist com.mono0926.LicensePlist/ @@ -106,19 +101,15 @@ com.mono0926.LicensePlist.latest_result.txt com.mono0926.LicensePlist.plist # Firebase -GoogleService-Info.plist Frameworks/Firebase/ -# xcodebuild log -xcodebuild_*.log - # SwiftLint Remote Config Cache .swiftlint/RemoteConfigCache -# Slather -xml_report/ -html_report/ - # Swift Package Manager SourcePackages/ +# Reports +Reports/* +!Reports/.gitkeep + diff --git a/.iblinter.yml b/.iblinter.yml index d13fd9cf..f2fafdb4 100644 --- a/.iblinter.yml +++ b/.iblinter.yml @@ -1,4 +1,3 @@ -# デフォルト有効で無効にするルール disabled_rules: #- enable_autolayout #- duplicate_constraint @@ -6,7 +5,6 @@ disabled_rules: #- custom_module #- ambiguous -# デフォルト無効で有効にするルール enabled_rules: #- custom_class_name # ファイル名は末尾の `ViewController` を省略したいため - relative_to_margin @@ -19,8 +17,19 @@ enabled_rules: - reuse_identifier - color_resources - use_trait_collections + #- hides_bottom_bar # [Hide Bottom Bar on Push]はデフォルトOFFのため + +included: + - Shared + - UhooiPicBook + - UhooiPicBookStickers + - UhooiPicBookWidgets + - UhooiPicBookWidgetsConfigurableIntent + - UhooiPicBookTests + - UhooiPicBookUITests + - Sources + - Tests -# 対象外のファイル・フォルダ excluded: - SourcePackages - Tools diff --git a/.lic-plist.yml b/.lic-plist.yml new file mode 100644 index 00000000..67650839 --- /dev/null +++ b/.lic-plist.yml @@ -0,0 +1,5 @@ +github: + - owner: firebase + name: firebase-ios-sdk + version: v8.12.1 + diff --git a/.ruby-version b/.ruby-version deleted file mode 100644 index 860487ca..00000000 --- a/.ruby-version +++ /dev/null @@ -1 +0,0 @@ -2.7.1 diff --git a/.slather.yml b/.slather.yml deleted file mode 100644 index c4cf51e2..00000000 --- a/.slather.yml +++ /dev/null @@ -1,16 +0,0 @@ -coverage_service: cobertura_xml -xcodeproj: UhooiPicBook.xcodeproj -scheme: UhooiPicBook -source_directory: UhooiPicBook -output_directory: xml_report -ignore: - - SourcePackages/* - - "**/AppDelegate.swift" - - "**/SceneDelegate.swift" - - "**/Generated/*" - - "**/Util/Debug.swift" - - "**/Extensions/UIKit/*" - - "**/UIParts/*" - - "**/Views/*" - - "**/Routers/*" - diff --git a/spell-checker.yml b/.spell-checker.yml similarity index 66% rename from spell-checker.yml rename to .spell-checker.yml index fd89ca70..479bf141 100644 --- a/spell-checker.yml +++ b/.spell-checker.yml @@ -1,14 +1,19 @@ whiteList: # Common - codable + - autoclosure - lhs - rhs - dto + - dtos - interactor - swiftlint + - bannzai - gedatsu - json - hashable + - iterable + - diffable - fcm - github - thii @@ -17,6 +22,13 @@ whiteList: - fromkk - uber - mockolo + - crashlytics + - firestore + - nanopb + - leveldb + - xcframework + - nslocalizedstring + - xfrontend # Uhooi - theuhooi diff --git a/.swiftlint.yml b/.swiftlint.yml index 759f3a9d..fcf5ad1a 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -1,4 +1,16 @@ -parent_config: https://raw.githubusercontent.com/uhooi/SwiftLint-Config/v1.1.0/uhooi-base-swiftlint-config.yml +parent_config: https://raw.githubusercontent.com/uhooi/SwiftLint-Config/v1.10.0/uhooi-base-swiftlint-config.yml + +disabled_rules: + - missing_docs + +custom_rules: + if_let_shorthand: + included: + - ".*\\.swift" + name: "`if let` shorthand for shadowing an existing optional variable" + regex: '(if|guard)\s+let\s+(.+?)\s*=\s*(\2)(\s+|\{)' + message: "Use `if let` shorthand." + severity: warning included: - Shared @@ -6,9 +18,13 @@ included: - UhooiPicBookStickers - UhooiPicBookWidgets - UhooiPicBookWidgetsConfigurableIntent - #- UhooiPicBookTests - #- UhooiPicBookUITests + - Sources excluded: - - UhooiPicBook/Generated + - UhooiPicBookTests + - UhooiPicBookUITests + - Tests + - SourcePackages + - Tools + - Generated diff --git a/App/.gitignore b/App/.gitignore new file mode 100644 index 00000000..3e6af795 --- /dev/null +++ b/App/.gitignore @@ -0,0 +1,2 @@ +# SwiftLint Remote Config Cache +.swiftlint/RemoteConfigCache \ No newline at end of file diff --git a/App/Develop.xcodeproj/project.pbxproj b/App/Develop.xcodeproj/project.pbxproj new file mode 100644 index 00000000..2fce5716 --- /dev/null +++ b/App/Develop.xcodeproj/project.pbxproj @@ -0,0 +1,1365 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXBuildFile section */ + 2AB9187FB6C6F195BDFA0AEA /* UhooiPicBookUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F77956692405C61E8D8C04B5 /* UhooiPicBookUITests.swift */; }; + 3784E43C6F9862BB2E871B15 /* UhooiPicBookWidgetsConfigurableIntent.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = D3A28FF132F9DB6448EAC23F /* UhooiPicBookWidgetsConfigurableIntent.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + 3ED6158022DE90CA4AA73905 /* ImagePopupPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C5239C3163F47164ECE33E8 /* ImagePopupPage.swift */; }; + 478286982E492B33E65E682B /* ActivityPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1BC591FA4C18A058784472F /* ActivityPage.swift */; }; + 5022F0F1F72B5341C9486B7A /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 33B49E10FB3AFB3745B0AEF4 /* SwiftUI.framework */; }; + 522896F9FC51ED2221060387 /* MonsterListPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = B21F0F147EB90FE7EAF86DB2 /* MonsterListPage.swift */; }; + 745EB4E9574D57EB307F2AB9 /* UhooiPicBookStickers.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = D97430DE3B018D83FA30BA3F /* UhooiPicBookStickers.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + 791904CA2793F9CB00416F7D /* ImageLoader in Frameworks */ = {isa = PBXBuildFile; productRef = 791904C92793F9CB00416F7D /* ImageLoader */; }; + 791904CE2794082700416F7D /* MonstersRepository in Frameworks */ = {isa = PBXBuildFile; productRef = 791904CD2794082700416F7D /* MonstersRepository */; }; + 791904D02794083500416F7D /* MonstersRepository in Frameworks */ = {isa = PBXBuildFile; productRef = 791904CF2794083500416F7D /* MonstersRepository */; }; + 7921EEFD2785E6370033DDEC /* FirebaseSetup in Frameworks */ = {isa = PBXBuildFile; productRef = 7921EEFC2785E6370033DDEC /* FirebaseSetup */; }; + 7921EEFF2785E63E0033DDEC /* FirebaseSetup in Frameworks */ = {isa = PBXBuildFile; productRef = 7921EEFE2785E63E0033DDEC /* FirebaseSetup */; }; + 792E8ED9278C4299000F3902 /* WidgetsConfiguration.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = 792E8ED3278C4299000F3902 /* WidgetsConfiguration.intentdefinition */; }; + 792E8EDA278C4299000F3902 /* WidgetsConfiguration.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = 792E8ED3278C4299000F3902 /* WidgetsConfiguration.intentdefinition */; }; + 792E8EDB278C4299000F3902 /* WidgetsConfiguration.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = 792E8ED3278C4299000F3902 /* WidgetsConfiguration.intentdefinition */; }; + 792E8EDC278C4299000F3902 /* MonsterIntentObject+Convert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 792E8ED5278C4299000F3902 /* MonsterIntentObject+Convert.swift */; }; + 792E8EDD278C4299000F3902 /* MonsterIntentObject+Convert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 792E8ED5278C4299000F3902 /* MonsterIntentObject+Convert.swift */; }; + 792E8EDE278C4299000F3902 /* MonsterIntentObject+Convert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 792E8ED5278C4299000F3902 /* MonsterIntentObject+Convert.swift */; }; + 792E8F1B278C445E000F3902 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 792E8F0E278C445E000F3902 /* InfoPlist.strings */; }; + 792E8F1E278C445E000F3902 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 792E8F15278C445E000F3902 /* LaunchScreen.storyboard */; }; + 792E8F20278C445E000F3902 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 792E8F18278C445E000F3902 /* AppDelegate.swift */; }; + 792E8F21278C445E000F3902 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 792E8F19278C445E000F3902 /* SceneDelegate.swift */; }; + 792E8F55278C4C22000F3902 /* Stickers.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 792E8F53278C4C22000F3902 /* Stickers.xcassets */; }; + 792E8F85278C6465000F3902 /* MonsterConfigurableWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 792E8F82278C6465000F3902 /* MonsterConfigurableWidget.swift */; }; + 792E8F86278C6465000F3902 /* UhooiPicBookWidgets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 792E8F83278C6465000F3902 /* UhooiPicBookWidgets.swift */; }; + 792E8F92278C675C000F3902 /* IntentHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 792E8F90278C675C000F3902 /* IntentHandler.swift */; }; + 792E8F9A278C6901000F3902 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 792E8F99278C6901000F3902 /* Assets.xcassets */; }; + 792E8F9E278C6A3C000F3902 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 792E8F9D278C6A3C000F3902 /* GoogleService-Info.plist */; }; + 792E8F9F278C6A3C000F3902 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 792E8F9D278C6A3C000F3902 /* GoogleService-Info.plist */; }; + 792E8FA0278C6A3C000F3902 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 792E8F9D278C6A3C000F3902 /* GoogleService-Info.plist */; }; + 792E8FD9278C7ABC000F3902 /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 792E8FD8278C7ABC000F3902 /* Settings.bundle */; }; + 797ABFA7278A9B59005B445B /* AppModule in Frameworks */ = {isa = PBXBuildFile; productRef = 797ABFA6278A9B59005B445B /* AppModule */; }; + 7995BD2E2786F35200B553DC /* FirebaseMessagingBridge in Frameworks */ = {isa = PBXBuildFile; productRef = 7995BD2D2786F35200B553DC /* FirebaseMessagingBridge */; }; + 79C193A92789CF1D00E7A58E /* MonsterWidgets in Frameworks */ = {isa = PBXBuildFile; productRef = 79C193A82789CF1D00E7A58E /* MonsterWidgets */; }; + 7B7002A645C43EBB624D82D8 /* MonsterDetailPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B117974B5DFAEB1BA1DB35C /* MonsterDetailPage.swift */; }; + A1713DA74A4AE73B34351622 /* XCUIElement+Ex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 541427EC2F900D49CD247CB2 /* XCUIElement+Ex.swift */; }; + A6BE80E8825B6DA6ACE56D06 /* BundleStringTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4618659C63EB6D450468854 /* BundleStringTests.swift */; }; + ED23EF346F55E2E02F461F16 /* PageProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B1D686A013EAD76B19604C9 /* PageProtocol.swift */; }; + F84FC678215D503C49D26C58 /* UhooiPicBookWidgets.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = AE659249AE186390141063EE /* UhooiPicBookWidgets.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + F8BBF148F1591E57471509B2 /* WidgetKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3678749154206AA2C7DE69F6 /* WidgetKit.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 46DB71745F7E01A515C0F13C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 8F21FB9F02C54BE4076B12F8 /* Project object */; + proxyType = 1; + remoteGlobalIDString = F7174334A4963303CCEE4E61; + remoteInfo = UhooiPicBook; + }; + 73857B2E0E8A6F194DF299E9 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 8F21FB9F02C54BE4076B12F8 /* Project object */; + proxyType = 1; + remoteGlobalIDString = F7174334A4963303CCEE4E61; + remoteInfo = UhooiPicBook; + }; + 8DABA011EEC5DA70896A6C44 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 8F21FB9F02C54BE4076B12F8 /* Project object */; + proxyType = 1; + remoteGlobalIDString = C2DB76B6BCC6E8EF34FA57BF; + remoteInfo = UhooiPicBookWidgetsConfigurableIntent; + }; + EA1D5D72FB9D70100338E4A8 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 8F21FB9F02C54BE4076B12F8 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 162395B56ED57E8800847617; + remoteInfo = UhooiPicBookWidgets; + }; + F97CF2FC9CF60F60A337F2AA /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 8F21FB9F02C54BE4076B12F8 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 0E1AD029696068D4B516B255; + remoteInfo = UhooiPicBookStickers; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 4224260094675C4E9D31B589 /* Embed Foundation Extensions */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 13; + files = ( + 745EB4E9574D57EB307F2AB9 /* UhooiPicBookStickers.appex in Embed Foundation Extensions */, + F84FC678215D503C49D26C58 /* UhooiPicBookWidgets.appex in Embed Foundation Extensions */, + 3784E43C6F9862BB2E871B15 /* UhooiPicBookWidgetsConfigurableIntent.appex in Embed Foundation Extensions */, + ); + name = "Embed Foundation Extensions"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 056CC3440EC68EDD8CB4F9D0 /* FirebaseAppDistribution.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = FirebaseAppDistribution.xcframework; path = Frameworks/Firebase/FirebaseAppDistribution/FirebaseAppDistribution.xcframework; sourceTree = ""; }; + 10643B8C75A51C25725E377B /* FirebaseAnalytics.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = FirebaseAnalytics.xcframework; path = Frameworks/Firebase/FirebaseAnalytics/FirebaseAnalytics.xcframework; sourceTree = ""; }; + 144AF202560DF7170CA1B88E /* FirebaseRemoteConfig.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = FirebaseRemoteConfig.xcframework; path = Frameworks/Firebase/FirebasePerformance/FirebaseRemoteConfig.xcframework; sourceTree = ""; }; + 18C42AC12CA0DA009E4241B5 /* leveldb-library.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = "leveldb-library.xcframework"; path = "Frameworks/Firebase/FirebaseFirestore/leveldb-library.xcframework"; sourceTree = ""; }; + 1B117974B5DFAEB1BA1DB35C /* MonsterDetailPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MonsterDetailPage.swift; sourceTree = ""; }; + 33B49E10FB3AFB3745B0AEF4 /* SwiftUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftUI.framework; path = System/Library/Frameworks/SwiftUI.framework; sourceTree = SDKROOT; }; + 3678749154206AA2C7DE69F6 /* WidgetKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WidgetKit.framework; path = System/Library/Frameworks/WidgetKit.framework; sourceTree = SDKROOT; }; + 39F4CD1686D945CFB87141CE /* GoogleUtilities.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = GoogleUtilities.xcframework; path = Frameworks/Firebase/FirebaseAnalytics/GoogleUtilities.xcframework; sourceTree = ""; }; + 541427EC2F900D49CD247CB2 /* XCUIElement+Ex.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "XCUIElement+Ex.swift"; sourceTree = ""; }; + 5FC40872E7A32ADB0B8AE3D7 /* FirebaseFirestore.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = FirebaseFirestore.xcframework; path = Frameworks/Firebase/FirebaseFirestore/FirebaseFirestore.xcframework; sourceTree = ""; }; + 64FA23DFA00E386CF2DBCE63 /* FirebaseCoreDiagnostics.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = FirebaseCoreDiagnostics.xcframework; path = Frameworks/Firebase/FirebaseAnalytics/FirebaseCoreDiagnostics.xcframework; sourceTree = ""; }; + 792E8ED4278C4299000F3902 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.intentdefinition; name = Base; path = Base.lproj/WidgetsConfiguration.intentdefinition; sourceTree = ""; }; + 792E8ED5278C4299000F3902 /* MonsterIntentObject+Convert.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "MonsterIntentObject+Convert.swift"; sourceTree = ""; }; + 792E8EDF278C42BD000F3902 /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/WidgetsConfiguration.strings; sourceTree = ""; }; + 792E8EE0278C42C1000F3902 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/WidgetsConfiguration.strings; sourceTree = ""; }; + 792E8F0F278C445E000F3902 /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/InfoPlist.strings; sourceTree = ""; }; + 792E8F12278C445E000F3902 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; + 792E8F13278C445E000F3902 /* UhooiPicBook.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = UhooiPicBook.entitlements; sourceTree = ""; }; + 792E8F16278C445E000F3902 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 792E8F17278C445E000F3902 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 792E8F18278C445E000F3902 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 792E8F19278C445E000F3902 /* SceneDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; + 792E8F22278C4489000F3902 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/LaunchScreen.strings; sourceTree = ""; }; + 792E8F53278C4C22000F3902 /* Stickers.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Stickers.xcassets; sourceTree = ""; }; + 792E8F54278C4C22000F3902 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 792E8F80278C6465000F3902 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 792E8F82278C6465000F3902 /* MonsterConfigurableWidget.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MonsterConfigurableWidget.swift; sourceTree = ""; }; + 792E8F83278C6465000F3902 /* UhooiPicBookWidgets.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UhooiPicBookWidgets.swift; sourceTree = ""; }; + 792E8F90278C675C000F3902 /* IntentHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IntentHandler.swift; sourceTree = ""; }; + 792E8F91278C675C000F3902 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 792E8F99278C6901000F3902 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = UhooiPicBook/Develop/Assets.xcassets; sourceTree = SOURCE_ROOT; }; + 792E8F9D278C6A3C000F3902 /* GoogleService-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "Shared/Develop/GoogleService-Info.plist"; sourceTree = SOURCE_ROOT; }; + 792E8FD8278C7ABC000F3902 /* Settings.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = Settings.bundle; sourceTree = ""; }; + 7955D06227B94B050061AE99 /* Develop.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = Develop.xctestplan; sourceTree = ""; }; + 7C5239C3163F47164ECE33E8 /* ImagePopupPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImagePopupPage.swift; sourceTree = ""; }; + 83C280827AC1AC8CDC771EC4 /* UhooiPicBookUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = UhooiPicBookUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 84E4ADEF286CCE96A2942A1A /* FirebaseCore.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = FirebaseCore.xcframework; path = Frameworks/Firebase/FirebaseAnalytics/FirebaseCore.xcframework; sourceTree = ""; }; + 8A43FC43A5F5F2869F78909D /* FirebasePerformance.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = FirebasePerformance.xcframework; path = Frameworks/Firebase/FirebasePerformance/FirebasePerformance.xcframework; sourceTree = ""; }; + 8B1D686A013EAD76B19604C9 /* PageProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PageProtocol.swift; sourceTree = ""; }; + 8BA1D60203EDBC076FFF5642 /* FirebaseMessaging.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = FirebaseMessaging.xcframework; path = Frameworks/Firebase/FirebaseMessaging/FirebaseMessaging.xcframework; sourceTree = ""; }; + 8F94607B0325642C330CD793 /* nanopb.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = nanopb.xcframework; path = Frameworks/Firebase/FirebaseAnalytics/nanopb.xcframework; sourceTree = ""; }; + 988A97043A06E226C6868588 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; + AE659249AE186390141063EE /* UhooiPicBookWidgets.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = UhooiPicBookWidgets.appex; sourceTree = BUILT_PRODUCTS_DIR; }; + AE841A10BB74D787FB068BD6 /* GoogleDataTransport.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = GoogleDataTransport.xcframework; path = Frameworks/Firebase/FirebaseAnalytics/GoogleDataTransport.xcframework; sourceTree = ""; }; + B121E1EC2442F244D11C5380 /* PromisesObjC.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = PromisesObjC.xcframework; path = Frameworks/Firebase/FirebaseAnalytics/PromisesObjC.xcframework; sourceTree = ""; }; + B21F0F147EB90FE7EAF86DB2 /* MonsterListPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MonsterListPage.swift; sourceTree = ""; }; + B2A9349AFF95EFE00FCADA23 /* FirebaseCrashlytics.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = FirebaseCrashlytics.xcframework; path = Frameworks/Firebase/FirebaseCrashlytics/FirebaseCrashlytics.xcframework; sourceTree = ""; }; + B3034A14E3F41394DEB55A62 /* GoogleAppMeasurement.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = GoogleAppMeasurement.xcframework; path = Frameworks/Firebase/FirebaseAnalytics/GoogleAppMeasurement.xcframework; sourceTree = ""; }; + B3ACB3BE3E7ED3A4C84410CA /* BoringSSL-GRPC.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = "BoringSSL-GRPC.xcframework"; path = "Frameworks/Firebase/FirebaseFirestore/BoringSSL-GRPC.xcframework"; sourceTree = ""; }; + BA21C3023C46CC6151A43886 /* UhooiPicBookTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = UhooiPicBookTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + BD6DB9EB8A33ED4D0822DB8F /* FirebaseABTesting.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = FirebaseABTesting.xcframework; path = Frameworks/Firebase/FirebasePerformance/FirebaseABTesting.xcframework; sourceTree = ""; }; + BF104BB707E325AC73440499 /* FirebaseInstallations.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = FirebaseInstallations.xcframework; path = Frameworks/Firebase/FirebaseAnalytics/FirebaseInstallations.xcframework; sourceTree = ""; }; + D1BC591FA4C18A058784472F /* ActivityPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActivityPage.swift; sourceTree = ""; }; + D3A28FF132F9DB6448EAC23F /* UhooiPicBookWidgetsConfigurableIntent.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = UhooiPicBookWidgetsConfigurableIntent.appex; sourceTree = BUILT_PRODUCTS_DIR; }; + D97430DE3B018D83FA30BA3F /* UhooiPicBookStickers.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = UhooiPicBookStickers.appex; sourceTree = BUILT_PRODUCTS_DIR; }; + E4618659C63EB6D450468854 /* BundleStringTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BundleStringTests.swift; sourceTree = ""; }; + E486EDFB4B99417855E33115 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; + E4EA4C797239C728014E8BCC /* UhooiPicBook.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = UhooiPicBook.app; sourceTree = BUILT_PRODUCTS_DIR; }; + E8C25BE3139AF9A212CCC8F0 /* gRPC-C++.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = "gRPC-C++.xcframework"; path = "Frameworks/Firebase/FirebaseFirestore/gRPC-C++.xcframework"; sourceTree = ""; }; + E93FC0F13B863F9E5F5D500D /* abseil.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = abseil.xcframework; path = Frameworks/Firebase/FirebaseFirestore/abseil.xcframework; sourceTree = ""; }; + F6868AB01C3AABA6F00D83C8 /* gRPC-Core.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = "gRPC-Core.xcframework"; path = "Frameworks/Firebase/FirebaseFirestore/gRPC-Core.xcframework"; sourceTree = ""; }; + F77956692405C61E8D8C04B5 /* UhooiPicBookUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UhooiPicBookUITests.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 6986B5ACA2E569F81163AE24 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 797ABFA7278A9B59005B445B /* AppModule in Frameworks */, + 7995BD2E2786F35200B553DC /* FirebaseMessagingBridge in Frameworks */, + 7921EEFD2785E6370033DDEC /* FirebaseSetup in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 7807E38B57A7E4DC3FAF7927 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 7921EEFF2785E63E0033DDEC /* FirebaseSetup in Frameworks */, + 791904D02794083500416F7D /* MonstersRepository in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + F7D826D061CE893E40DE10DA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 5022F0F1F72B5341C9486B7A /* SwiftUI.framework in Frameworks */, + 791904CA2793F9CB00416F7D /* ImageLoader in Frameworks */, + F8BBF148F1591E57471509B2 /* WidgetKit.framework in Frameworks */, + 79C193A92789CF1D00E7A58E /* MonsterWidgets in Frameworks */, + 791904CE2794082700416F7D /* MonstersRepository in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 17E82F135C45DA22DAD85E72 /* Foundation */ = { + isa = PBXGroup; + children = ( + E4618659C63EB6D450468854 /* BundleStringTests.swift */, + ); + path = Foundation; + sourceTree = ""; + }; + 47C552D3546C641AB89783C1 = { + isa = PBXGroup; + children = ( + 7955D06227B94B050061AE99 /* Develop.xctestplan */, + 781042549E5A01519EFED671 /* Shared */, + 792E8F0B278C445E000F3902 /* UhooiPicBook */, + 792E8F52278C4C22000F3902 /* UhooiPicBookStickers */, + BAB84381A6737A2083BC961F /* UhooiPicBookTests */, + EB1BD4D1C82D8077591B0698 /* UhooiPicBookUITests */, + 792E8F7F278C6465000F3902 /* UhooiPicBookWidgets */, + 792E8F8F278C675C000F3902 /* UhooiPicBookWidgetsConfigurableIntent */, + 644BA30E73485BDC342F7204 /* Frameworks */, + B9F854ED00B8603447D5057B /* Products */, + ); + sourceTree = ""; + }; + 644BA30E73485BDC342F7204 /* Frameworks */ = { + isa = PBXGroup; + children = ( + E93FC0F13B863F9E5F5D500D /* abseil.xcframework */, + B3ACB3BE3E7ED3A4C84410CA /* BoringSSL-GRPC.xcframework */, + BD6DB9EB8A33ED4D0822DB8F /* FirebaseABTesting.xcframework */, + 10643B8C75A51C25725E377B /* FirebaseAnalytics.xcframework */, + 056CC3440EC68EDD8CB4F9D0 /* FirebaseAppDistribution.xcframework */, + 84E4ADEF286CCE96A2942A1A /* FirebaseCore.xcframework */, + 64FA23DFA00E386CF2DBCE63 /* FirebaseCoreDiagnostics.xcframework */, + B2A9349AFF95EFE00FCADA23 /* FirebaseCrashlytics.xcframework */, + 5FC40872E7A32ADB0B8AE3D7 /* FirebaseFirestore.xcframework */, + BF104BB707E325AC73440499 /* FirebaseInstallations.xcframework */, + 8BA1D60203EDBC076FFF5642 /* FirebaseMessaging.xcframework */, + 8A43FC43A5F5F2869F78909D /* FirebasePerformance.xcframework */, + 144AF202560DF7170CA1B88E /* FirebaseRemoteConfig.xcframework */, + B3034A14E3F41394DEB55A62 /* GoogleAppMeasurement.xcframework */, + AE841A10BB74D787FB068BD6 /* GoogleDataTransport.xcframework */, + 39F4CD1686D945CFB87141CE /* GoogleUtilities.xcframework */, + E8C25BE3139AF9A212CCC8F0 /* gRPC-C++.xcframework */, + F6868AB01C3AABA6F00D83C8 /* gRPC-Core.xcframework */, + 18C42AC12CA0DA009E4241B5 /* leveldb-library.xcframework */, + 8F94607B0325642C330CD793 /* nanopb.xcframework */, + B121E1EC2442F244D11C5380 /* PromisesObjC.xcframework */, + 33B49E10FB3AFB3745B0AEF4 /* SwiftUI.framework */, + 3678749154206AA2C7DE69F6 /* WidgetKit.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 781042549E5A01519EFED671 /* Shared */ = { + isa = PBXGroup; + children = ( + 792E8ECF278C4299000F3902 /* IntentDefinition */, + C2B92E538C189F4941F7DAFE /* Resources */, + ); + path = Shared; + sourceTree = ""; + }; + 792E8ECF278C4299000F3902 /* IntentDefinition */ = { + isa = PBXGroup; + children = ( + 792E8ED5278C4299000F3902 /* MonsterIntentObject+Convert.swift */, + 792E8ED3278C4299000F3902 /* WidgetsConfiguration.intentdefinition */, + ); + name = IntentDefinition; + path = Shared/IntentDefinition; + sourceTree = SOURCE_ROOT; + }; + 792E8F0B278C445E000F3902 /* UhooiPicBook */ = { + isa = PBXGroup; + children = ( + 792E8F18278C445E000F3902 /* AppDelegate.swift */, + 792E8F19278C445E000F3902 /* SceneDelegate.swift */, + 792E8F0D278C445E000F3902 /* Resources */, + ); + path = UhooiPicBook; + sourceTree = ""; + }; + 792E8F0D278C445E000F3902 /* Resources */ = { + isa = PBXGroup; + children = ( + 792E8F99278C6901000F3902 /* Assets.xcassets */, + 792E8F17278C445E000F3902 /* Info.plist */, + 792E8F0E278C445E000F3902 /* InfoPlist.strings */, + 792E8F15278C445E000F3902 /* LaunchScreen.storyboard */, + 792E8FD8278C7ABC000F3902 /* Settings.bundle */, + 792E8F13278C445E000F3902 /* UhooiPicBook.entitlements */, + ); + path = Resources; + sourceTree = ""; + }; + 792E8F52278C4C22000F3902 /* UhooiPicBookStickers */ = { + isa = PBXGroup; + children = ( + 792E8F54278C4C22000F3902 /* Info.plist */, + 792E8F53278C4C22000F3902 /* Stickers.xcassets */, + ); + path = UhooiPicBookStickers; + sourceTree = ""; + }; + 792E8F7F278C6465000F3902 /* UhooiPicBookWidgets */ = { + isa = PBXGroup; + children = ( + 792E8F80278C6465000F3902 /* Info.plist */, + 792E8F83278C6465000F3902 /* UhooiPicBookWidgets.swift */, + 792E8F81278C6465000F3902 /* Monster */, + ); + path = UhooiPicBookWidgets; + sourceTree = ""; + }; + 792E8F81278C6465000F3902 /* Monster */ = { + isa = PBXGroup; + children = ( + 792E8F82278C6465000F3902 /* MonsterConfigurableWidget.swift */, + ); + path = Monster; + sourceTree = ""; + }; + 792E8F8F278C675C000F3902 /* UhooiPicBookWidgetsConfigurableIntent */ = { + isa = PBXGroup; + children = ( + 792E8F91278C675C000F3902 /* Info.plist */, + 792E8F90278C675C000F3902 /* IntentHandler.swift */, + ); + path = UhooiPicBookWidgetsConfigurableIntent; + sourceTree = ""; + }; + 9D14FEE7DAB67CCFD61B333D /* TestCases */ = { + isa = PBXGroup; + children = ( + F77956692405C61E8D8C04B5 /* UhooiPicBookUITests.swift */, + ); + path = TestCases; + sourceTree = ""; + }; + 9E07DDF4AF7D2B2926033FDC /* Extensions */ = { + isa = PBXGroup; + children = ( + 17E82F135C45DA22DAD85E72 /* Foundation */, + ); + path = Extensions; + sourceTree = ""; + }; + B9F854ED00B8603447D5057B /* Products */ = { + isa = PBXGroup; + children = ( + E4EA4C797239C728014E8BCC /* UhooiPicBook.app */, + D97430DE3B018D83FA30BA3F /* UhooiPicBookStickers.appex */, + BA21C3023C46CC6151A43886 /* UhooiPicBookTests.xctest */, + 83C280827AC1AC8CDC771EC4 /* UhooiPicBookUITests.xctest */, + AE659249AE186390141063EE /* UhooiPicBookWidgets.appex */, + D3A28FF132F9DB6448EAC23F /* UhooiPicBookWidgetsConfigurableIntent.appex */, + ); + name = Products; + sourceTree = ""; + }; + BAB84381A6737A2083BC961F /* UhooiPicBookTests */ = { + isa = PBXGroup; + children = ( + 988A97043A06E226C6868588 /* Info.plist */, + 9E07DDF4AF7D2B2926033FDC /* Extensions */, + ); + path = UhooiPicBookTests; + sourceTree = ""; + }; + C2B92E538C189F4941F7DAFE /* Resources */ = { + isa = PBXGroup; + children = ( + 792E8F9D278C6A3C000F3902 /* GoogleService-Info.plist */, + ); + path = Resources; + sourceTree = ""; + }; + EB1BD4D1C82D8077591B0698 /* UhooiPicBookUITests */ = { + isa = PBXGroup; + children = ( + E486EDFB4B99417855E33115 /* Info.plist */, + 8B1D686A013EAD76B19604C9 /* PageProtocol.swift */, + 541427EC2F900D49CD247CB2 /* XCUIElement+Ex.swift */, + EB9FF08BDED117C228729B0B /* Pages */, + 9D14FEE7DAB67CCFD61B333D /* TestCases */, + ); + path = UhooiPicBookUITests; + sourceTree = ""; + }; + EB9FF08BDED117C228729B0B /* Pages */ = { + isa = PBXGroup; + children = ( + D1BC591FA4C18A058784472F /* ActivityPage.swift */, + 7C5239C3163F47164ECE33E8 /* ImagePopupPage.swift */, + 1B117974B5DFAEB1BA1DB35C /* MonsterDetailPage.swift */, + B21F0F147EB90FE7EAF86DB2 /* MonsterListPage.swift */, + ); + path = Pages; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 0E1AD029696068D4B516B255 /* UhooiPicBookStickers */ = { + isa = PBXNativeTarget; + buildConfigurationList = 3E50B2D32EEA9C3FA89AE8F6 /* Build configuration list for PBXNativeTarget "UhooiPicBookStickers" */; + buildPhases = ( + D3F1C1F751AC3C59ADE107DA /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = UhooiPicBookStickers; + productName = UhooiPicBookStickers; + productReference = D97430DE3B018D83FA30BA3F /* UhooiPicBookStickers.appex */; + productType = "com.apple.product-type.app-extension.messages-sticker-pack"; + }; + 162395B56ED57E8800847617 /* UhooiPicBookWidgets */ = { + isa = PBXNativeTarget; + buildConfigurationList = BF5510DB2613969D49C12435 /* Build configuration list for PBXNativeTarget "UhooiPicBookWidgets" */; + buildPhases = ( + B1556D34667F4525E961FE38 /* Sources */, + 895AFD8905206AF423271193 /* Resources */, + F7D826D061CE893E40DE10DA /* Frameworks */, + ED5C992B9082C440532A022E /* Run Firebase Crashlytics */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = UhooiPicBookWidgets; + packageProductDependencies = ( + 79C193A82789CF1D00E7A58E /* MonsterWidgets */, + 791904C92793F9CB00416F7D /* ImageLoader */, + 791904CD2794082700416F7D /* MonstersRepository */, + ); + productName = UhooiPicBookWidgets; + productReference = AE659249AE186390141063EE /* UhooiPicBookWidgets.appex */; + productType = "com.apple.product-type.app-extension"; + }; + 4677FBF8E3C5D8691051D106 /* UhooiPicBookTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1FF40AA4CFE5087652123EAD /* Build configuration list for PBXNativeTarget "UhooiPicBookTests" */; + buildPhases = ( + 4FE41A7B35B5E5FAA407F3FA /* Sources */, + ); + buildRules = ( + ); + dependencies = ( + 4DAF6BC74EE9AEF3E06A50D2 /* PBXTargetDependency */, + ); + name = UhooiPicBookTests; + productName = UhooiPicBookTests; + productReference = BA21C3023C46CC6151A43886 /* UhooiPicBookTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + AD5F2C9896C8C0CAC68E089A /* UhooiPicBookUITests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 5336812240FABFFCD289F94B /* Build configuration list for PBXNativeTarget "UhooiPicBookUITests" */; + buildPhases = ( + 22070DEEFB8F99971EC40231 /* Sources */, + ); + buildRules = ( + ); + dependencies = ( + BB72275143FEBC036B69BC5C /* PBXTargetDependency */, + ); + name = UhooiPicBookUITests; + productName = UhooiPicBookUITests; + productReference = 83C280827AC1AC8CDC771EC4 /* UhooiPicBookUITests.xctest */; + productType = "com.apple.product-type.bundle.ui-testing"; + }; + C2DB76B6BCC6E8EF34FA57BF /* UhooiPicBookWidgetsConfigurableIntent */ = { + isa = PBXNativeTarget; + buildConfigurationList = 0BE8F8DC9871C9E99D77E15E /* Build configuration list for PBXNativeTarget "UhooiPicBookWidgetsConfigurableIntent" */; + buildPhases = ( + 4B799ED34E78C3F6214D145F /* Sources */, + 14414248979752991022B441 /* Resources */, + 7807E38B57A7E4DC3FAF7927 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = UhooiPicBookWidgetsConfigurableIntent; + packageProductDependencies = ( + 7921EEFE2785E63E0033DDEC /* FirebaseSetup */, + 791904CF2794083500416F7D /* MonstersRepository */, + ); + productName = UhooiPicBookWidgetsConfigurableIntent; + productReference = D3A28FF132F9DB6448EAC23F /* UhooiPicBookWidgetsConfigurableIntent.appex */; + productType = "com.apple.product-type.app-extension"; + }; + F7174334A4963303CCEE4E61 /* UhooiPicBook */ = { + isa = PBXNativeTarget; + buildConfigurationList = 13C9DF26DB51CA2F181109A7 /* Build configuration list for PBXNativeTarget "UhooiPicBook" */; + buildPhases = ( + 1536BFDD1A0F36A88A1E7765 /* Sources */, + 3E2EB7F4463B4E5B0378F12C /* Run SwiftLint */, + 273E5548C378B1635B235E18 /* Run IBLinter */, + 0FA2530C0E3D86880E87A1B6 /* Run SpellChecker */, + 37FBDE35DD42D3CF137E6A2B /* Resources */, + 6986B5ACA2E569F81163AE24 /* Frameworks */, + 4224260094675C4E9D31B589 /* Embed Foundation Extensions */, + CE0A4BD6818C7BDE485094F6 /* Run Firebase Crashlytics */, + ); + buildRules = ( + ); + dependencies = ( + 51B7EA9FEB54D0504D29FD8D /* PBXTargetDependency */, + EC6680A6178CDFC223187F43 /* PBXTargetDependency */, + CFF8820FAA1030EA6191F5CE /* PBXTargetDependency */, + ); + name = UhooiPicBook; + packageProductDependencies = ( + 7921EEFC2785E6370033DDEC /* FirebaseSetup */, + 7995BD2D2786F35200B553DC /* FirebaseMessagingBridge */, + 797ABFA6278A9B59005B445B /* AppModule */, + ); + productName = UhooiPicBook; + productReference = E4EA4C797239C728014E8BCC /* UhooiPicBook.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 8F21FB9F02C54BE4076B12F8 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1400; + TargetAttributes = { + 0E1AD029696068D4B516B255 = { + DevelopmentTeam = 47E56DYP3N; + ProvisioningStyle = Automatic; + }; + 162395B56ED57E8800847617 = { + DevelopmentTeam = 47E56DYP3N; + ProvisioningStyle = Automatic; + }; + 4677FBF8E3C5D8691051D106 = { + DevelopmentTeam = 47E56DYP3N; + TestTargetID = F7174334A4963303CCEE4E61; + }; + AD5F2C9896C8C0CAC68E089A = { + DevelopmentTeam = 47E56DYP3N; + TestTargetID = F7174334A4963303CCEE4E61; + }; + C2DB76B6BCC6E8EF34FA57BF = { + DevelopmentTeam = 47E56DYP3N; + ProvisioningStyle = Automatic; + }; + F7174334A4963303CCEE4E61 = { + DevelopmentTeam = 47E56DYP3N; + }; + }; + }; + buildConfigurationList = 09429085F8A0F9BD0D9F66E1 /* Build configuration list for PBXProject "Develop" */; + compatibilityVersion = "Xcode 10.0"; + developmentRegion = ja; + hasScannedForEncodings = 0; + knownRegions = ( + Base, + en, + ja, + ); + mainGroup = 47C552D3546C641AB89783C1; + packageReferences = ( + ); + projectDirPath = ""; + projectRoot = ""; + targets = ( + F7174334A4963303CCEE4E61 /* UhooiPicBook */, + 0E1AD029696068D4B516B255 /* UhooiPicBookStickers */, + 4677FBF8E3C5D8691051D106 /* UhooiPicBookTests */, + AD5F2C9896C8C0CAC68E089A /* UhooiPicBookUITests */, + 162395B56ED57E8800847617 /* UhooiPicBookWidgets */, + C2DB76B6BCC6E8EF34FA57BF /* UhooiPicBookWidgetsConfigurableIntent */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 14414248979752991022B441 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 792E8FA0278C6A3C000F3902 /* GoogleService-Info.plist in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 37FBDE35DD42D3CF137E6A2B /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 792E8F1B278C445E000F3902 /* InfoPlist.strings in Resources */, + 792E8F9E278C6A3C000F3902 /* GoogleService-Info.plist in Resources */, + 792E8FD9278C7ABC000F3902 /* Settings.bundle in Resources */, + 792E8F1E278C445E000F3902 /* LaunchScreen.storyboard in Resources */, + 792E8F9A278C6901000F3902 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 895AFD8905206AF423271193 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 792E8F9F278C6A3C000F3902 /* GoogleService-Info.plist in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D3F1C1F751AC3C59ADE107DA /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 792E8F55278C4C22000F3902 /* Stickers.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 0FA2530C0E3D86880E87A1B6 /* Run SpellChecker */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = "Run SpellChecker"; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "#git_path=/usr/local/bin/git\n#files=$($git_path diff --diff-filter=d --name-only -- \"*.swift\" \"*.h\" \"*.m\")\n#if (test -z $files) || (test ${#files[@]} -eq 0); then\n# echo \"no files changed.\"\n# exit 0\n#fi\n#\n#options=\"\"\n#for file in $files\n#do\n# options=\"$options $SRCROOT/../$file\"\n#done\n#\n#SDKROOT=$(xcrun --sdk macosx --show-sdk-path)\n#SPELLCHECKER_PATH=$SRCROOT/../Tools/UhooiPicBookTools/.build/release/SpellChecker\n#if [ -f $SPELLCHECKER_PATH ]; then\n# $SPELLCHECKER_PATH --yml $SRCROOT/../.spell-checker.yml -- $options\n#else\n# echo \"warning: SpellChecker not installed, please run \\`make setup\\` .\"\n#fi\n\n"; + }; + 273E5548C378B1635B235E18 /* Run IBLinter */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = "Run IBLinter"; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "#SDKROOT=$(xcrun --sdk macosx --show-sdk-path)\n#IBLINTER_PATH=$SRCROOT/../Tools/UhooiPicBookTools/.build/release/iblinter\n#if [ -f $IBLINTER_PATH ]; then\n# $IBLINTER_PATH lint --path $SRCROOT/.. --config $SRCROOT/../.iblinter.yml\n#else\n# echo \"warning: IBLinter not installed, please run \\`make setup\\` .\"\n#fi\n\n"; + }; + 3E2EB7F4463B4E5B0378F12C /* Run SwiftLint */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = "Run SwiftLint"; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "SDKROOT=$(xcrun --sdk macosx --show-sdk-path)\nSWIFTLINT_PATH=$SRCROOT/../Tools/UhooiPicBookTools/.build/release/swiftlint\nif [ -f $SWIFTLINT_PATH ]; then\n $SWIFTLINT_PATH --config $SRCROOT/../.swiftlint.yml --fix --format\n $SWIFTLINT_PATH --config $SRCROOT/../.swiftlint.yml\nelse\n echo \"warning: SwiftLint not installed, please run \\`make setup\\` .\"\nfi\n\n"; + }; + CE0A4BD6818C7BDE485094F6 /* Run Firebase Crashlytics */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "$(SRCROOT)/$(BUILT_PRODUCTS_DIR)/$(INFOPLIST_PATH)", + ); + name = "Run Firebase Crashlytics"; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "$SRCROOT/../Frameworks/Firebase/FirebaseCrashlytics/run\n"; + }; + ED5C992B9082C440532A022E /* Run Firebase Crashlytics */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "$(SRCROOT)/$(BUILT_PRODUCTS_DIR)/$(INFOPLIST_PATH)", + ); + name = "Run Firebase Crashlytics"; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "../Frameworks/Firebase/FirebaseCrashlytics/run\n"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1536BFDD1A0F36A88A1E7765 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 792E8F20278C445E000F3902 /* AppDelegate.swift in Sources */, + 792E8ED9278C4299000F3902 /* WidgetsConfiguration.intentdefinition in Sources */, + 792E8EDC278C4299000F3902 /* MonsterIntentObject+Convert.swift in Sources */, + 792E8F21278C445E000F3902 /* SceneDelegate.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 22070DEEFB8F99971EC40231 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 478286982E492B33E65E682B /* ActivityPage.swift in Sources */, + 3ED6158022DE90CA4AA73905 /* ImagePopupPage.swift in Sources */, + 7B7002A645C43EBB624D82D8 /* MonsterDetailPage.swift in Sources */, + 522896F9FC51ED2221060387 /* MonsterListPage.swift in Sources */, + ED23EF346F55E2E02F461F16 /* PageProtocol.swift in Sources */, + 2AB9187FB6C6F195BDFA0AEA /* UhooiPicBookUITests.swift in Sources */, + A1713DA74A4AE73B34351622 /* XCUIElement+Ex.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4B799ED34E78C3F6214D145F /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 792E8EDE278C4299000F3902 /* MonsterIntentObject+Convert.swift in Sources */, + 792E8F92278C675C000F3902 /* IntentHandler.swift in Sources */, + 792E8EDB278C4299000F3902 /* WidgetsConfiguration.intentdefinition in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4FE41A7B35B5E5FAA407F3FA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A6BE80E8825B6DA6ACE56D06 /* BundleStringTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B1556D34667F4525E961FE38 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 792E8F85278C6465000F3902 /* MonsterConfigurableWidget.swift in Sources */, + 792E8EDA278C4299000F3902 /* WidgetsConfiguration.intentdefinition in Sources */, + 792E8F86278C6465000F3902 /* UhooiPicBookWidgets.swift in Sources */, + 792E8EDD278C4299000F3902 /* MonsterIntentObject+Convert.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 4DAF6BC74EE9AEF3E06A50D2 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = F7174334A4963303CCEE4E61 /* UhooiPicBook */; + targetProxy = 46DB71745F7E01A515C0F13C /* PBXContainerItemProxy */; + }; + 51B7EA9FEB54D0504D29FD8D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 0E1AD029696068D4B516B255 /* UhooiPicBookStickers */; + targetProxy = F97CF2FC9CF60F60A337F2AA /* PBXContainerItemProxy */; + }; + BB72275143FEBC036B69BC5C /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = F7174334A4963303CCEE4E61 /* UhooiPicBook */; + targetProxy = 73857B2E0E8A6F194DF299E9 /* PBXContainerItemProxy */; + }; + CFF8820FAA1030EA6191F5CE /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = C2DB76B6BCC6E8EF34FA57BF /* UhooiPicBookWidgetsConfigurableIntent */; + targetProxy = 8DABA011EEC5DA70896A6C44 /* PBXContainerItemProxy */; + }; + EC6680A6178CDFC223187F43 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 162395B56ED57E8800847617 /* UhooiPicBookWidgets */; + targetProxy = EA1D5D72FB9D70100338E4A8 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 792E8ED3278C4299000F3902 /* WidgetsConfiguration.intentdefinition */ = { + isa = PBXVariantGroup; + children = ( + 792E8ED4278C4299000F3902 /* Base */, + 792E8EDF278C42BD000F3902 /* ja */, + 792E8EE0278C42C1000F3902 /* en */, + ); + name = WidgetsConfiguration.intentdefinition; + sourceTree = ""; + }; + 792E8F0E278C445E000F3902 /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + 792E8F0F278C445E000F3902 /* ja */, + 792E8F12278C445E000F3902 /* en */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; + 792E8F15278C445E000F3902 /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 792E8F16278C445E000F3902 /* Base */, + 792E8F22278C4489000F3902 /* en */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 09D4296D6247B3DC0D1D51D7 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + INFOPLIST_FILE = UhooiPicBookUITests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.theuhooi.UhooiPicBookUITests; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_TARGET_NAME = UhooiPicBook; + }; + name = Release; + }; + 0ED5B166D8E6F0C77AD417DD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + INFOPLIST_FILE = UhooiPicBookTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.theuhooi.UhooiPicBookTests; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/UhooiPicBook.app/UhooiPicBook"; + }; + name = Debug; + }; + 1F66094B9A6482DB9583F607 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = "$(SRCROOT)/UhooiPicBookWidgets/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + OTHER_LDFLAGS = ( + "$(inherited)", + "$(OTHER_LDFLAGS)", + "-ObjC", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.theuhooi.UhooiPicBook-Develop.Widgets"; + PRODUCT_NAME = UhooiPicBookWidgets; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 2B6E9D86BE7350731825FA24 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = "$(SRCROOT)/UhooiPicBookWidgetsConfigurableIntent/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + OTHER_LDFLAGS = ( + "$(inherited)", + "$(OTHER_LDFLAGS)", + "-ObjC", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.theuhooi.UhooiPicBook-Develop.WidgetsConfigurableIntent"; + PRODUCT_NAME = UhooiPicBookWidgetsConfigurableIntent; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + 47074D1AA8DC853C8208EE3C /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = "iMessage App Icon"; + CLANG_ENABLE_OBJC_WEAK = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = "$(SRCROOT)/UhooiPicBookStickers/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + LD_RUNPATH_SEARCH_PATHS = ""; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = "com.theuhooi.UhooiPicBook-Develop.Stickers"; + PRODUCT_NAME = UhooiPicBookStickers; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 526474C0707A0615CE591087 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = "$(SRCROOT)/UhooiPicBookWidgets/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + OTHER_LDFLAGS = ( + "$(inherited)", + "$(OTHER_LDFLAGS)", + "-ObjC", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.theuhooi.UhooiPicBook-Develop.Widgets"; + PRODUCT_NAME = UhooiPicBookWidgets; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + 637D639F1590AE62D4CC5F5B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + INFOPLIST_FILE = UhooiPicBookUITests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.theuhooi.UhooiPicBookUITests; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_TARGET_NAME = UhooiPicBook; + }; + name = Debug; + }; + 6F3C0123B6BDA1D471303B9B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 17; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = 47E56DYP3N; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + MARKETING_VERSION = 1.6.0; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + OTHER_LDFLAGS = ( + "$(inherited)", + "$(OTHER_LDFLAGS)", + "-ObjC", + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; + 78CA1F5826002F4089502798 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = "iMessage App Icon"; + CLANG_ENABLE_OBJC_WEAK = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = "$(SRCROOT)/UhooiPicBookStickers/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + LD_RUNPATH_SEARCH_PATHS = ""; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = "com.theuhooi.UhooiPicBook-Develop.Stickers"; + PRODUCT_NAME = UhooiPicBookStickers; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + 7957E27092FF80EC435C94B8 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 17; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = 47E56DYP3N; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "DEBUG=1", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + MARKETING_VERSION = 1.6.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + OTHER_LDFLAGS = ( + "$(inherited)", + "$(OTHER_LDFLAGS)", + "-ObjC", + ); + OTHER_SWIFT_FLAGS = "$(inherited) -Xfrontend -warn-long-expression-type-checking=500 -Xfrontend -warn-long-function-bodies=500 -Xfrontend -warn-concurrency -Xfrontend -enable-actor-data-race-checks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 7C503DF97828E781A59C4ECF /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_ENTITLEMENTS = ""; + CODE_SIGN_IDENTITY = "iPhone Developer"; + DEVELOPMENT_LANGUAGE = jp; + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; + INFOPLIST_FILE = "$(SRCROOT)/UhooiPicBook/Resources/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.theuhooi.UhooiPicBook-Develop"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + A7401616F8B6C53FFDF54AD5 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_ENTITLEMENTS = ""; + CODE_SIGN_IDENTITY = "iPhone Developer"; + DEVELOPMENT_LANGUAGE = jp; + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; + INFOPLIST_FILE = "$(SRCROOT)/UhooiPicBook/Resources/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.theuhooi.UhooiPicBook-Develop"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + C95A34D40744F3B1A485A39D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + INFOPLIST_FILE = UhooiPicBookTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.theuhooi.UhooiPicBookTests; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/UhooiPicBook.app/UhooiPicBook"; + }; + name = Release; + }; + CE81301A562141C55A4EA86A /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = "$(SRCROOT)/UhooiPicBookWidgetsConfigurableIntent/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + OTHER_LDFLAGS = ( + "$(inherited)", + "$(OTHER_LDFLAGS)", + "-ObjC", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.theuhooi.UhooiPicBook-Develop.WidgetsConfigurableIntent"; + PRODUCT_NAME = UhooiPicBookWidgetsConfigurableIntent; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 09429085F8A0F9BD0D9F66E1 /* Build configuration list for PBXProject "Develop" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7957E27092FF80EC435C94B8 /* Debug */, + 6F3C0123B6BDA1D471303B9B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + 0BE8F8DC9871C9E99D77E15E /* Build configuration list for PBXNativeTarget "UhooiPicBookWidgetsConfigurableIntent" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + CE81301A562141C55A4EA86A /* Debug */, + 2B6E9D86BE7350731825FA24 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + 13C9DF26DB51CA2F181109A7 /* Build configuration list for PBXNativeTarget "UhooiPicBook" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7C503DF97828E781A59C4ECF /* Debug */, + A7401616F8B6C53FFDF54AD5 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + 1FF40AA4CFE5087652123EAD /* Build configuration list for PBXNativeTarget "UhooiPicBookTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0ED5B166D8E6F0C77AD417DD /* Debug */, + C95A34D40744F3B1A485A39D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + 3E50B2D32EEA9C3FA89AE8F6 /* Build configuration list for PBXNativeTarget "UhooiPicBookStickers" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 47074D1AA8DC853C8208EE3C /* Debug */, + 78CA1F5826002F4089502798 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + 5336812240FABFFCD289F94B /* Build configuration list for PBXNativeTarget "UhooiPicBookUITests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 637D639F1590AE62D4CC5F5B /* Debug */, + 09D4296D6247B3DC0D1D51D7 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + BF5510DB2613969D49C12435 /* Build configuration list for PBXNativeTarget "UhooiPicBookWidgets" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1F66094B9A6482DB9583F607 /* Debug */, + 526474C0707A0615CE591087 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; +/* End XCConfigurationList section */ + +/* Begin XCSwiftPackageProductDependency section */ + 791904C92793F9CB00416F7D /* ImageLoader */ = { + isa = XCSwiftPackageProductDependency; + productName = ImageLoader; + }; + 791904CD2794082700416F7D /* MonstersRepository */ = { + isa = XCSwiftPackageProductDependency; + productName = MonstersRepository; + }; + 791904CF2794083500416F7D /* MonstersRepository */ = { + isa = XCSwiftPackageProductDependency; + productName = MonstersRepository; + }; + 7921EEFC2785E6370033DDEC /* FirebaseSetup */ = { + isa = XCSwiftPackageProductDependency; + productName = FirebaseSetup; + }; + 7921EEFE2785E63E0033DDEC /* FirebaseSetup */ = { + isa = XCSwiftPackageProductDependency; + productName = FirebaseSetup; + }; + 797ABFA6278A9B59005B445B /* AppModule */ = { + isa = XCSwiftPackageProductDependency; + productName = AppModule; + }; + 7995BD2D2786F35200B553DC /* FirebaseMessagingBridge */ = { + isa = XCSwiftPackageProductDependency; + productName = FirebaseMessagingBridge; + }; + 79C193A82789CF1D00E7A58E /* MonsterWidgets */ = { + isa = XCSwiftPackageProductDependency; + productName = MonsterWidgets; + }; +/* End XCSwiftPackageProductDependency section */ + }; + rootObject = 8F21FB9F02C54BE4076B12F8 /* Project object */; +} diff --git a/App/Develop.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/App/Develop.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..919434a6 --- /dev/null +++ b/App/Develop.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/App/Develop.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/App/Develop.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/App/Develop.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/App/Develop.xcodeproj/xcshareddata/xcschemes/UhooiPicBook.xcscheme b/App/Develop.xcodeproj/xcshareddata/xcschemes/UhooiPicBook.xcscheme new file mode 100644 index 00000000..f4c8332e --- /dev/null +++ b/App/Develop.xcodeproj/xcshareddata/xcschemes/UhooiPicBook.xcscheme @@ -0,0 +1,147 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/App/Develop.xcodeproj/xcshareddata/xcschemes/UhooiPicBookStickers.xcscheme b/App/Develop.xcodeproj/xcshareddata/xcschemes/UhooiPicBookStickers.xcscheme new file mode 100644 index 00000000..7f14de3e --- /dev/null +++ b/App/Develop.xcodeproj/xcshareddata/xcschemes/UhooiPicBookStickers.xcscheme @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/App/Develop.xcodeproj/xcshareddata/xcschemes/UhooiPicBookWidgets.xcscheme b/App/Develop.xcodeproj/xcshareddata/xcschemes/UhooiPicBookWidgets.xcscheme new file mode 100644 index 00000000..28b8261f --- /dev/null +++ b/App/Develop.xcodeproj/xcshareddata/xcschemes/UhooiPicBookWidgets.xcscheme @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/App/Develop.xcodeproj/xcshareddata/xcschemes/UhooiPicBookWidgetsConfigurableIntent.xcscheme b/App/Develop.xcodeproj/xcshareddata/xcschemes/UhooiPicBookWidgetsConfigurableIntent.xcscheme new file mode 100644 index 00000000..3ca5caca --- /dev/null +++ b/App/Develop.xcodeproj/xcshareddata/xcschemes/UhooiPicBookWidgetsConfigurableIntent.xcscheme @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/App/Develop.xctestplan b/App/Develop.xctestplan new file mode 100644 index 00000000..d42c84b7 --- /dev/null +++ b/App/Develop.xctestplan @@ -0,0 +1,65 @@ +{ + "configurations" : [ + { + "id" : "7B68A168-81D0-4EE9-BA66-24D2FAD70C02", + "name" : "English", + "options" : { + "language" : "en", + "locationScenario" : { + "identifier" : "New York, NY, USA", + "referenceType" : "built-in" + }, + "region" : "US" + } + }, + { + "id" : "5051C0FC-3449-46DE-81DB-96132ADFFC25", + "name" : "Japanese", + "options" : { + "language" : "ja", + "locationScenario" : { + "identifier" : "Tokyo, Japan", + "referenceType" : "built-in" + }, + "region" : "JP" + } + } + ], + "defaultOptions" : { + "codeCoverage" : { + "targets" : [ + { + "containerPath" : "container:..", + "identifier" : "AppModule", + "name" : "AppModule" + } + ] + }, + "defaultTestExecutionTimeAllowance" : 60, + "targetForVariableExpansion" : { + "containerPath" : "container:Develop.xcodeproj", + "identifier" : "F7174334A4963303CCEE4E61", + "name" : "UhooiPicBook" + }, + "testTimeoutsEnabled" : true + }, + "testTargets" : [ + { + "parallelizable" : true, + "target" : { + "containerPath" : "container:Develop.xcodeproj", + "identifier" : "4677FBF8E3C5D8691051D106", + "name" : "UhooiPicBookTests" + } + }, + { + "parallelizable" : true, + "target" : { + "containerPath" : "container:Develop.xcodeproj", + "identifier" : "AD5F2C9896C8C0CAC68E089A", + "name" : "UhooiPicBookUITests" + } + } + ], + "version" : 1 +} diff --git a/App/Package.swift b/App/Package.swift new file mode 100644 index 00000000..0d5aaddc --- /dev/null +++ b/App/Package.swift @@ -0,0 +1,11 @@ +// swift-tools-version:5.5 + +// Leave blank. This is only here so that Xcode doesn't display it. + +import PackageDescription + +let package = Package( + name: "Client", + products: [], + targets: [] +) diff --git a/App/Production.xcodeproj/project.pbxproj b/App/Production.xcodeproj/project.pbxproj new file mode 100644 index 00000000..1b100dd2 --- /dev/null +++ b/App/Production.xcodeproj/project.pbxproj @@ -0,0 +1,1380 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXBuildFile section */ + 2AB9187FB6C6F195BDFA0AEA /* UhooiPicBookUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F77956692405C61E8D8C04B5 /* UhooiPicBookUITests.swift */; }; + 3784E43C6F9862BB2E871B15 /* UhooiPicBookWidgetsConfigurableIntent.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = D3A28FF132F9DB6448EAC23F /* UhooiPicBookWidgetsConfigurableIntent.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + 3ED6158022DE90CA4AA73905 /* ImagePopupPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C5239C3163F47164ECE33E8 /* ImagePopupPage.swift */; }; + 478286982E492B33E65E682B /* ActivityPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1BC591FA4C18A058784472F /* ActivityPage.swift */; }; + 5022F0F1F72B5341C9486B7A /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 33B49E10FB3AFB3745B0AEF4 /* SwiftUI.framework */; }; + 522896F9FC51ED2221060387 /* MonsterListPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = B21F0F147EB90FE7EAF86DB2 /* MonsterListPage.swift */; }; + 745EB4E9574D57EB307F2AB9 /* UhooiPicBookStickers.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = D97430DE3B018D83FA30BA3F /* UhooiPicBookStickers.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + 791904CC2793F9DA00416F7D /* ImageLoader in Frameworks */ = {isa = PBXBuildFile; productRef = 791904CB2793F9DA00416F7D /* ImageLoader */; }; + 791904D22794084800416F7D /* MonstersRepository in Frameworks */ = {isa = PBXBuildFile; productRef = 791904D12794084800416F7D /* MonstersRepository */; }; + 791904D42794085600416F7D /* MonstersRepository in Frameworks */ = {isa = PBXBuildFile; productRef = 791904D32794085600416F7D /* MonstersRepository */; }; + 7921EEF92785E5E40033DDEC /* FirebaseSetup in Frameworks */ = {isa = PBXBuildFile; productRef = 7921EEF82785E5E40033DDEC /* FirebaseSetup */; }; + 7921EEFB2785E6290033DDEC /* FirebaseSetup in Frameworks */ = {isa = PBXBuildFile; productRef = 7921EEFA2785E6290033DDEC /* FirebaseSetup */; }; + 792E8EEB278C430A000F3902 /* WidgetsConfiguration.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = 792E8EE5278C430A000F3902 /* WidgetsConfiguration.intentdefinition */; }; + 792E8EEC278C430A000F3902 /* WidgetsConfiguration.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = 792E8EE5278C430A000F3902 /* WidgetsConfiguration.intentdefinition */; }; + 792E8EED278C430A000F3902 /* WidgetsConfiguration.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = 792E8EE5278C430A000F3902 /* WidgetsConfiguration.intentdefinition */; }; + 792E8EEE278C430A000F3902 /* MonsterIntentObject+Convert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 792E8EE7278C430A000F3902 /* MonsterIntentObject+Convert.swift */; }; + 792E8EEF278C430A000F3902 /* MonsterIntentObject+Convert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 792E8EE7278C430A000F3902 /* MonsterIntentObject+Convert.swift */; }; + 792E8EF0278C430A000F3902 /* MonsterIntentObject+Convert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 792E8EE7278C430A000F3902 /* MonsterIntentObject+Convert.swift */; }; + 792E8F4A278C4B2D000F3902 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 792E8F3D278C4B2D000F3902 /* InfoPlist.strings */; }; + 792E8F4D278C4B2D000F3902 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 792E8F44278C4B2D000F3902 /* LaunchScreen.storyboard */; }; + 792E8F4F278C4B2D000F3902 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 792E8F47278C4B2D000F3902 /* AppDelegate.swift */; }; + 792E8F50278C4B2D000F3902 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 792E8F48278C4B2D000F3902 /* SceneDelegate.swift */; }; + 792E8F5A278C4C8E000F3902 /* Stickers.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 792E8F58278C4C8E000F3902 /* Stickers.xcassets */; }; + 792E8F8D278C6532000F3902 /* MonsterConfigurableWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 792E8F8A278C6532000F3902 /* MonsterConfigurableWidget.swift */; }; + 792E8F8E278C6532000F3902 /* UhooiPicBookWidgets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 792E8F8B278C6532000F3902 /* UhooiPicBookWidgets.swift */; }; + 792E8F97278C67F1000F3902 /* IntentHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 792E8F95278C67F1000F3902 /* IntentHandler.swift */; }; + 792E8F9C278C6933000F3902 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 792E8F9B278C6933000F3902 /* Assets.xcassets */; }; + 792E8FA2278C6A56000F3902 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 792E8FA1278C6A56000F3902 /* GoogleService-Info.plist */; }; + 792E8FA3278C6A56000F3902 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 792E8FA1278C6A56000F3902 /* GoogleService-Info.plist */; }; + 792E8FA4278C6A56000F3902 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 792E8FA1278C6A56000F3902 /* GoogleService-Info.plist */; }; + 792E8FDB278C7B6F000F3902 /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 792E8FDA278C7B6F000F3902 /* Settings.bundle */; }; + 797ABFA9278A9BA5005B445B /* AppModule in Frameworks */ = {isa = PBXBuildFile; productRef = 797ABFA8278A9BA5005B445B /* AppModule */; }; + 7995BD302786F36A00B553DC /* FirebaseMessagingBridge in Frameworks */ = {isa = PBXBuildFile; productRef = 7995BD2F2786F36A00B553DC /* FirebaseMessagingBridge */; }; + 79C193AB2789CF5200E7A58E /* MonsterWidgets in Frameworks */ = {isa = PBXBuildFile; productRef = 79C193AA2789CF5200E7A58E /* MonsterWidgets */; }; + 7B7002A645C43EBB624D82D8 /* MonsterDetailPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B117974B5DFAEB1BA1DB35C /* MonsterDetailPage.swift */; }; + A1713DA74A4AE73B34351622 /* XCUIElement+Ex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 541427EC2F900D49CD247CB2 /* XCUIElement+Ex.swift */; }; + A6BE80E8825B6DA6ACE56D06 /* BundleStringTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4618659C63EB6D450468854 /* BundleStringTests.swift */; }; + ED23EF346F55E2E02F461F16 /* PageProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B1D686A013EAD76B19604C9 /* PageProtocol.swift */; }; + F84FC678215D503C49D26C58 /* UhooiPicBookWidgets.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = AE659249AE186390141063EE /* UhooiPicBookWidgets.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + F8BBF148F1591E57471509B2 /* WidgetKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3678749154206AA2C7DE69F6 /* WidgetKit.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 46DB71745F7E01A515C0F13C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 8F21FB9F02C54BE4076B12F8 /* Project object */; + proxyType = 1; + remoteGlobalIDString = F7174334A4963303CCEE4E61; + remoteInfo = UhooiPicBook; + }; + 73857B2E0E8A6F194DF299E9 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 8F21FB9F02C54BE4076B12F8 /* Project object */; + proxyType = 1; + remoteGlobalIDString = F7174334A4963303CCEE4E61; + remoteInfo = UhooiPicBook; + }; + 8DABA011EEC5DA70896A6C44 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 8F21FB9F02C54BE4076B12F8 /* Project object */; + proxyType = 1; + remoteGlobalIDString = C2DB76B6BCC6E8EF34FA57BF; + remoteInfo = UhooiPicBookWidgetsConfigurableIntent; + }; + EA1D5D72FB9D70100338E4A8 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 8F21FB9F02C54BE4076B12F8 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 162395B56ED57E8800847617; + remoteInfo = UhooiPicBookWidgets; + }; + F97CF2FC9CF60F60A337F2AA /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 8F21FB9F02C54BE4076B12F8 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 0E1AD029696068D4B516B255; + remoteInfo = UhooiPicBookStickers; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 4224260094675C4E9D31B589 /* Embed App Extensions */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 13; + files = ( + 745EB4E9574D57EB307F2AB9 /* UhooiPicBookStickers.appex in Embed App Extensions */, + F84FC678215D503C49D26C58 /* UhooiPicBookWidgets.appex in Embed App Extensions */, + 3784E43C6F9862BB2E871B15 /* UhooiPicBookWidgetsConfigurableIntent.appex in Embed App Extensions */, + ); + name = "Embed App Extensions"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 056CC3440EC68EDD8CB4F9D0 /* FirebaseAppDistribution.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = FirebaseAppDistribution.xcframework; path = Frameworks/Firebase/FirebaseAppDistribution/FirebaseAppDistribution.xcframework; sourceTree = ""; }; + 10643B8C75A51C25725E377B /* FirebaseAnalytics.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = FirebaseAnalytics.xcframework; path = Frameworks/Firebase/FirebaseAnalytics/FirebaseAnalytics.xcframework; sourceTree = ""; }; + 144AF202560DF7170CA1B88E /* FirebaseRemoteConfig.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = FirebaseRemoteConfig.xcframework; path = Frameworks/Firebase/FirebasePerformance/FirebaseRemoteConfig.xcframework; sourceTree = ""; }; + 18C42AC12CA0DA009E4241B5 /* leveldb-library.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = "leveldb-library.xcframework"; path = "Frameworks/Firebase/FirebaseFirestore/leveldb-library.xcframework"; sourceTree = ""; }; + 1B117974B5DFAEB1BA1DB35C /* MonsterDetailPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MonsterDetailPage.swift; sourceTree = ""; }; + 33B49E10FB3AFB3745B0AEF4 /* SwiftUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftUI.framework; path = System/Library/Frameworks/SwiftUI.framework; sourceTree = SDKROOT; }; + 3678749154206AA2C7DE69F6 /* WidgetKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WidgetKit.framework; path = System/Library/Frameworks/WidgetKit.framework; sourceTree = SDKROOT; }; + 39F4CD1686D945CFB87141CE /* GoogleUtilities.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = GoogleUtilities.xcframework; path = Frameworks/Firebase/FirebaseAnalytics/GoogleUtilities.xcframework; sourceTree = ""; }; + 541427EC2F900D49CD247CB2 /* XCUIElement+Ex.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "XCUIElement+Ex.swift"; sourceTree = ""; }; + 5FC40872E7A32ADB0B8AE3D7 /* FirebaseFirestore.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = FirebaseFirestore.xcframework; path = Frameworks/Firebase/FirebaseFirestore/FirebaseFirestore.xcframework; sourceTree = ""; }; + 64FA23DFA00E386CF2DBCE63 /* FirebaseCoreDiagnostics.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = FirebaseCoreDiagnostics.xcframework; path = Frameworks/Firebase/FirebaseAnalytics/FirebaseCoreDiagnostics.xcframework; sourceTree = ""; }; + 792E8EE6278C430A000F3902 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.intentdefinition; name = Base; path = Base.lproj/WidgetsConfiguration.intentdefinition; sourceTree = ""; }; + 792E8EE7278C430A000F3902 /* MonsterIntentObject+Convert.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "MonsterIntentObject+Convert.swift"; sourceTree = ""; }; + 792E8EF1278C4318000F3902 /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/WidgetsConfiguration.strings; sourceTree = ""; }; + 792E8EF2278C431A000F3902 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/WidgetsConfiguration.strings; sourceTree = ""; }; + 792E8F3E278C4B2D000F3902 /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/InfoPlist.strings; sourceTree = ""; }; + 792E8F41278C4B2D000F3902 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; + 792E8F42278C4B2D000F3902 /* UhooiPicBook.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = UhooiPicBook.entitlements; sourceTree = ""; }; + 792E8F45278C4B2D000F3902 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 792E8F46278C4B2D000F3902 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 792E8F47278C4B2D000F3902 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 792E8F48278C4B2D000F3902 /* SceneDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; + 792E8F51278C4B5E000F3902 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/LaunchScreen.strings; sourceTree = ""; }; + 792E8F58278C4C8E000F3902 /* Stickers.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Stickers.xcassets; sourceTree = ""; }; + 792E8F59278C4C8E000F3902 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 792E8F88278C6532000F3902 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 792E8F8A278C6532000F3902 /* MonsterConfigurableWidget.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MonsterConfigurableWidget.swift; sourceTree = ""; }; + 792E8F8B278C6532000F3902 /* UhooiPicBookWidgets.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UhooiPicBookWidgets.swift; sourceTree = ""; }; + 792E8F95278C67F1000F3902 /* IntentHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IntentHandler.swift; sourceTree = ""; }; + 792E8F96278C67F1000F3902 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 792E8F9B278C6933000F3902 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = UhooiPicBook/Production/Assets.xcassets; sourceTree = SOURCE_ROOT; }; + 792E8FA1278C6A56000F3902 /* GoogleService-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "Shared/Production/GoogleService-Info.plist"; sourceTree = SOURCE_ROOT; }; + 792E8FDA278C7B6F000F3902 /* Settings.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = Settings.bundle; sourceTree = ""; }; + 7955D06327B94B730061AE99 /* Production.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = Production.xctestplan; sourceTree = ""; }; + 7C5239C3163F47164ECE33E8 /* ImagePopupPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImagePopupPage.swift; sourceTree = ""; }; + 83C280827AC1AC8CDC771EC4 /* UhooiPicBookUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = UhooiPicBookUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 84E4ADEF286CCE96A2942A1A /* FirebaseCore.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = FirebaseCore.xcframework; path = Frameworks/Firebase/FirebaseAnalytics/FirebaseCore.xcframework; sourceTree = ""; }; + 8A43FC43A5F5F2869F78909D /* FirebasePerformance.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = FirebasePerformance.xcframework; path = Frameworks/Firebase/FirebasePerformance/FirebasePerformance.xcframework; sourceTree = ""; }; + 8B1D686A013EAD76B19604C9 /* PageProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PageProtocol.swift; sourceTree = ""; }; + 8BA1D60203EDBC076FFF5642 /* FirebaseMessaging.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = FirebaseMessaging.xcframework; path = Frameworks/Firebase/FirebaseMessaging/FirebaseMessaging.xcframework; sourceTree = ""; }; + 8F94607B0325642C330CD793 /* nanopb.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = nanopb.xcframework; path = Frameworks/Firebase/FirebaseAnalytics/nanopb.xcframework; sourceTree = ""; }; + 988A97043A06E226C6868588 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; + AE659249AE186390141063EE /* UhooiPicBookWidgets.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = UhooiPicBookWidgets.appex; sourceTree = BUILT_PRODUCTS_DIR; }; + AE841A10BB74D787FB068BD6 /* GoogleDataTransport.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = GoogleDataTransport.xcframework; path = Frameworks/Firebase/FirebaseAnalytics/GoogleDataTransport.xcframework; sourceTree = ""; }; + B121E1EC2442F244D11C5380 /* PromisesObjC.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = PromisesObjC.xcframework; path = Frameworks/Firebase/FirebaseAnalytics/PromisesObjC.xcframework; sourceTree = ""; }; + B21F0F147EB90FE7EAF86DB2 /* MonsterListPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MonsterListPage.swift; sourceTree = ""; }; + B2A9349AFF95EFE00FCADA23 /* FirebaseCrashlytics.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = FirebaseCrashlytics.xcframework; path = Frameworks/Firebase/FirebaseCrashlytics/FirebaseCrashlytics.xcframework; sourceTree = ""; }; + B3034A14E3F41394DEB55A62 /* GoogleAppMeasurement.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = GoogleAppMeasurement.xcframework; path = Frameworks/Firebase/FirebaseAnalytics/GoogleAppMeasurement.xcframework; sourceTree = ""; }; + B3ACB3BE3E7ED3A4C84410CA /* BoringSSL-GRPC.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = "BoringSSL-GRPC.xcframework"; path = "Frameworks/Firebase/FirebaseFirestore/BoringSSL-GRPC.xcframework"; sourceTree = ""; }; + BA21C3023C46CC6151A43886 /* UhooiPicBookTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = UhooiPicBookTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + BD6DB9EB8A33ED4D0822DB8F /* FirebaseABTesting.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = FirebaseABTesting.xcframework; path = Frameworks/Firebase/FirebasePerformance/FirebaseABTesting.xcframework; sourceTree = ""; }; + BF104BB707E325AC73440499 /* FirebaseInstallations.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = FirebaseInstallations.xcframework; path = Frameworks/Firebase/FirebaseAnalytics/FirebaseInstallations.xcframework; sourceTree = ""; }; + D1BC591FA4C18A058784472F /* ActivityPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActivityPage.swift; sourceTree = ""; }; + D3A28FF132F9DB6448EAC23F /* UhooiPicBookWidgetsConfigurableIntent.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = UhooiPicBookWidgetsConfigurableIntent.appex; sourceTree = BUILT_PRODUCTS_DIR; }; + D97430DE3B018D83FA30BA3F /* UhooiPicBookStickers.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = UhooiPicBookStickers.appex; sourceTree = BUILT_PRODUCTS_DIR; }; + E4618659C63EB6D450468854 /* BundleStringTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BundleStringTests.swift; sourceTree = ""; }; + E486EDFB4B99417855E33115 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; + E4EA4C797239C728014E8BCC /* UhooiPicBook.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = UhooiPicBook.app; sourceTree = BUILT_PRODUCTS_DIR; }; + E8C25BE3139AF9A212CCC8F0 /* gRPC-C++.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = "gRPC-C++.xcframework"; path = "Frameworks/Firebase/FirebaseFirestore/gRPC-C++.xcframework"; sourceTree = ""; }; + E93FC0F13B863F9E5F5D500D /* abseil.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = abseil.xcframework; path = Frameworks/Firebase/FirebaseFirestore/abseil.xcframework; sourceTree = ""; }; + F6868AB01C3AABA6F00D83C8 /* gRPC-Core.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = "gRPC-Core.xcframework"; path = "Frameworks/Firebase/FirebaseFirestore/gRPC-Core.xcframework"; sourceTree = ""; }; + F77956692405C61E8D8C04B5 /* UhooiPicBookUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UhooiPicBookUITests.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 6986B5ACA2E569F81163AE24 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 797ABFA9278A9BA5005B445B /* AppModule in Frameworks */, + 7995BD302786F36A00B553DC /* FirebaseMessagingBridge in Frameworks */, + 7921EEF92785E5E40033DDEC /* FirebaseSetup in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 7807E38B57A7E4DC3FAF7927 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 7921EEFB2785E6290033DDEC /* FirebaseSetup in Frameworks */, + 791904D42794085600416F7D /* MonstersRepository in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + F7D826D061CE893E40DE10DA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 5022F0F1F72B5341C9486B7A /* SwiftUI.framework in Frameworks */, + 791904CC2793F9DA00416F7D /* ImageLoader in Frameworks */, + F8BBF148F1591E57471509B2 /* WidgetKit.framework in Frameworks */, + 79C193AB2789CF5200E7A58E /* MonsterWidgets in Frameworks */, + 791904D22794084800416F7D /* MonstersRepository in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 17E82F135C45DA22DAD85E72 /* Foundation */ = { + isa = PBXGroup; + children = ( + E4618659C63EB6D450468854 /* BundleStringTests.swift */, + ); + path = Foundation; + sourceTree = ""; + }; + 47C552D3546C641AB89783C1 = { + isa = PBXGroup; + children = ( + 7955D06327B94B730061AE99 /* Production.xctestplan */, + 781042549E5A01519EFED671 /* Shared */, + 792E8F3A278C4B2D000F3902 /* UhooiPicBook */, + 792E8F57278C4C8E000F3902 /* UhooiPicBookStickers */, + BAB84381A6737A2083BC961F /* UhooiPicBookTests */, + EB1BD4D1C82D8077591B0698 /* UhooiPicBookUITests */, + 792E8F87278C6532000F3902 /* UhooiPicBookWidgets */, + 792E8F94278C67F1000F3902 /* UhooiPicBookWidgetsConfigurableIntent */, + 644BA30E73485BDC342F7204 /* Frameworks */, + B9F854ED00B8603447D5057B /* Products */, + ); + sourceTree = ""; + }; + 644BA30E73485BDC342F7204 /* Frameworks */ = { + isa = PBXGroup; + children = ( + E93FC0F13B863F9E5F5D500D /* abseil.xcframework */, + B3ACB3BE3E7ED3A4C84410CA /* BoringSSL-GRPC.xcframework */, + BD6DB9EB8A33ED4D0822DB8F /* FirebaseABTesting.xcframework */, + 10643B8C75A51C25725E377B /* FirebaseAnalytics.xcframework */, + 056CC3440EC68EDD8CB4F9D0 /* FirebaseAppDistribution.xcframework */, + 84E4ADEF286CCE96A2942A1A /* FirebaseCore.xcframework */, + 64FA23DFA00E386CF2DBCE63 /* FirebaseCoreDiagnostics.xcframework */, + B2A9349AFF95EFE00FCADA23 /* FirebaseCrashlytics.xcframework */, + 5FC40872E7A32ADB0B8AE3D7 /* FirebaseFirestore.xcframework */, + BF104BB707E325AC73440499 /* FirebaseInstallations.xcframework */, + 8BA1D60203EDBC076FFF5642 /* FirebaseMessaging.xcframework */, + 8A43FC43A5F5F2869F78909D /* FirebasePerformance.xcframework */, + 144AF202560DF7170CA1B88E /* FirebaseRemoteConfig.xcframework */, + B3034A14E3F41394DEB55A62 /* GoogleAppMeasurement.xcframework */, + AE841A10BB74D787FB068BD6 /* GoogleDataTransport.xcframework */, + 39F4CD1686D945CFB87141CE /* GoogleUtilities.xcframework */, + E8C25BE3139AF9A212CCC8F0 /* gRPC-C++.xcframework */, + F6868AB01C3AABA6F00D83C8 /* gRPC-Core.xcframework */, + 18C42AC12CA0DA009E4241B5 /* leveldb-library.xcframework */, + 8F94607B0325642C330CD793 /* nanopb.xcframework */, + B121E1EC2442F244D11C5380 /* PromisesObjC.xcframework */, + 33B49E10FB3AFB3745B0AEF4 /* SwiftUI.framework */, + 3678749154206AA2C7DE69F6 /* WidgetKit.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 781042549E5A01519EFED671 /* Shared */ = { + isa = PBXGroup; + children = ( + 792E8EE1278C430A000F3902 /* IntentDefinition */, + C2B92E538C189F4941F7DAFE /* Resources */, + ); + path = Shared; + sourceTree = ""; + }; + 792E8EE1278C430A000F3902 /* IntentDefinition */ = { + isa = PBXGroup; + children = ( + 792E8EE7278C430A000F3902 /* MonsterIntentObject+Convert.swift */, + 792E8EE5278C430A000F3902 /* WidgetsConfiguration.intentdefinition */, + ); + name = IntentDefinition; + path = Shared/IntentDefinition; + sourceTree = SOURCE_ROOT; + }; + 792E8F3A278C4B2D000F3902 /* UhooiPicBook */ = { + isa = PBXGroup; + children = ( + 792E8F47278C4B2D000F3902 /* AppDelegate.swift */, + 792E8F48278C4B2D000F3902 /* SceneDelegate.swift */, + 792E8F3C278C4B2D000F3902 /* Resources */, + ); + path = UhooiPicBook; + sourceTree = ""; + }; + 792E8F3C278C4B2D000F3902 /* Resources */ = { + isa = PBXGroup; + children = ( + 792E8F9B278C6933000F3902 /* Assets.xcassets */, + 792E8F46278C4B2D000F3902 /* Info.plist */, + 792E8F3D278C4B2D000F3902 /* InfoPlist.strings */, + 792E8F44278C4B2D000F3902 /* LaunchScreen.storyboard */, + 792E8FDA278C7B6F000F3902 /* Settings.bundle */, + 792E8F42278C4B2D000F3902 /* UhooiPicBook.entitlements */, + ); + path = Resources; + sourceTree = ""; + }; + 792E8F57278C4C8E000F3902 /* UhooiPicBookStickers */ = { + isa = PBXGroup; + children = ( + 792E8F59278C4C8E000F3902 /* Info.plist */, + 792E8F58278C4C8E000F3902 /* Stickers.xcassets */, + ); + path = UhooiPicBookStickers; + sourceTree = ""; + }; + 792E8F87278C6532000F3902 /* UhooiPicBookWidgets */ = { + isa = PBXGroup; + children = ( + 792E8F88278C6532000F3902 /* Info.plist */, + 792E8F8B278C6532000F3902 /* UhooiPicBookWidgets.swift */, + 792E8F89278C6532000F3902 /* Monster */, + ); + path = UhooiPicBookWidgets; + sourceTree = ""; + }; + 792E8F89278C6532000F3902 /* Monster */ = { + isa = PBXGroup; + children = ( + 792E8F8A278C6532000F3902 /* MonsterConfigurableWidget.swift */, + ); + path = Monster; + sourceTree = ""; + }; + 792E8F94278C67F1000F3902 /* UhooiPicBookWidgetsConfigurableIntent */ = { + isa = PBXGroup; + children = ( + 792E8F96278C67F1000F3902 /* Info.plist */, + 792E8F95278C67F1000F3902 /* IntentHandler.swift */, + ); + path = UhooiPicBookWidgetsConfigurableIntent; + sourceTree = ""; + }; + 9D14FEE7DAB67CCFD61B333D /* TestCases */ = { + isa = PBXGroup; + children = ( + F77956692405C61E8D8C04B5 /* UhooiPicBookUITests.swift */, + ); + path = TestCases; + sourceTree = ""; + }; + 9E07DDF4AF7D2B2926033FDC /* Extensions */ = { + isa = PBXGroup; + children = ( + 17E82F135C45DA22DAD85E72 /* Foundation */, + ); + path = Extensions; + sourceTree = ""; + }; + B9F854ED00B8603447D5057B /* Products */ = { + isa = PBXGroup; + children = ( + E4EA4C797239C728014E8BCC /* UhooiPicBook.app */, + D97430DE3B018D83FA30BA3F /* UhooiPicBookStickers.appex */, + BA21C3023C46CC6151A43886 /* UhooiPicBookTests.xctest */, + 83C280827AC1AC8CDC771EC4 /* UhooiPicBookUITests.xctest */, + AE659249AE186390141063EE /* UhooiPicBookWidgets.appex */, + D3A28FF132F9DB6448EAC23F /* UhooiPicBookWidgetsConfigurableIntent.appex */, + ); + name = Products; + sourceTree = ""; + }; + BAB84381A6737A2083BC961F /* UhooiPicBookTests */ = { + isa = PBXGroup; + children = ( + 988A97043A06E226C6868588 /* Info.plist */, + 9E07DDF4AF7D2B2926033FDC /* Extensions */, + ); + path = UhooiPicBookTests; + sourceTree = ""; + }; + C2B92E538C189F4941F7DAFE /* Resources */ = { + isa = PBXGroup; + children = ( + 792E8FA1278C6A56000F3902 /* GoogleService-Info.plist */, + ); + path = Resources; + sourceTree = ""; + }; + EB1BD4D1C82D8077591B0698 /* UhooiPicBookUITests */ = { + isa = PBXGroup; + children = ( + E486EDFB4B99417855E33115 /* Info.plist */, + 8B1D686A013EAD76B19604C9 /* PageProtocol.swift */, + 541427EC2F900D49CD247CB2 /* XCUIElement+Ex.swift */, + EB9FF08BDED117C228729B0B /* Pages */, + 9D14FEE7DAB67CCFD61B333D /* TestCases */, + ); + path = UhooiPicBookUITests; + sourceTree = ""; + }; + EB9FF08BDED117C228729B0B /* Pages */ = { + isa = PBXGroup; + children = ( + D1BC591FA4C18A058784472F /* ActivityPage.swift */, + 7C5239C3163F47164ECE33E8 /* ImagePopupPage.swift */, + 1B117974B5DFAEB1BA1DB35C /* MonsterDetailPage.swift */, + B21F0F147EB90FE7EAF86DB2 /* MonsterListPage.swift */, + ); + path = Pages; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 0E1AD029696068D4B516B255 /* UhooiPicBookStickers */ = { + isa = PBXNativeTarget; + buildConfigurationList = 3E50B2D32EEA9C3FA89AE8F6 /* Build configuration list for PBXNativeTarget "UhooiPicBookStickers" */; + buildPhases = ( + D3F1C1F751AC3C59ADE107DA /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = UhooiPicBookStickers; + productName = UhooiPicBookStickers; + productReference = D97430DE3B018D83FA30BA3F /* UhooiPicBookStickers.appex */; + productType = "com.apple.product-type.app-extension.messages-sticker-pack"; + }; + 162395B56ED57E8800847617 /* UhooiPicBookWidgets */ = { + isa = PBXNativeTarget; + buildConfigurationList = BF5510DB2613969D49C12435 /* Build configuration list for PBXNativeTarget "UhooiPicBookWidgets" */; + buildPhases = ( + B1556D34667F4525E961FE38 /* Sources */, + 895AFD8905206AF423271193 /* Resources */, + F7D826D061CE893E40DE10DA /* Frameworks */, + ED5C992B9082C440532A022E /* Run Firebase Crashlytics */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = UhooiPicBookWidgets; + packageProductDependencies = ( + 79C193AA2789CF5200E7A58E /* MonsterWidgets */, + 791904CB2793F9DA00416F7D /* ImageLoader */, + 791904D12794084800416F7D /* MonstersRepository */, + ); + productName = UhooiPicBookWidgets; + productReference = AE659249AE186390141063EE /* UhooiPicBookWidgets.appex */; + productType = "com.apple.product-type.app-extension"; + }; + 4677FBF8E3C5D8691051D106 /* UhooiPicBookTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1FF40AA4CFE5087652123EAD /* Build configuration list for PBXNativeTarget "UhooiPicBookTests" */; + buildPhases = ( + 4FE41A7B35B5E5FAA407F3FA /* Sources */, + ); + buildRules = ( + ); + dependencies = ( + 4DAF6BC74EE9AEF3E06A50D2 /* PBXTargetDependency */, + ); + name = UhooiPicBookTests; + productName = UhooiPicBookTests; + productReference = BA21C3023C46CC6151A43886 /* UhooiPicBookTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + AD5F2C9896C8C0CAC68E089A /* UhooiPicBookUITests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 5336812240FABFFCD289F94B /* Build configuration list for PBXNativeTarget "UhooiPicBookUITests" */; + buildPhases = ( + 22070DEEFB8F99971EC40231 /* Sources */, + ); + buildRules = ( + ); + dependencies = ( + BB72275143FEBC036B69BC5C /* PBXTargetDependency */, + ); + name = UhooiPicBookUITests; + productName = UhooiPicBookUITests; + productReference = 83C280827AC1AC8CDC771EC4 /* UhooiPicBookUITests.xctest */; + productType = "com.apple.product-type.bundle.ui-testing"; + }; + C2DB76B6BCC6E8EF34FA57BF /* UhooiPicBookWidgetsConfigurableIntent */ = { + isa = PBXNativeTarget; + buildConfigurationList = 0BE8F8DC9871C9E99D77E15E /* Build configuration list for PBXNativeTarget "UhooiPicBookWidgetsConfigurableIntent" */; + buildPhases = ( + 4B799ED34E78C3F6214D145F /* Sources */, + 14414248979752991022B441 /* Resources */, + 7807E38B57A7E4DC3FAF7927 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = UhooiPicBookWidgetsConfigurableIntent; + packageProductDependencies = ( + 7921EEFA2785E6290033DDEC /* FirebaseSetup */, + 791904D32794085600416F7D /* MonstersRepository */, + ); + productName = UhooiPicBookWidgetsConfigurableIntent; + productReference = D3A28FF132F9DB6448EAC23F /* UhooiPicBookWidgetsConfigurableIntent.appex */; + productType = "com.apple.product-type.app-extension"; + }; + F7174334A4963303CCEE4E61 /* UhooiPicBook */ = { + isa = PBXNativeTarget; + buildConfigurationList = 13C9DF26DB51CA2F181109A7 /* Build configuration list for PBXNativeTarget "UhooiPicBook" */; + buildPhases = ( + 1536BFDD1A0F36A88A1E7765 /* Sources */, + 3E2EB7F4463B4E5B0378F12C /* Run SwiftLint */, + 273E5548C378B1635B235E18 /* Run IBLinter */, + 0FA2530C0E3D86880E87A1B6 /* Run SpellChecker */, + 37FBDE35DD42D3CF137E6A2B /* Resources */, + 6986B5ACA2E569F81163AE24 /* Frameworks */, + 4224260094675C4E9D31B589 /* Embed App Extensions */, + CE0A4BD6818C7BDE485094F6 /* Run Firebase Crashlytics */, + ); + buildRules = ( + ); + dependencies = ( + 51B7EA9FEB54D0504D29FD8D /* PBXTargetDependency */, + EC6680A6178CDFC223187F43 /* PBXTargetDependency */, + CFF8820FAA1030EA6191F5CE /* PBXTargetDependency */, + ); + name = UhooiPicBook; + packageProductDependencies = ( + 7921EEF82785E5E40033DDEC /* FirebaseSetup */, + 7995BD2F2786F36A00B553DC /* FirebaseMessagingBridge */, + 797ABFA8278A9BA5005B445B /* AppModule */, + ); + productName = UhooiPicBook; + productReference = E4EA4C797239C728014E8BCC /* UhooiPicBook.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 8F21FB9F02C54BE4076B12F8 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1330; + TargetAttributes = { + 0E1AD029696068D4B516B255 = { + DevelopmentTeam = 47E56DYP3N; + ProvisioningStyle = Automatic; + }; + 162395B56ED57E8800847617 = { + DevelopmentTeam = 47E56DYP3N; + ProvisioningStyle = Automatic; + }; + 4677FBF8E3C5D8691051D106 = { + DevelopmentTeam = 47E56DYP3N; + }; + AD5F2C9896C8C0CAC68E089A = { + DevelopmentTeam = 47E56DYP3N; + TestTargetID = F7174334A4963303CCEE4E61; + }; + C2DB76B6BCC6E8EF34FA57BF = { + DevelopmentTeam = 47E56DYP3N; + ProvisioningStyle = Automatic; + }; + F7174334A4963303CCEE4E61 = { + DevelopmentTeam = 47E56DYP3N; + }; + }; + }; + buildConfigurationList = 09429085F8A0F9BD0D9F66E1 /* Build configuration list for PBXProject "Production" */; + compatibilityVersion = "Xcode 10.0"; + developmentRegion = ja; + hasScannedForEncodings = 0; + knownRegions = ( + Base, + en, + ja, + ); + mainGroup = 47C552D3546C641AB89783C1; + packageReferences = ( + ); + projectDirPath = ""; + projectRoot = ""; + targets = ( + F7174334A4963303CCEE4E61 /* UhooiPicBook */, + 0E1AD029696068D4B516B255 /* UhooiPicBookStickers */, + 4677FBF8E3C5D8691051D106 /* UhooiPicBookTests */, + AD5F2C9896C8C0CAC68E089A /* UhooiPicBookUITests */, + 162395B56ED57E8800847617 /* UhooiPicBookWidgets */, + C2DB76B6BCC6E8EF34FA57BF /* UhooiPicBookWidgetsConfigurableIntent */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 14414248979752991022B441 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 792E8FA4278C6A56000F3902 /* GoogleService-Info.plist in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 37FBDE35DD42D3CF137E6A2B /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 792E8F4A278C4B2D000F3902 /* InfoPlist.strings in Resources */, + 792E8FA2278C6A56000F3902 /* GoogleService-Info.plist in Resources */, + 792E8FDB278C7B6F000F3902 /* Settings.bundle in Resources */, + 792E8F4D278C4B2D000F3902 /* LaunchScreen.storyboard in Resources */, + 792E8F9C278C6933000F3902 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 895AFD8905206AF423271193 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 792E8FA3278C6A56000F3902 /* GoogleService-Info.plist in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D3F1C1F751AC3C59ADE107DA /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 792E8F5A278C4C8E000F3902 /* Stickers.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 0FA2530C0E3D86880E87A1B6 /* Run SpellChecker */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = "Run SpellChecker"; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "#git_path=/usr/local/bin/git\n#files=$($git_path diff --diff-filter=d --name-only -- \"*.swift\" \"*.h\" \"*.m\")\n#if (test -z $files) || (test ${#files[@]} -eq 0); then\n# echo \"no files changed.\"\n# exit 0\n#fi\n#\n#options=\"\"\n#for file in $files\n#do\n# options=\"$options $SRCROOT/../$file\"\n#done\n#\n#SDKROOT=$(xcrun --sdk macosx --show-sdk-path)\n#SPELLCHECKER_PATH=$SRCROOT/../Tools/UhooiPicBookTools/.build/release/SpellChecker\n#if [ -f $SPELLCHECKER_PATH ]; then\n# $SPELLCHECKER_PATH --yml $SRCROOT/../.spell-checker.yml -- $options\n#else\n# echo \"warning: SpellChecker not installed, please run \\`make setup\\` .\"\n#fi\n\n"; + }; + 273E5548C378B1635B235E18 /* Run IBLinter */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = "Run IBLinter"; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "#SDKROOT=$(xcrun --sdk macosx --show-sdk-path)\n#IBLINTER_PATH=$SRCROOT/../Tools/UhooiPicBookTools/.build/release/iblinter\n#if [ -f $IBLINTER_PATH ]; then\n# $IBLINTER_PATH lint --path $SRCROOT/.. --config $SRCROOT/../.iblinter.yml\n#else\n# echo \"warning: IBLinter not installed, please run \\`make setup\\` .\"\n#fi\n\n"; + }; + 3E2EB7F4463B4E5B0378F12C /* Run SwiftLint */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = "Run SwiftLint"; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "SDKROOT=$(xcrun --sdk macosx --show-sdk-path)\nSWIFTLINT_PATH=$SRCROOT/../Tools/UhooiPicBookTools/.build/release/swiftlint\nif [ -f $SWIFTLINT_PATH ]; then\n $SWIFTLINT_PATH --config $SRCROOT/../.swiftlint.yml --fix --format\n $SWIFTLINT_PATH --config $SRCROOT/../.swiftlint.yml\nelse\n echo \"warning: SwiftLint not installed, please run \\`make setup\\` .\"\nfi\n\n"; + }; + CE0A4BD6818C7BDE485094F6 /* Run Firebase Crashlytics */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "$(SRCROOT)/$(BUILT_PRODUCTS_DIR)/$(INFOPLIST_PATH)", + ); + name = "Run Firebase Crashlytics"; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "$SRCROOT/../Frameworks/Firebase/FirebaseCrashlytics/run\n"; + }; + ED5C992B9082C440532A022E /* Run Firebase Crashlytics */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "$(SRCROOT)/$(BUILT_PRODUCTS_DIR)/$(INFOPLIST_PATH)", + ); + name = "Run Firebase Crashlytics"; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "$SRCROOT/../Frameworks/Firebase/FirebaseCrashlytics/run\n"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1536BFDD1A0F36A88A1E7765 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 792E8F4F278C4B2D000F3902 /* AppDelegate.swift in Sources */, + 792E8EEB278C430A000F3902 /* WidgetsConfiguration.intentdefinition in Sources */, + 792E8EEE278C430A000F3902 /* MonsterIntentObject+Convert.swift in Sources */, + 792E8F50278C4B2D000F3902 /* SceneDelegate.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 22070DEEFB8F99971EC40231 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 478286982E492B33E65E682B /* ActivityPage.swift in Sources */, + 3ED6158022DE90CA4AA73905 /* ImagePopupPage.swift in Sources */, + 7B7002A645C43EBB624D82D8 /* MonsterDetailPage.swift in Sources */, + 522896F9FC51ED2221060387 /* MonsterListPage.swift in Sources */, + ED23EF346F55E2E02F461F16 /* PageProtocol.swift in Sources */, + 2AB9187FB6C6F195BDFA0AEA /* UhooiPicBookUITests.swift in Sources */, + A1713DA74A4AE73B34351622 /* XCUIElement+Ex.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4B799ED34E78C3F6214D145F /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 792E8EF0278C430A000F3902 /* MonsterIntentObject+Convert.swift in Sources */, + 792E8F97278C67F1000F3902 /* IntentHandler.swift in Sources */, + 792E8EED278C430A000F3902 /* WidgetsConfiguration.intentdefinition in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4FE41A7B35B5E5FAA407F3FA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A6BE80E8825B6DA6ACE56D06 /* BundleStringTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B1556D34667F4525E961FE38 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 792E8F8D278C6532000F3902 /* MonsterConfigurableWidget.swift in Sources */, + 792E8EEC278C430A000F3902 /* WidgetsConfiguration.intentdefinition in Sources */, + 792E8F8E278C6532000F3902 /* UhooiPicBookWidgets.swift in Sources */, + 792E8EEF278C430A000F3902 /* MonsterIntentObject+Convert.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 4DAF6BC74EE9AEF3E06A50D2 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = F7174334A4963303CCEE4E61 /* UhooiPicBook */; + targetProxy = 46DB71745F7E01A515C0F13C /* PBXContainerItemProxy */; + }; + 51B7EA9FEB54D0504D29FD8D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 0E1AD029696068D4B516B255 /* UhooiPicBookStickers */; + targetProxy = F97CF2FC9CF60F60A337F2AA /* PBXContainerItemProxy */; + }; + BB72275143FEBC036B69BC5C /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = F7174334A4963303CCEE4E61 /* UhooiPicBook */; + targetProxy = 73857B2E0E8A6F194DF299E9 /* PBXContainerItemProxy */; + }; + CFF8820FAA1030EA6191F5CE /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = C2DB76B6BCC6E8EF34FA57BF /* UhooiPicBookWidgetsConfigurableIntent */; + targetProxy = 8DABA011EEC5DA70896A6C44 /* PBXContainerItemProxy */; + }; + EC6680A6178CDFC223187F43 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 162395B56ED57E8800847617 /* UhooiPicBookWidgets */; + targetProxy = EA1D5D72FB9D70100338E4A8 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 792E8EE5278C430A000F3902 /* WidgetsConfiguration.intentdefinition */ = { + isa = PBXVariantGroup; + children = ( + 792E8EE6278C430A000F3902 /* Base */, + 792E8EF1278C4318000F3902 /* ja */, + 792E8EF2278C431A000F3902 /* en */, + ); + name = WidgetsConfiguration.intentdefinition; + sourceTree = ""; + }; + 792E8F3D278C4B2D000F3902 /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + 792E8F3E278C4B2D000F3902 /* ja */, + 792E8F41278C4B2D000F3902 /* en */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; + 792E8F44278C4B2D000F3902 /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 792E8F45278C4B2D000F3902 /* Base */, + 792E8F51278C4B5E000F3902 /* en */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 09D4296D6247B3DC0D1D51D7 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + INFOPLIST_FILE = UhooiPicBookUITests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.theuhooi.UhooiPicBookUITests; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_TARGET_NAME = UhooiPicBook; + }; + name = Release; + }; + 0ED5B166D8E6F0C77AD417DD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + INFOPLIST_FILE = UhooiPicBookTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.theuhooi.UhooiPicBookTests; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/UhooiPicBook.app/UhooiPicBook"; + }; + name = Debug; + }; + 1F66094B9A6482DB9583F607 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 17; + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = "$(SRCROOT)/UhooiPicBookWidgets/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + MARKETING_VERSION = 1.6.0; + OTHER_LDFLAGS = ( + "$(inherited)", + "$(OTHER_LDFLAGS)", + "-ObjC", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.theuhooi.UhooiPicBook.Widgets; + PRODUCT_NAME = UhooiPicBookWidgets; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 2B6E9D86BE7350731825FA24 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 17; + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = "$(SRCROOT)/UhooiPicBookWidgetsConfigurableIntent/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + MARKETING_VERSION = 1.6.0; + OTHER_LDFLAGS = ( + "$(inherited)", + "$(OTHER_LDFLAGS)", + "-ObjC", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.theuhooi.UhooiPicBook.WidgetsConfigurableIntent; + PRODUCT_NAME = UhooiPicBookWidgetsConfigurableIntent; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + 47074D1AA8DC853C8208EE3C /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = "iMessage App Icon"; + CLANG_ENABLE_OBJC_WEAK = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 17; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = "$(SRCROOT)/UhooiPicBookStickers/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + LD_RUNPATH_SEARCH_PATHS = ""; + MARKETING_VERSION = 1.6.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.theuhooi.UhooiPicBook.Stickers; + PRODUCT_NAME = UhooiPicBookStickers; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 526474C0707A0615CE591087 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 17; + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = "$(SRCROOT)/UhooiPicBookWidgets/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + MARKETING_VERSION = 1.6.0; + OTHER_LDFLAGS = ( + "$(inherited)", + "$(OTHER_LDFLAGS)", + "-ObjC", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.theuhooi.UhooiPicBook.Widgets; + PRODUCT_NAME = UhooiPicBookWidgets; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + 637D639F1590AE62D4CC5F5B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + INFOPLIST_FILE = UhooiPicBookUITests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.theuhooi.UhooiPicBookUITests; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_TARGET_NAME = UhooiPicBook; + }; + name = Debug; + }; + 6F3C0123B6BDA1D471303B9B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 17; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = 47E56DYP3N; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + MARKETING_VERSION = 1.6.0; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + OTHER_LDFLAGS = ( + "$(inherited)", + "$(OTHER_LDFLAGS)", + "-ObjC", + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; + 78CA1F5826002F4089502798 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = "iMessage App Icon"; + CLANG_ENABLE_OBJC_WEAK = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 17; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = "$(SRCROOT)/UhooiPicBookStickers/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + LD_RUNPATH_SEARCH_PATHS = ""; + MARKETING_VERSION = 1.6.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.theuhooi.UhooiPicBook.Stickers; + PRODUCT_NAME = UhooiPicBookStickers; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + 7957E27092FF80EC435C94B8 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 17; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = 47E56DYP3N; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "DEBUG=1", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + MARKETING_VERSION = 1.6.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + OTHER_LDFLAGS = ( + "$(inherited)", + "$(OTHER_LDFLAGS)", + "-ObjC", + ); + OTHER_SWIFT_FLAGS = "$(inherited) -Xfrontend -warn-long-expression-type-checking=500 -Xfrontend -warn-long-function-bodies=500 -Xfrontend -warn-concurrency -Xfrontend -enable-actor-data-race-checks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 7C503DF97828E781A59C4ECF /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_ENTITLEMENTS = ""; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CURRENT_PROJECT_VERSION = 17; + DEVELOPMENT_LANGUAGE = jp; + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; + INFOPLIST_FILE = "$(SRCROOT)/UhooiPicBook/Resources/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.6.0; + PRODUCT_BUNDLE_IDENTIFIER = com.theuhooi.UhooiPicBook; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + A7401616F8B6C53FFDF54AD5 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_ENTITLEMENTS = ""; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CURRENT_PROJECT_VERSION = 17; + DEVELOPMENT_LANGUAGE = jp; + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; + INFOPLIST_FILE = "$(SRCROOT)/UhooiPicBook/Resources/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.6.0; + PRODUCT_BUNDLE_IDENTIFIER = com.theuhooi.UhooiPicBook; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + C95A34D40744F3B1A485A39D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + INFOPLIST_FILE = UhooiPicBookTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.theuhooi.UhooiPicBookTests; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/UhooiPicBook.app/UhooiPicBook"; + }; + name = Release; + }; + CE81301A562141C55A4EA86A /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 17; + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = "$(SRCROOT)/UhooiPicBookWidgetsConfigurableIntent/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + MARKETING_VERSION = 1.6.0; + OTHER_LDFLAGS = ( + "$(inherited)", + "$(OTHER_LDFLAGS)", + "-ObjC", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.theuhooi.UhooiPicBook.WidgetsConfigurableIntent; + PRODUCT_NAME = UhooiPicBookWidgetsConfigurableIntent; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 09429085F8A0F9BD0D9F66E1 /* Build configuration list for PBXProject "Production" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7957E27092FF80EC435C94B8 /* Debug */, + 6F3C0123B6BDA1D471303B9B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + 0BE8F8DC9871C9E99D77E15E /* Build configuration list for PBXNativeTarget "UhooiPicBookWidgetsConfigurableIntent" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + CE81301A562141C55A4EA86A /* Debug */, + 2B6E9D86BE7350731825FA24 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + 13C9DF26DB51CA2F181109A7 /* Build configuration list for PBXNativeTarget "UhooiPicBook" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7C503DF97828E781A59C4ECF /* Debug */, + A7401616F8B6C53FFDF54AD5 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + 1FF40AA4CFE5087652123EAD /* Build configuration list for PBXNativeTarget "UhooiPicBookTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0ED5B166D8E6F0C77AD417DD /* Debug */, + C95A34D40744F3B1A485A39D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + 3E50B2D32EEA9C3FA89AE8F6 /* Build configuration list for PBXNativeTarget "UhooiPicBookStickers" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 47074D1AA8DC853C8208EE3C /* Debug */, + 78CA1F5826002F4089502798 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + 5336812240FABFFCD289F94B /* Build configuration list for PBXNativeTarget "UhooiPicBookUITests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 637D639F1590AE62D4CC5F5B /* Debug */, + 09D4296D6247B3DC0D1D51D7 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + BF5510DB2613969D49C12435 /* Build configuration list for PBXNativeTarget "UhooiPicBookWidgets" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1F66094B9A6482DB9583F607 /* Debug */, + 526474C0707A0615CE591087 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; +/* End XCConfigurationList section */ + +/* Begin XCSwiftPackageProductDependency section */ + 791904CB2793F9DA00416F7D /* ImageLoader */ = { + isa = XCSwiftPackageProductDependency; + productName = ImageLoader; + }; + 791904D12794084800416F7D /* MonstersRepository */ = { + isa = XCSwiftPackageProductDependency; + productName = MonstersRepository; + }; + 791904D32794085600416F7D /* MonstersRepository */ = { + isa = XCSwiftPackageProductDependency; + productName = MonstersRepository; + }; + 7921EEF82785E5E40033DDEC /* FirebaseSetup */ = { + isa = XCSwiftPackageProductDependency; + productName = FirebaseSetup; + }; + 7921EEFA2785E6290033DDEC /* FirebaseSetup */ = { + isa = XCSwiftPackageProductDependency; + productName = FirebaseSetup; + }; + 797ABFA8278A9BA5005B445B /* AppModule */ = { + isa = XCSwiftPackageProductDependency; + productName = AppModule; + }; + 7995BD2F2786F36A00B553DC /* FirebaseMessagingBridge */ = { + isa = XCSwiftPackageProductDependency; + productName = FirebaseMessagingBridge; + }; + 79C193AA2789CF5200E7A58E /* MonsterWidgets */ = { + isa = XCSwiftPackageProductDependency; + productName = MonsterWidgets; + }; +/* End XCSwiftPackageProductDependency section */ + }; + rootObject = 8F21FB9F02C54BE4076B12F8 /* Project object */; +} diff --git a/App/Production.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/App/Production.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..919434a6 --- /dev/null +++ b/App/Production.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/App/Production.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/App/Production.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/App/Production.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/App/Production.xcodeproj/xcshareddata/xcschemes/UhooiPicBook.xcscheme b/App/Production.xcodeproj/xcshareddata/xcschemes/UhooiPicBook.xcscheme new file mode 100644 index 00000000..519df04a --- /dev/null +++ b/App/Production.xcodeproj/xcshareddata/xcschemes/UhooiPicBook.xcscheme @@ -0,0 +1,147 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/App/Production.xcodeproj/xcshareddata/xcschemes/UhooiPicBookStickers.xcscheme b/App/Production.xcodeproj/xcshareddata/xcschemes/UhooiPicBookStickers.xcscheme new file mode 100644 index 00000000..959a7599 --- /dev/null +++ b/App/Production.xcodeproj/xcshareddata/xcschemes/UhooiPicBookStickers.xcscheme @@ -0,0 +1,107 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/App/Production.xcodeproj/xcshareddata/xcschemes/UhooiPicBookWidgets.xcscheme b/App/Production.xcodeproj/xcshareddata/xcschemes/UhooiPicBookWidgets.xcscheme new file mode 100644 index 00000000..e8d1436d --- /dev/null +++ b/App/Production.xcodeproj/xcshareddata/xcschemes/UhooiPicBookWidgets.xcscheme @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/App/Production.xcodeproj/xcshareddata/xcschemes/UhooiPicBookWidgetsConfigurableIntent.xcscheme b/App/Production.xcodeproj/xcshareddata/xcschemes/UhooiPicBookWidgetsConfigurableIntent.xcscheme new file mode 100644 index 00000000..5c7248cd --- /dev/null +++ b/App/Production.xcodeproj/xcshareddata/xcschemes/UhooiPicBookWidgetsConfigurableIntent.xcscheme @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/App/Production.xctestplan b/App/Production.xctestplan new file mode 100644 index 00000000..406b91dd --- /dev/null +++ b/App/Production.xctestplan @@ -0,0 +1,65 @@ +{ + "configurations" : [ + { + "id" : "03C95FB5-EEAF-45DD-A484-C328E6F0AD67", + "name" : "English", + "options" : { + "language" : "en", + "locationScenario" : { + "identifier" : "New York, NY, USA", + "referenceType" : "built-in" + }, + "region" : "US" + } + }, + { + "id" : "8981905E-0DAA-41B6-A94A-FD47D42FC583", + "name" : "Japanese", + "options" : { + "language" : "ja", + "locationScenario" : { + "identifier" : "Tokyo, Japan", + "referenceType" : "built-in" + }, + "region" : "JP" + } + } + ], + "defaultOptions" : { + "codeCoverage" : { + "targets" : [ + { + "containerPath" : "container:..", + "identifier" : "AppModule", + "name" : "AppModule" + } + ] + }, + "defaultTestExecutionTimeAllowance" : 60, + "targetForVariableExpansion" : { + "containerPath" : "container:Production.xcodeproj", + "identifier" : "F7174334A4963303CCEE4E61", + "name" : "UhooiPicBook" + }, + "testTimeoutsEnabled" : true + }, + "testTargets" : [ + { + "parallelizable" : true, + "target" : { + "containerPath" : "container:Production.xcodeproj", + "identifier" : "4677FBF8E3C5D8691051D106", + "name" : "UhooiPicBookTests" + } + }, + { + "parallelizable" : true, + "target" : { + "containerPath" : "container:Production.xcodeproj", + "identifier" : "AD5F2C9896C8C0CAC68E089A", + "name" : "UhooiPicBookUITests" + } + } + ], + "version" : 1 +} diff --git a/GoogleServiceInfo/GoogleService-Info-Develop.plist b/App/Shared/Develop/GoogleService-Info.plist similarity index 100% rename from GoogleServiceInfo/GoogleService-Info-Develop.plist rename to App/Shared/Develop/GoogleService-Info.plist diff --git a/Shared/IntentDefinition/Base.lproj/WidgetsConfiguration.intentdefinition b/App/Shared/IntentDefinition/Base.lproj/WidgetsConfiguration.intentdefinition similarity index 97% rename from Shared/IntentDefinition/Base.lproj/WidgetsConfiguration.intentdefinition rename to App/Shared/IntentDefinition/Base.lproj/WidgetsConfiguration.intentdefinition index d7b9922b..0010cf17 100644 --- a/Shared/IntentDefinition/Base.lproj/WidgetsConfiguration.intentdefinition +++ b/App/Shared/IntentDefinition/Base.lproj/WidgetsConfiguration.intentdefinition @@ -9,11 +9,11 @@ INIntentDefinitionNamespace uWBxEI INIntentDefinitionSystemVersion - 20B29 + 20G165 INIntentDefinitionToolsBuildVersion - 12B45b + 13C100 INIntentDefinitionToolsVersion - 12.2 + 13.2.1 INIntents @@ -214,13 +214,13 @@ INTypePropertyDisplayName - Icon Url + Icon URL INTypePropertyDisplayNameID LDC0ih INTypePropertyDisplayPriority 8 INTypePropertyName - iconUrl + iconURL INTypePropertyTag 104 INTypePropertyType @@ -228,13 +228,13 @@ INTypePropertyDisplayName - Dancing Url String + Dancing URL String INTypePropertyDisplayNameID mlnQMc INTypePropertyDisplayPriority 9 INTypePropertyName - dancingUrlString + dancingURLString INTypePropertyTag 106 INTypePropertyType diff --git a/Shared/IntentDefinition/MonsterIntentObject+Convert.swift b/App/Shared/IntentDefinition/MonsterIntentObject+Convert.swift similarity index 56% rename from Shared/IntentDefinition/MonsterIntentObject+Convert.swift rename to App/Shared/IntentDefinition/MonsterIntentObject+Convert.swift index cefa550c..08dbc5ff 100644 --- a/Shared/IntentDefinition/MonsterIntentObject+Convert.swift +++ b/App/Shared/IntentDefinition/MonsterIntentObject+Convert.swift @@ -6,6 +6,7 @@ // import Intents +import MonstersRepository extension MonsterIntentObject { convenience init(monster: MonsterDTO) { @@ -13,27 +14,27 @@ extension MonsterIntentObject { self.name = monster.name self.body = monster.description // The `description` is a reserved word. self.baseColorCode = monster.baseColorCode - self.iconUrl = URL(string: monster.iconUrlString) - self.dancingUrlString = monster.dancingUrlString + self.iconURL = URL(string: monster.iconURLString) + self.dancingURLString = monster.dancingURLString self.order = monster.order as NSNumber } - func convertToDTO() -> MonsterDTO? { - guard let name = name, - let description = body, - let baseColorCode = baseColorCode, - let iconUrl = iconUrl, - let dancingUrlString = dancingUrlString, - let order = order + func dto() -> MonsterDTO? { + guard let name, + let body, + let baseColorCode, + let iconURL, + let dancingURLString, + let order else { return nil } return MonsterDTO( name: name, - description: description, + description: body, baseColorCode: baseColorCode, - iconUrlString: iconUrl.absoluteString, - dancingUrlString: dancingUrlString, + iconURLString: iconURL.absoluteString, + dancingURLString: dancingURLString, order: order.intValue ) } diff --git a/Shared/IntentDefinition/en.lproj/WidgetsConfiguration.strings b/App/Shared/IntentDefinition/en.lproj/WidgetsConfiguration.strings similarity index 76% rename from Shared/IntentDefinition/en.lproj/WidgetsConfiguration.strings rename to App/Shared/IntentDefinition/en.lproj/WidgetsConfiguration.strings index 232a849f..f6516538 100644 --- a/Shared/IntentDefinition/en.lproj/WidgetsConfiguration.strings +++ b/App/Shared/IntentDefinition/en.lproj/WidgetsConfiguration.strings @@ -6,13 +6,13 @@ "FHLn3U" = "Character"; -"LDC0ih" = "Icon Url"; +"LDC0ih" = "Icon URL"; "SVmOax" = "Order"; "cR4ir7" = "Character"; -"mlnQMc" = "Dancing Url String"; +"mlnQMc" = "Dancing URL String"; "pZ2SDO" = "Description"; diff --git a/Shared/IntentDefinition/ja.lproj/WidgetsConfiguration.strings b/App/Shared/IntentDefinition/ja.lproj/WidgetsConfiguration.strings similarity index 100% rename from Shared/IntentDefinition/ja.lproj/WidgetsConfiguration.strings rename to App/Shared/IntentDefinition/ja.lproj/WidgetsConfiguration.strings diff --git a/GoogleServiceInfo/GoogleService-Info-Production.plist b/App/Shared/Production/GoogleService-Info.plist similarity index 100% rename from GoogleServiceInfo/GoogleService-Info-Production.plist rename to App/Shared/Production/GoogleService-Info.plist diff --git a/App/Shared/Resources/.gitkeep b/App/Shared/Resources/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/UhooiPicBook/AppDelegate.swift b/App/UhooiPicBook/AppDelegate.swift similarity index 89% rename from UhooiPicBook/AppDelegate.swift rename to App/UhooiPicBook/AppDelegate.swift index 66894546..032d2e5d 100644 --- a/UhooiPicBook/AppDelegate.swift +++ b/App/UhooiPicBook/AppDelegate.swift @@ -7,24 +7,20 @@ // import UIKit -import FirebaseCore -import FirebaseMessaging -#if DEBUG -import Gedatsu -#endif +import FirebaseSetup +import FirebaseMessagingBridge @UIApplicationMain +@MainActor class AppDelegate: UIResponder, UIApplicationDelegate { + private let firebaseMessagingBridge = FirebaseMessagingBridge() + // swiftlint:disable:next discouraged_optional_collection func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { - #if DEBUG - Gedatsu.open() - #endif - - FirebaseApp.configure() + FirebaseSetup.configure() configureNotifications(application: application) - Messaging.messaging().delegate = self + firebaseMessagingBridge.delegate = self return true } @@ -85,8 +81,8 @@ extension AppDelegate: UNUserNotificationCenterDelegate { } } -extension AppDelegate: MessagingDelegate { - func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) { +extension AppDelegate: MessagingBridgeDelegate { + func didReceiveRegistrationToken(_ fcmToken: String?) { guard let fcmToken = fcmToken else { return } diff --git a/App/UhooiPicBook/Develop/Assets.xcassets/AppIcon.appiconset/Contents.json b/App/UhooiPicBook/Develop/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..1d9d0aa2 --- /dev/null +++ b/App/UhooiPicBook/Develop/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,14 @@ +{ + "images" : [ + { + "filename" : "icon_develop_AppStore.png", + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-DEVELOP.appiconset/icon_develop_AppStore.png b/App/UhooiPicBook/Develop/Assets.xcassets/AppIcon.appiconset/icon_develop_AppStore.png similarity index 100% rename from UhooiPicBook/Resources/Assets.xcassets/AppIcon-DEVELOP.appiconset/icon_develop_AppStore.png rename to App/UhooiPicBook/Develop/Assets.xcassets/AppIcon.appiconset/icon_develop_AppStore.png diff --git a/UhooiPicBook/Resources/Assets.xcassets/Contents.json b/App/UhooiPicBook/Develop/Assets.xcassets/Contents.json similarity index 100% rename from UhooiPicBook/Resources/Assets.xcassets/Contents.json rename to App/UhooiPicBook/Develop/Assets.xcassets/Contents.json diff --git a/App/UhooiPicBook/Production/Assets.xcassets/AppIcon.appiconset/Contents.json b/App/UhooiPicBook/Production/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..a8d49974 --- /dev/null +++ b/App/UhooiPicBook/Production/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,14 @@ +{ + "images" : [ + { + "filename" : "uhooipicbook_AppStore.png", + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-PRODUCTION.appiconset/uhooipicbook_AppStore.png b/App/UhooiPicBook/Production/Assets.xcassets/AppIcon.appiconset/uhooipicbook_AppStore.png similarity index 100% rename from UhooiPicBook/Resources/Assets.xcassets/AppIcon-PRODUCTION.appiconset/uhooipicbook_AppStore.png rename to App/UhooiPicBook/Production/Assets.xcassets/AppIcon.appiconset/uhooipicbook_AppStore.png diff --git a/UhooiPicBookStickers/Stickers.xcassets/Contents.json b/App/UhooiPicBook/Production/Assets.xcassets/Contents.json similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Contents.json rename to App/UhooiPicBook/Production/Assets.xcassets/Contents.json diff --git a/UhooiPicBook/Resources/Base.lproj/LaunchScreen.storyboard b/App/UhooiPicBook/Resources/Base.lproj/LaunchScreen.storyboard similarity index 95% rename from UhooiPicBook/Resources/Base.lproj/LaunchScreen.storyboard rename to App/UhooiPicBook/Resources/Base.lproj/LaunchScreen.storyboard index 0b64f641..cf996030 100644 --- a/UhooiPicBook/Resources/Base.lproj/LaunchScreen.storyboard +++ b/App/UhooiPicBook/Resources/Base.lproj/LaunchScreen.storyboard @@ -1,9 +1,9 @@ - + - + diff --git a/UhooiPicBook/Resources/Info.plist b/App/UhooiPicBook/Resources/Info.plist similarity index 100% rename from UhooiPicBook/Resources/Info.plist rename to App/UhooiPicBook/Resources/Info.plist diff --git a/UhooiPicBook/Settings.bundle/Root.plist b/App/UhooiPicBook/Resources/Settings.bundle/Root.plist similarity index 100% rename from UhooiPicBook/Settings.bundle/Root.plist rename to App/UhooiPicBook/Resources/Settings.bundle/Root.plist diff --git a/UhooiPicBook/Settings.bundle/en.lproj/Root.strings b/App/UhooiPicBook/Resources/Settings.bundle/en.lproj/Root.strings similarity index 100% rename from UhooiPicBook/Settings.bundle/en.lproj/Root.strings rename to App/UhooiPicBook/Resources/Settings.bundle/en.lproj/Root.strings diff --git a/UhooiPicBook/Resources/UhooiPicBook.entitlements b/App/UhooiPicBook/Resources/UhooiPicBook.entitlements similarity index 100% rename from UhooiPicBook/Resources/UhooiPicBook.entitlements rename to App/UhooiPicBook/Resources/UhooiPicBook.entitlements diff --git a/UhooiPicBook/Resources/en.lproj/InfoPlist.strings b/App/UhooiPicBook/Resources/en.lproj/InfoPlist.strings similarity index 100% rename from UhooiPicBook/Resources/en.lproj/InfoPlist.strings rename to App/UhooiPicBook/Resources/en.lproj/InfoPlist.strings diff --git a/UhooiPicBook/Resources/en.lproj/LaunchScreen.strings b/App/UhooiPicBook/Resources/en.lproj/LaunchScreen.strings similarity index 100% rename from UhooiPicBook/Resources/en.lproj/LaunchScreen.strings rename to App/UhooiPicBook/Resources/en.lproj/LaunchScreen.strings diff --git a/UhooiPicBook/Resources/ja.lproj/InfoPlist.strings b/App/UhooiPicBook/Resources/ja.lproj/InfoPlist.strings similarity index 100% rename from UhooiPicBook/Resources/ja.lproj/InfoPlist.strings rename to App/UhooiPicBook/Resources/ja.lproj/InfoPlist.strings diff --git a/UhooiPicBook/SceneDelegate.swift b/App/UhooiPicBook/SceneDelegate.swift similarity index 87% rename from UhooiPicBook/SceneDelegate.swift rename to App/UhooiPicBook/SceneDelegate.swift index 5ca53a25..50d0977d 100644 --- a/UhooiPicBook/SceneDelegate.swift +++ b/App/UhooiPicBook/SceneDelegate.swift @@ -8,7 +8,9 @@ import CoreSpotlight import UIKit +import AppModule +@MainActor class SceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? @@ -22,9 +24,9 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { } let rootViewController = MonsterListRouter.assembleModule() - self.window = UIWindow(windowScene: windowScene) - self.window?.makeKeyAndVisible() - self.window?.rootViewController = UINavigationController(rootViewController: rootViewController) + window = UIWindow(windowScene: windowScene) + window?.makeKeyAndVisible() + window?.rootViewController = UINavigationController(rootViewController: rootViewController) if let userActivity = connectionOptions.userActivities.first { executeUserActivity(userActivity) @@ -65,11 +67,12 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { // MARK: - UserActivity extension SceneDelegate { - func scene(_ scene: UIScene, continue userActivity: NSUserActivity) { executeUserActivity(userActivity) } + // MARK: Other Private Methods + private func executeUserActivity(_ userActivity: NSUserActivity) { switch userActivity.activityType { case CSSearchableItemActionType: @@ -81,15 +84,15 @@ extension SceneDelegate { private func executeSpotlightActivity(_ userActivity: NSUserActivity) { guard let key = userActivity.userInfo?[CSSearchableItemActivityIdentifier] as? String, - let monster = UserDefaultsClient().loadMonster(key: key), - let nav = self.window?.rootViewController as? UINavigationController else { + let monsterEntity = UserDefaultsClient.shared.monster(key: key), + let nav = window?.rootViewController as? UINavigationController else { return } nav.dismiss(animated: false) nav.popToRootViewController(animated: false) - let vc = MonsterDetailRouter.assembleModule(monster: monster) + + let vc = MonsterDetailRouter.assembleModule(monster: MonsterItem(entity: monsterEntity)) nav.pushViewController(vc, animated: true) } - } diff --git a/UhooiPicBookStickers/Info.plist b/App/UhooiPicBookStickers/Info.plist similarity index 100% rename from UhooiPicBookStickers/Info.plist rename to App/UhooiPicBookStickers/Info.plist diff --git a/UhooiPicBookWidgets/Assets.xcassets/Contents.json b/App/UhooiPicBookStickers/Stickers.xcassets/Contents.json similarity index 100% rename from UhooiPicBookWidgets/Assets.xcassets/Contents.json rename to App/UhooiPicBookStickers/Stickers.xcassets/Contents.json diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/Contents.json b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/Contents.json similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/Contents.json rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/Contents.json diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/asainu_sticker_small.sticker/Contents.json b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/asainu_sticker_small.sticker/Contents.json similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/asainu_sticker_small.sticker/Contents.json rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/asainu_sticker_small.sticker/Contents.json diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/asainu_sticker_small.sticker/asainu_sticker_small.png b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/asainu_sticker_small.sticker/asainu_sticker_small.png similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/asainu_sticker_small.sticker/asainu_sticker_small.png rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/asainu_sticker_small.sticker/asainu_sticker_small.png diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/ayausa_sticker_small.sticker/Contents.json b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/ayausa_sticker_small.sticker/Contents.json similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/ayausa_sticker_small.sticker/Contents.json rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/ayausa_sticker_small.sticker/Contents.json diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/ayausa_sticker_small.sticker/ayausa_sticker_small.png b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/ayausa_sticker_small.sticker/ayausa_sticker_small.png similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/ayausa_sticker_small.sticker/ayausa_sticker_small.png rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/ayausa_sticker_small.sticker/ayausa_sticker_small.png diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/bannzaru_sticker_small.sticker/Contents.json b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/bannzaru_sticker_small.sticker/Contents.json similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/bannzaru_sticker_small.sticker/Contents.json rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/bannzaru_sticker_small.sticker/Contents.json diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/bannzaru_sticker_small.sticker/bannzaru_sticker_small.png b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/bannzaru_sticker_small.sticker/bannzaru_sticker_small.png similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/bannzaru_sticker_small.sticker/bannzaru_sticker_small.png rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/bannzaru_sticker_small.sticker/bannzaru_sticker_small.png diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/burakan_sticker_small.sticker/Contents.json b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/burakan_sticker_small.sticker/Contents.json similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/burakan_sticker_small.sticker/Contents.json rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/burakan_sticker_small.sticker/Contents.json diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/burakan_sticker_small.sticker/burakan_sticker_small.png b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/burakan_sticker_small.sticker/burakan_sticker_small.png similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/burakan_sticker_small.sticker/burakan_sticker_small.png rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/burakan_sticker_small.sticker/burakan_sticker_small.png diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/chibird_sticker_small.sticker/Contents.json b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/chibird_sticker_small.sticker/Contents.json similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/chibird_sticker_small.sticker/Contents.json rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/chibird_sticker_small.sticker/Contents.json diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/chibird_sticker_small.sticker/chibird_sticker_small.png b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/chibird_sticker_small.sticker/chibird_sticker_small.png similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/chibird_sticker_small.sticker/chibird_sticker_small.png rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/chibird_sticker_small.sticker/chibird_sticker_small.png diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/chuni_sticker_small.sticker/Contents.json b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/chuni_sticker_small.sticker/Contents.json similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/chuni_sticker_small.sticker/Contents.json rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/chuni_sticker_small.sticker/Contents.json diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/chuni_sticker_small.sticker/chuni_sticker_small.png b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/chuni_sticker_small.sticker/chuni_sticker_small.png similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/chuni_sticker_small.sticker/chuni_sticker_small.png rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/chuni_sticker_small.sticker/chuni_sticker_small.png diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/conycat_sticker_small.sticker/Contents.json b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/conycat_sticker_small.sticker/Contents.json similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/conycat_sticker_small.sticker/Contents.json rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/conycat_sticker_small.sticker/Contents.json diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/conycat_sticker_small.sticker/conycat_sticker_small.png b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/conycat_sticker_small.sticker/conycat_sticker_small.png similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/conycat_sticker_small.sticker/conycat_sticker_small.png rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/conycat_sticker_small.sticker/conycat_sticker_small.png diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/entakun_sticker_small.sticker/Contents.json b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/entakun_sticker_small.sticker/Contents.json similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/entakun_sticker_small.sticker/Contents.json rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/entakun_sticker_small.sticker/Contents.json diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/entakun_sticker_small.sticker/entakun_sticker_small.png b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/entakun_sticker_small.sticker/entakun_sticker_small.png similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/entakun_sticker_small.sticker/entakun_sticker_small.png rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/entakun_sticker_small.sticker/entakun_sticker_small.png diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/firesoul_sticker_small.sticker/Contents.json b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/firesoul_sticker_small.sticker/Contents.json similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/firesoul_sticker_small.sticker/Contents.json rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/firesoul_sticker_small.sticker/Contents.json diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/firesoul_sticker_small.sticker/firesoul_sticker_small.png b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/firesoul_sticker_small.sticker/firesoul_sticker_small.png similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/firesoul_sticker_small.sticker/firesoul_sticker_small.png rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/firesoul_sticker_small.sticker/firesoul_sticker_small.png diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/fktn_sticker_small.sticker/Contents.json b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/fktn_sticker_small.sticker/Contents.json similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/fktn_sticker_small.sticker/Contents.json rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/fktn_sticker_small.sticker/Contents.json diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/fktn_sticker_small.sticker/fktn_sticker_small.png b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/fktn_sticker_small.sticker/fktn_sticker_small.png similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/fktn_sticker_small.sticker/fktn_sticker_small.png rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/fktn_sticker_small.sticker/fktn_sticker_small.png diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/kyuso_sticker_small.sticker/Contents.json b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/kyuso_sticker_small.sticker/Contents.json similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/kyuso_sticker_small.sticker/Contents.json rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/kyuso_sticker_small.sticker/Contents.json diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/kyuso_sticker_small.sticker/kyuso_sticker_small.png b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/kyuso_sticker_small.sticker/kyuso_sticker_small.png similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/kyuso_sticker_small.sticker/kyuso_sticker_small.png rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/kyuso_sticker_small.sticker/kyuso_sticker_small.png diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/mabomagi_sticker_small.sticker/Contents.json b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/mabomagi_sticker_small.sticker/Contents.json similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/mabomagi_sticker_small.sticker/Contents.json rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/mabomagi_sticker_small.sticker/Contents.json diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/mabomagi_sticker_small.sticker/mabomagi_sticker_small.png b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/mabomagi_sticker_small.sticker/mabomagi_sticker_small.png similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/mabomagi_sticker_small.sticker/mabomagi_sticker_small.png rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/mabomagi_sticker_small.sticker/mabomagi_sticker_small.png diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/madora_sticker_small.sticker/Contents.json b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/madora_sticker_small.sticker/Contents.json similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/madora_sticker_small.sticker/Contents.json rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/madora_sticker_small.sticker/Contents.json diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/madora_sticker_small.sticker/madora_sticker_small.png b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/madora_sticker_small.sticker/madora_sticker_small.png similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/madora_sticker_small.sticker/madora_sticker_small.png rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/madora_sticker_small.sticker/madora_sticker_small.png diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/marinyan_sticker_small.sticker/Contents.json b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/marinyan_sticker_small.sticker/Contents.json similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/marinyan_sticker_small.sticker/Contents.json rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/marinyan_sticker_small.sticker/Contents.json diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/marinyan_sticker_small.sticker/marinyan_sticker_small.png b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/marinyan_sticker_small.sticker/marinyan_sticker_small.png similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/marinyan_sticker_small.sticker/marinyan_sticker_small.png rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/marinyan_sticker_small.sticker/marinyan_sticker_small.png diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/meikui_sticker_small.sticker/Contents.json b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/meikui_sticker_small.sticker/Contents.json similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/meikui_sticker_small.sticker/Contents.json rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/meikui_sticker_small.sticker/Contents.json diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/meikui_sticker_small.sticker/meikui_sticker_small.png b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/meikui_sticker_small.sticker/meikui_sticker_small.png similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/meikui_sticker_small.sticker/meikui_sticker_small.png rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/meikui_sticker_small.sticker/meikui_sticker_small.png diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/meriusa_sticker_small.sticker/Contents.json b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/meriusa_sticker_small.sticker/Contents.json similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/meriusa_sticker_small.sticker/Contents.json rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/meriusa_sticker_small.sticker/Contents.json diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/meriusa_sticker_small.sticker/meriusa_sticker_small.png b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/meriusa_sticker_small.sticker/meriusa_sticker_small.png similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/meriusa_sticker_small.sticker/meriusa_sticker_small.png rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/meriusa_sticker_small.sticker/meriusa_sticker_small.png diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/mijara_sticker_small.sticker/Contents.json b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/mijara_sticker_small.sticker/Contents.json similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/mijara_sticker_small.sticker/Contents.json rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/mijara_sticker_small.sticker/Contents.json diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/mijara_sticker_small.sticker/mijara_sticker_small.png b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/mijara_sticker_small.sticker/mijara_sticker_small.png similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/mijara_sticker_small.sticker/mijara_sticker_small.png rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/mijara_sticker_small.sticker/mijara_sticker_small.png diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/mikkaneko_sticker_small.sticker/Contents.json b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/mikkaneko_sticker_small.sticker/Contents.json similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/mikkaneko_sticker_small.sticker/Contents.json rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/mikkaneko_sticker_small.sticker/Contents.json diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/mikkaneko_sticker_small.sticker/mikkaneko_sticker_small.png b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/mikkaneko_sticker_small.sticker/mikkaneko_sticker_small.png similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/mikkaneko_sticker_small.sticker/mikkaneko_sticker_small.png rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/mikkaneko_sticker_small.sticker/mikkaneko_sticker_small.png diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/moepin_sticker_small.sticker/Contents.json b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/moepin_sticker_small.sticker/Contents.json similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/moepin_sticker_small.sticker/Contents.json rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/moepin_sticker_small.sticker/Contents.json diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/moepin_sticker_small.sticker/moepin_sticker_small.png b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/moepin_sticker_small.sticker/moepin_sticker_small.png similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/moepin_sticker_small.sticker/moepin_sticker_small.png rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/moepin_sticker_small.sticker/moepin_sticker_small.png diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/monkuma_sticker_small.sticker/Contents.json b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/monkuma_sticker_small.sticker/Contents.json similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/monkuma_sticker_small.sticker/Contents.json rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/monkuma_sticker_small.sticker/Contents.json diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/monkuma_sticker_small.sticker/monkuma_sticker_small.png b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/monkuma_sticker_small.sticker/monkuma_sticker_small.png similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/monkuma_sticker_small.sticker/monkuma_sticker_small.png rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/monkuma_sticker_small.sticker/monkuma_sticker_small.png diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/motokuma_sticker_small.sticker/Contents.json b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/motokuma_sticker_small.sticker/Contents.json similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/motokuma_sticker_small.sticker/Contents.json rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/motokuma_sticker_small.sticker/Contents.json diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/motokuma_sticker_small.sticker/motokuma_sticker_small.png b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/motokuma_sticker_small.sticker/motokuma_sticker_small.png similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/motokuma_sticker_small.sticker/motokuma_sticker_small.png rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/motokuma_sticker_small.sticker/motokuma_sticker_small.png diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/noalf_sticker_small.sticker/Contents.json b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/noalf_sticker_small.sticker/Contents.json similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/noalf_sticker_small.sticker/Contents.json rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/noalf_sticker_small.sticker/Contents.json diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/noalf_sticker_small.sticker/noalf_sticker_small.png b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/noalf_sticker_small.sticker/noalf_sticker_small.png similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/noalf_sticker_small.sticker/noalf_sticker_small.png rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/noalf_sticker_small.sticker/noalf_sticker_small.png diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/nopetsune_sticker_small.sticker/Contents.json b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/nopetsune_sticker_small.sticker/Contents.json similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/nopetsune_sticker_small.sticker/Contents.json rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/nopetsune_sticker_small.sticker/Contents.json diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/nopetsune_sticker_small.sticker/nopetsune_sticker_small.png b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/nopetsune_sticker_small.sticker/nopetsune_sticker_small.png similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/nopetsune_sticker_small.sticker/nopetsune_sticker_small.png rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/nopetsune_sticker_small.sticker/nopetsune_sticker_small.png diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/reijin_sticker_small.sticker/Contents.json b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/reijin_sticker_small.sticker/Contents.json similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/reijin_sticker_small.sticker/Contents.json rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/reijin_sticker_small.sticker/Contents.json diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/reijin_sticker_small.sticker/reijin_sticker_small.png b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/reijin_sticker_small.sticker/reijin_sticker_small.png similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/reijin_sticker_small.sticker/reijin_sticker_small.png rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/reijin_sticker_small.sticker/reijin_sticker_small.png diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/renman_sticker_small.sticker/Contents.json b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/renman_sticker_small.sticker/Contents.json similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/renman_sticker_small.sticker/Contents.json rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/renman_sticker_small.sticker/Contents.json diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/renman_sticker_small.sticker/renman_sticker_small.png b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/renman_sticker_small.sticker/renman_sticker_small.png similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/renman_sticker_small.sticker/renman_sticker_small.png rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/renman_sticker_small.sticker/renman_sticker_small.png diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/rokukage_sticker_small.sticker/Contents.json b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/rokukage_sticker_small.sticker/Contents.json similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/rokukage_sticker_small.sticker/Contents.json rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/rokukage_sticker_small.sticker/Contents.json diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/rokukage_sticker_small.sticker/rokukage_sticker_small.png b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/rokukage_sticker_small.sticker/rokukage_sticker_small.png similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/rokukage_sticker_small.sticker/rokukage_sticker_small.png rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/rokukage_sticker_small.sticker/rokukage_sticker_small.png diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/samender_sticker_small.sticker/Contents.json b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/samender_sticker_small.sticker/Contents.json similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/samender_sticker_small.sticker/Contents.json rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/samender_sticker_small.sticker/Contents.json diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/samender_sticker_small.sticker/samender_sticker_small.png b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/samender_sticker_small.sticker/samender_sticker_small.png similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/samender_sticker_small.sticker/samender_sticker_small.png rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/samender_sticker_small.sticker/samender_sticker_small.png diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/tamako_sticker_small.sticker/Contents.json b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/tamako_sticker_small.sticker/Contents.json similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/tamako_sticker_small.sticker/Contents.json rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/tamako_sticker_small.sticker/Contents.json diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/tamako_sticker_small.sticker/tamako_sticker_small.png b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/tamako_sticker_small.sticker/tamako_sticker_small.png similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/tamako_sticker_small.sticker/tamako_sticker_small.png rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/tamako_sticker_small.sticker/tamako_sticker_small.png diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/tetsureon_sticker_small.sticker/Contents.json b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/tetsureon_sticker_small.sticker/Contents.json similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/tetsureon_sticker_small.sticker/Contents.json rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/tetsureon_sticker_small.sticker/Contents.json diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/tetsureon_sticker_small.sticker/tetsureon_sticker_small.png b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/tetsureon_sticker_small.sticker/tetsureon_sticker_small.png similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/tetsureon_sticker_small.sticker/tetsureon_sticker_small.png rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/tetsureon_sticker_small.sticker/tetsureon_sticker_small.png diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/toge-n_sticker_small.sticker/Contents.json b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/toge-n_sticker_small.sticker/Contents.json similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/toge-n_sticker_small.sticker/Contents.json rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/toge-n_sticker_small.sticker/Contents.json diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/toge-n_sticker_small.sticker/toge-n_sticker_small.png b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/toge-n_sticker_small.sticker/toge-n_sticker_small.png similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/toge-n_sticker_small.sticker/toge-n_sticker_small.png rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/toge-n_sticker_small.sticker/toge-n_sticker_small.png diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/totokuma_sticker_small.sticker/Contents.json b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/totokuma_sticker_small.sticker/Contents.json similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/totokuma_sticker_small.sticker/Contents.json rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/totokuma_sticker_small.sticker/Contents.json diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/totokuma_sticker_small.sticker/totokuma_sticker_small.png b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/totokuma_sticker_small.sticker/totokuma_sticker_small.png similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/totokuma_sticker_small.sticker/totokuma_sticker_small.png rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/totokuma_sticker_small.sticker/totokuma_sticker_small.png diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/uhooi_sticker_small.sticker/Contents.json b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/uhooi_sticker_small.sticker/Contents.json similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/uhooi_sticker_small.sticker/Contents.json rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/uhooi_sticker_small.sticker/Contents.json diff --git a/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/uhooi_sticker_small.sticker/uhooi_sticker_small.png b/App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/uhooi_sticker_small.sticker/uhooi_sticker_small.png similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/uhooi_sticker_small.sticker/uhooi_sticker_small.png rename to App/UhooiPicBookStickers/Stickers.xcassets/Sticker Pack.stickerpack/uhooi_sticker_small.sticker/uhooi_sticker_small.png diff --git a/UhooiPicBookStickers/Stickers.xcassets/iMessage App Icon.stickersiconset/Contents.json b/App/UhooiPicBookStickers/Stickers.xcassets/iMessage App Icon.stickersiconset/Contents.json similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/iMessage App Icon.stickersiconset/Contents.json rename to App/UhooiPicBookStickers/Stickers.xcassets/iMessage App Icon.stickersiconset/Contents.json diff --git a/UhooiPicBookStickers/Stickers.xcassets/iMessage App Icon.stickersiconset/uhooipicbook_AppStore.png b/App/UhooiPicBookStickers/Stickers.xcassets/iMessage App Icon.stickersiconset/uhooipicbook_AppStore.png similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/iMessage App Icon.stickersiconset/uhooipicbook_AppStore.png rename to App/UhooiPicBookStickers/Stickers.xcassets/iMessage App Icon.stickersiconset/uhooipicbook_AppStore.png diff --git a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-PRODUCTION.appiconset/uhooipicbook_iPad_Settings@2x.png b/App/UhooiPicBookStickers/Stickers.xcassets/iMessage App Icon.stickersiconset/uhooipicbook_iPad_Settings@2x.png similarity index 100% rename from UhooiPicBook/Resources/Assets.xcassets/AppIcon-PRODUCTION.appiconset/uhooipicbook_iPad_Settings@2x.png rename to App/UhooiPicBookStickers/Stickers.xcassets/iMessage App Icon.stickersiconset/uhooipicbook_iPad_Settings@2x.png diff --git a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-PRODUCTION.appiconset/uhooipicbook_iPhone_Settings@2x.png b/App/UhooiPicBookStickers/Stickers.xcassets/iMessage App Icon.stickersiconset/uhooipicbook_iPhone_Settings@2x.png similarity index 100% rename from UhooiPicBook/Resources/Assets.xcassets/AppIcon-PRODUCTION.appiconset/uhooipicbook_iPhone_Settings@2x.png rename to App/UhooiPicBookStickers/Stickers.xcassets/iMessage App Icon.stickersiconset/uhooipicbook_iPhone_Settings@2x.png diff --git a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-PRODUCTION.appiconset/uhooipicbook_iPhone_Settings@3x.png b/App/UhooiPicBookStickers/Stickers.xcassets/iMessage App Icon.stickersiconset/uhooipicbook_iPhone_Settings@3x.png similarity index 100% rename from UhooiPicBook/Resources/Assets.xcassets/AppIcon-PRODUCTION.appiconset/uhooipicbook_iPhone_Settings@3x.png rename to App/UhooiPicBookStickers/Stickers.xcassets/iMessage App Icon.stickersiconset/uhooipicbook_iPhone_Settings@3x.png diff --git a/UhooiPicBookStickers/Stickers.xcassets/iMessage App Icon.stickersiconset/uhooipicbook_messages@2x.png b/App/UhooiPicBookStickers/Stickers.xcassets/iMessage App Icon.stickersiconset/uhooipicbook_messages@2x.png similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/iMessage App Icon.stickersiconset/uhooipicbook_messages@2x.png rename to App/UhooiPicBookStickers/Stickers.xcassets/iMessage App Icon.stickersiconset/uhooipicbook_messages@2x.png diff --git a/UhooiPicBookStickers/Stickers.xcassets/iMessage App Icon.stickersiconset/uhooipicbook_messages@3x.png b/App/UhooiPicBookStickers/Stickers.xcassets/iMessage App Icon.stickersiconset/uhooipicbook_messages@3x.png similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/iMessage App Icon.stickersiconset/uhooipicbook_messages@3x.png rename to App/UhooiPicBookStickers/Stickers.xcassets/iMessage App Icon.stickersiconset/uhooipicbook_messages@3x.png diff --git a/UhooiPicBookStickers/Stickers.xcassets/iMessage App Icon.stickersiconset/uhooipicbook_messages_2@2x.png b/App/UhooiPicBookStickers/Stickers.xcassets/iMessage App Icon.stickersiconset/uhooipicbook_messages_2@2x.png similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/iMessage App Icon.stickersiconset/uhooipicbook_messages_2@2x.png rename to App/UhooiPicBookStickers/Stickers.xcassets/iMessage App Icon.stickersiconset/uhooipicbook_messages_2@2x.png diff --git a/UhooiPicBookStickers/Stickers.xcassets/iMessage App Icon.stickersiconset/uhooipicbook_messages_2@3x.png b/App/UhooiPicBookStickers/Stickers.xcassets/iMessage App Icon.stickersiconset/uhooipicbook_messages_2@3x.png similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/iMessage App Icon.stickersiconset/uhooipicbook_messages_2@3x.png rename to App/UhooiPicBookStickers/Stickers.xcassets/iMessage App Icon.stickersiconset/uhooipicbook_messages_2@3x.png diff --git a/UhooiPicBookStickers/Stickers.xcassets/iMessage App Icon.stickersiconset/uhooipicbook_messages_app_store.png b/App/UhooiPicBookStickers/Stickers.xcassets/iMessage App Icon.stickersiconset/uhooipicbook_messages_app_store.png similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/iMessage App Icon.stickersiconset/uhooipicbook_messages_app_store.png rename to App/UhooiPicBookStickers/Stickers.xcassets/iMessage App Icon.stickersiconset/uhooipicbook_messages_app_store.png diff --git a/UhooiPicBookStickers/Stickers.xcassets/iMessage App Icon.stickersiconset/uhooipicbook_messages_ipad@2x.png b/App/UhooiPicBookStickers/Stickers.xcassets/iMessage App Icon.stickersiconset/uhooipicbook_messages_ipad@2x.png similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/iMessage App Icon.stickersiconset/uhooipicbook_messages_ipad@2x.png rename to App/UhooiPicBookStickers/Stickers.xcassets/iMessage App Icon.stickersiconset/uhooipicbook_messages_ipad@2x.png diff --git a/UhooiPicBookStickers/Stickers.xcassets/iMessage App Icon.stickersiconset/uhooipicbook_messages_ipad_pro@2x.png b/App/UhooiPicBookStickers/Stickers.xcassets/iMessage App Icon.stickersiconset/uhooipicbook_messages_ipad_pro@2x.png similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/iMessage App Icon.stickersiconset/uhooipicbook_messages_ipad_pro@2x.png rename to App/UhooiPicBookStickers/Stickers.xcassets/iMessage App Icon.stickersiconset/uhooipicbook_messages_ipad_pro@2x.png diff --git a/UhooiPicBookStickers/Stickers.xcassets/iMessage App Icon.stickersiconset/uhooipicbook_messages_iphone@2x.png b/App/UhooiPicBookStickers/Stickers.xcassets/iMessage App Icon.stickersiconset/uhooipicbook_messages_iphone@2x.png similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/iMessage App Icon.stickersiconset/uhooipicbook_messages_iphone@2x.png rename to App/UhooiPicBookStickers/Stickers.xcassets/iMessage App Icon.stickersiconset/uhooipicbook_messages_iphone@2x.png diff --git a/UhooiPicBookStickers/Stickers.xcassets/iMessage App Icon.stickersiconset/uhooipicbook_messages_iphone@3x.png b/App/UhooiPicBookStickers/Stickers.xcassets/iMessage App Icon.stickersiconset/uhooipicbook_messages_iphone@3x.png similarity index 100% rename from UhooiPicBookStickers/Stickers.xcassets/iMessage App Icon.stickersiconset/uhooipicbook_messages_iphone@3x.png rename to App/UhooiPicBookStickers/Stickers.xcassets/iMessage App Icon.stickersiconset/uhooipicbook_messages_iphone@3x.png diff --git a/UhooiPicBookTests/Extensions/Foundation/BundleStringTests.swift b/App/UhooiPicBookTests/Extensions/Foundation/BundleStringTests.swift similarity index 89% rename from UhooiPicBookTests/Extensions/Foundation/BundleStringTests.swift rename to App/UhooiPicBookTests/Extensions/Foundation/BundleStringTests.swift index e2968a62..834448d6 100644 --- a/UhooiPicBookTests/Extensions/Foundation/BundleStringTests.swift +++ b/App/UhooiPicBookTests/Extensions/Foundation/BundleStringTests.swift @@ -6,7 +6,7 @@ // import XCTest -@testable import UhooiPicBook +@testable import AppModule final class BundleStringTests: XCTestCase { @@ -42,13 +42,12 @@ final class BundleStringTests: XCTestCase { // MARK: version func test_bundle_version() { - XCTAssertEqual(Bundle.main.version, "1.5.0") + XCTAssertEqual(Bundle.main.version, "1.6.0") } // MARK: build func test_bundle_build() { - XCTAssertEqual(Bundle.main.build, "16") + XCTAssertEqual(Bundle.main.build, "17") } - } diff --git a/UhooiPicBookTests/Info.plist b/App/UhooiPicBookTests/Info.plist similarity index 100% rename from UhooiPicBookTests/Info.plist rename to App/UhooiPicBookTests/Info.plist diff --git a/UhooiPicBookUITests/Info.plist b/App/UhooiPicBookUITests/Info.plist similarity index 100% rename from UhooiPicBookUITests/Info.plist rename to App/UhooiPicBookUITests/Info.plist diff --git a/UhooiPicBookUITests/PageProtocol.swift b/App/UhooiPicBookUITests/PageProtocol.swift similarity index 100% rename from UhooiPicBookUITests/PageProtocol.swift rename to App/UhooiPicBookUITests/PageProtocol.swift diff --git a/UhooiPicBookUITests/Pages/ActivityPage.swift b/App/UhooiPicBookUITests/Pages/ActivityPage.swift similarity index 100% rename from UhooiPicBookUITests/Pages/ActivityPage.swift rename to App/UhooiPicBookUITests/Pages/ActivityPage.swift diff --git a/UhooiPicBookUITests/Pages/ImagePopupPage.swift b/App/UhooiPicBookUITests/Pages/ImagePopupPage.swift similarity index 100% rename from UhooiPicBookUITests/Pages/ImagePopupPage.swift rename to App/UhooiPicBookUITests/Pages/ImagePopupPage.swift diff --git a/UhooiPicBookUITests/Pages/MonsterDetailPage.swift b/App/UhooiPicBookUITests/Pages/MonsterDetailPage.swift similarity index 100% rename from UhooiPicBookUITests/Pages/MonsterDetailPage.swift rename to App/UhooiPicBookUITests/Pages/MonsterDetailPage.swift diff --git a/UhooiPicBookUITests/Pages/MonsterListPage.swift b/App/UhooiPicBookUITests/Pages/MonsterListPage.swift similarity index 100% rename from UhooiPicBookUITests/Pages/MonsterListPage.swift rename to App/UhooiPicBookUITests/Pages/MonsterListPage.swift diff --git a/UhooiPicBookUITests/TestCases/UhooiPicBookUITests.swift b/App/UhooiPicBookUITests/TestCases/UhooiPicBookUITests.swift similarity index 100% rename from UhooiPicBookUITests/TestCases/UhooiPicBookUITests.swift rename to App/UhooiPicBookUITests/TestCases/UhooiPicBookUITests.swift diff --git a/UhooiPicBookUITests/XCUIElement+Ex.swift b/App/UhooiPicBookUITests/XCUIElement+Ex.swift similarity index 97% rename from UhooiPicBookUITests/XCUIElement+Ex.swift rename to App/UhooiPicBookUITests/XCUIElement+Ex.swift index 0a22b888..1d89cbdd 100644 --- a/UhooiPicBookUITests/XCUIElement+Ex.swift +++ b/App/UhooiPicBookUITests/XCUIElement+Ex.swift @@ -8,10 +8,8 @@ import XCTest extension XCUIElement { - func inputText(_ text: String) { tap() typeText(text) } - } diff --git a/UhooiPicBookWidgets/Info.plist b/App/UhooiPicBookWidgets/Info.plist similarity index 100% rename from UhooiPicBookWidgets/Info.plist rename to App/UhooiPicBookWidgets/Info.plist diff --git a/App/UhooiPicBookWidgets/Monster/MonsterConfigurableWidget.swift b/App/UhooiPicBookWidgets/Monster/MonsterConfigurableWidget.swift new file mode 100644 index 00000000..fdd58fec --- /dev/null +++ b/App/UhooiPicBookWidgets/Monster/MonsterConfigurableWidget.swift @@ -0,0 +1,61 @@ +// +// MonsterConfigurableWidget.swift +// UhooiPicBookWidgets +// +// Created by Takehito Koshimizu on 2020/11/14. +// + +import WidgetKit +import SwiftUI +import MonsterWidgets +import MonstersRepository +import ImageLoader + +private struct MonsterProvider { + typealias Entry = MonsterEntry + typealias Intent = SelectMonsterIntent +} + +struct MonsterConfigurableWidget: Widget { + var body: some WidgetConfiguration { + IntentConfiguration( + kind: "MonsterConfigurable", + intent: SelectMonsterIntent.self, + provider: MonsterProvider() + ) { entry in + MonsterEntryView(entry: entry) + } + .configurationDisplayName(R.LocalizedString.configurationDisplayName) + .description(R.LocalizedString.configurableDescription) + .supportedFamilies([.systemSmall, .systemMedium]) + } +} + +extension MonsterProvider: IntentTimelineProvider { + func placeholder(in context: Context) -> Entry { + .placeholder() + } + + func getSnapshot(for intent: Intent, in context: Context, completion: @escaping (Entry) -> Void) { + completion(.placeholder()) + } + + func getTimeline(for intent: Intent, in context: Context, completion: @escaping (Timeline) -> Void) { + Task { + let entry = await entry(dto: intent.monster?.dto()) + let entries = [entry ?? .placeholder()] + completion(Timeline(entries: entries, policy: .never)) + } + } + + private func entry(dto: MonsterDTO?) async -> Entry? { + guard let dto, + let iconURL = URL(string: dto.iconURLString), + let icon = await UIImage.create(with: iconURL) + else { + return nil + } + let description = dto.description.replacingOccurrences(of: "\\n", with: "\n") + return Entry(date: Date(), name: dto.name, description: description, icon: icon) + } +} diff --git a/UhooiPicBookWidgets/UhooiPicBookWidgets.swift b/App/UhooiPicBookWidgets/UhooiPicBookWidgets.swift similarity index 92% rename from UhooiPicBookWidgets/UhooiPicBookWidgets.swift rename to App/UhooiPicBookWidgets/UhooiPicBookWidgets.swift index 5d52ff02..bf669174 100644 --- a/UhooiPicBookWidgets/UhooiPicBookWidgets.swift +++ b/App/UhooiPicBookWidgets/UhooiPicBookWidgets.swift @@ -6,6 +6,7 @@ // import SwiftUI +import MonsterWidgets @main struct UhooiPicBookWidgets: WidgetBundle { diff --git a/UhooiPicBookWidgetsConfigurableIntent/Info.plist b/App/UhooiPicBookWidgetsConfigurableIntent/Info.plist similarity index 100% rename from UhooiPicBookWidgetsConfigurableIntent/Info.plist rename to App/UhooiPicBookWidgetsConfigurableIntent/Info.plist diff --git a/UhooiPicBookWidgetsConfigurableIntent/IntentHandler.swift b/App/UhooiPicBookWidgetsConfigurableIntent/IntentHandler.swift similarity index 70% rename from UhooiPicBookWidgetsConfigurableIntent/IntentHandler.swift rename to App/UhooiPicBookWidgetsConfigurableIntent/IntentHandler.swift index f0474817..d6758ad2 100644 --- a/UhooiPicBookWidgetsConfigurableIntent/IntentHandler.swift +++ b/App/UhooiPicBookWidgetsConfigurableIntent/IntentHandler.swift @@ -6,29 +6,30 @@ // import Intents -import FirebaseCore +import FirebaseSetup +import MonstersRepository final class IntentHandler: INExtension, SelectMonsterIntentHandling { - private let repository: MonstersRepository + private let repository: any MonstersRepository override init() { - FirebaseApp.configure() - self.repository = MonstersFirebaseClient() + FirebaseSetup.configure() + self.repository = MonstersFirestoreClient.shared super.init() } func provideMonsterOptionsCollection( for intent: SelectMonsterIntent, with completion: @escaping (INObjectCollection?, Error?) -> Void) { - self.repository.loadMonsters { result in - switch result { - case let .success(monsters): + Task { + do { + let monsters = try await repository.monsters() let monsterIntentObject = monsters .sorted { $0.order < $1.order } .map(MonsterIntentObject.init) completion(INObjectCollection(items: monsterIntentObject), nil) - case let .failure(error): + } catch { completion(nil, error) } } diff --git a/Docs/Download_on_the_App_Store_Badge_US-UK_RGB_blk_092917.svg b/Docs/Download_on_the_App_Store_Badge_US-UK_RGB_blk_092917.svg deleted file mode 100755 index 072b425a..00000000 --- a/Docs/Download_on_the_App_Store_Badge_US-UK_RGB_blk_092917.svg +++ /dev/null @@ -1,46 +0,0 @@ - - Download_on_the_App_Store_Badge_US-UK_RGB_blk_4SVG_092917 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Docs/Screenshots/iPhone11ProMax/iOS14_3/Dark/ImagePopup_English.png b/Docs/Screenshots/iPhone11ProMax/iOS14_3/Dark/ImagePopup_English.png deleted file mode 100644 index aa8c6bf8..00000000 Binary files a/Docs/Screenshots/iPhone11ProMax/iOS14_3/Dark/ImagePopup_English.png and /dev/null differ diff --git a/Docs/Screenshots/iPhone11ProMax/iOS14_3/Dark/MenuOpenedInMonsterList_English.png b/Docs/Screenshots/iPhone11ProMax/iOS14_3/Dark/MenuOpenedInMonsterList_English.png deleted file mode 100644 index 862990ad..00000000 Binary files a/Docs/Screenshots/iPhone11ProMax/iOS14_3/Dark/MenuOpenedInMonsterList_English.png and /dev/null differ diff --git a/Docs/Screenshots/iPhone11ProMax/iOS14_3/Dark/MonsterDetail_English.png b/Docs/Screenshots/iPhone11ProMax/iOS14_3/Dark/MonsterDetail_English.png deleted file mode 100644 index ed292ddb..00000000 Binary files a/Docs/Screenshots/iPhone11ProMax/iOS14_3/Dark/MonsterDetail_English.png and /dev/null differ diff --git a/Docs/Screenshots/iPhone11ProMax/iOS14_3/Dark/MonsterList.png b/Docs/Screenshots/iPhone11ProMax/iOS14_3/Dark/MonsterList.png deleted file mode 100644 index 3e54bfb0..00000000 Binary files a/Docs/Screenshots/iPhone11ProMax/iOS14_3/Dark/MonsterList.png and /dev/null differ diff --git a/Docs/Screenshots/iPhone11ProMax/iOS14_3/Light/ImagePopup_English.png b/Docs/Screenshots/iPhone11ProMax/iOS14_3/Light/ImagePopup_English.png deleted file mode 100644 index de5f6462..00000000 Binary files a/Docs/Screenshots/iPhone11ProMax/iOS14_3/Light/ImagePopup_English.png and /dev/null differ diff --git a/Docs/Screenshots/iPhone11ProMax/iOS14_3/Light/MenuOpenedInMonsterList_English.png b/Docs/Screenshots/iPhone11ProMax/iOS14_3/Light/MenuOpenedInMonsterList_English.png deleted file mode 100644 index e13254e6..00000000 Binary files a/Docs/Screenshots/iPhone11ProMax/iOS14_3/Light/MenuOpenedInMonsterList_English.png and /dev/null differ diff --git a/Docs/Screenshots/iPhone11ProMax/iOS14_3/Light/MonsterDetail_English.png b/Docs/Screenshots/iPhone11ProMax/iOS14_3/Light/MonsterDetail_English.png deleted file mode 100644 index 7f6db6b3..00000000 Binary files a/Docs/Screenshots/iPhone11ProMax/iOS14_3/Light/MonsterDetail_English.png and /dev/null differ diff --git a/Docs/Screenshots/iPhone11ProMax/iOS14_3/Light/MonsterList.png b/Docs/Screenshots/iPhone11ProMax/iOS14_3/Light/MonsterList.png deleted file mode 100644 index f8179b0c..00000000 Binary files a/Docs/Screenshots/iPhone11ProMax/iOS14_3/Light/MonsterList.png and /dev/null differ diff --git a/Docs/Screenshots/iPhone11ProMax/iOS15_2/Dark/ImagePopup_English.png b/Docs/Screenshots/iPhone11ProMax/iOS15_2/Dark/ImagePopup_English.png new file mode 100644 index 00000000..353bf59e Binary files /dev/null and b/Docs/Screenshots/iPhone11ProMax/iOS15_2/Dark/ImagePopup_English.png differ diff --git a/Docs/Screenshots/iPhone11ProMax/iOS15_2/Dark/MenuOpenedInMonsterList_English.png b/Docs/Screenshots/iPhone11ProMax/iOS15_2/Dark/MenuOpenedInMonsterList_English.png new file mode 100644 index 00000000..5b107114 Binary files /dev/null and b/Docs/Screenshots/iPhone11ProMax/iOS15_2/Dark/MenuOpenedInMonsterList_English.png differ diff --git a/Docs/Screenshots/iPhone11ProMax/iOS15_2/Dark/MonsterDetail_English.png b/Docs/Screenshots/iPhone11ProMax/iOS15_2/Dark/MonsterDetail_English.png new file mode 100644 index 00000000..02b42a9a Binary files /dev/null and b/Docs/Screenshots/iPhone11ProMax/iOS15_2/Dark/MonsterDetail_English.png differ diff --git a/Docs/Screenshots/iPhone11ProMax/iOS15_2/Dark/MonsterList.png b/Docs/Screenshots/iPhone11ProMax/iOS15_2/Dark/MonsterList.png new file mode 100644 index 00000000..1a7de4fe Binary files /dev/null and b/Docs/Screenshots/iPhone11ProMax/iOS15_2/Dark/MonsterList.png differ diff --git a/Docs/Screenshots/iPhone11ProMax/iOS15_2/Light/ImagePopup_English.png b/Docs/Screenshots/iPhone11ProMax/iOS15_2/Light/ImagePopup_English.png new file mode 100644 index 00000000..744d4c51 Binary files /dev/null and b/Docs/Screenshots/iPhone11ProMax/iOS15_2/Light/ImagePopup_English.png differ diff --git a/Docs/Screenshots/iPhone11ProMax/iOS15_2/Light/MenuOpenedInMonsterList_English.png b/Docs/Screenshots/iPhone11ProMax/iOS15_2/Light/MenuOpenedInMonsterList_English.png new file mode 100644 index 00000000..69d16c97 Binary files /dev/null and b/Docs/Screenshots/iPhone11ProMax/iOS15_2/Light/MenuOpenedInMonsterList_English.png differ diff --git a/Docs/Screenshots/iPhone11ProMax/iOS15_2/Light/MonsterDetail_English.png b/Docs/Screenshots/iPhone11ProMax/iOS15_2/Light/MonsterDetail_English.png new file mode 100644 index 00000000..0d8bd007 Binary files /dev/null and b/Docs/Screenshots/iPhone11ProMax/iOS15_2/Light/MonsterDetail_English.png differ diff --git a/Docs/Screenshots/iPhone11ProMax/iOS15_2/Light/MonsterList.png b/Docs/Screenshots/iPhone11ProMax/iOS15_2/Light/MonsterList.png new file mode 100644 index 00000000..2a6dc28c Binary files /dev/null and b/Docs/Screenshots/iPhone11ProMax/iOS15_2/Light/MonsterList.png differ diff --git a/Gemfile b/Gemfile deleted file mode 100644 index 0ff8912a..00000000 --- a/Gemfile +++ /dev/null @@ -1,9 +0,0 @@ -# frozen_string_literal: true - -source "https://rubygems.org" - -git_source(:github) {|repo_name| "https://github.com/#{repo_name}" } - -gem "generamba" -gem "slather" - diff --git a/Gemfile.lock b/Gemfile.lock deleted file mode 100644 index 4b7f4804..00000000 --- a/Gemfile.lock +++ /dev/null @@ -1,85 +0,0 @@ -GEM - remote: https://rubygems.org/ - specs: - CFPropertyList (3.0.3) - activesupport (5.2.5) - concurrent-ruby (~> 1.0, >= 1.0.2) - i18n (>= 0.7, < 2) - minitest (~> 5.1) - tzinfo (~> 1.1) - addressable (2.7.0) - public_suffix (>= 2.0.2, < 5.0) - algoliasearch (1.27.5) - httpclient (~> 2.8, >= 2.8.3) - json (>= 1.5.1) - atomos (0.1.3) - claide (1.0.3) - clamp (1.3.2) - cocoapods-core (1.10.1) - activesupport (> 5.0, < 6) - addressable (~> 2.6) - algoliasearch (~> 1.0) - concurrent-ruby (~> 1.1) - fuzzy_match (~> 2.0.4) - nap (~> 1.0) - netrc (~> 0.11) - public_suffix - typhoeus (~> 1.0) - colored2 (3.1.2) - concurrent-ruby (1.1.8) - ethon (0.12.0) - ffi (>= 1.3.0) - ffi (1.15.0) - fuzzy_match (2.0.4) - generamba (1.5.0) - cocoapods-core (>= 1.4.0, < 2.0.0) - git (= 1.2.9.1) - liquid (= 4.0.0) - terminal-table (= 1.4.5) - thor (= 0.19.1) - xcodeproj (>= 1.5.0, < 2.0.0) - git (1.2.9.1) - httpclient (2.8.3) - i18n (1.8.9) - concurrent-ruby (~> 1.0) - json (2.5.1) - liquid (4.0.0) - mini_portile2 (2.5.0) - minitest (5.14.4) - nanaimo (0.3.0) - nap (1.1.0) - netrc (0.11.0) - nokogiri (1.11.2) - mini_portile2 (~> 2.5.0) - racc (~> 1.4) - public_suffix (4.0.6) - racc (1.5.2) - slather (2.7.0) - CFPropertyList (>= 2.2, < 4) - activesupport - clamp (~> 1.3) - nokogiri (~> 1.11) - xcodeproj (~> 1.7) - terminal-table (1.4.5) - thor (0.19.1) - thread_safe (0.3.6) - typhoeus (1.4.0) - ethon (>= 0.9.0) - tzinfo (1.2.9) - thread_safe (~> 0.1) - xcodeproj (1.19.0) - CFPropertyList (>= 2.3.3, < 4.0) - atomos (~> 0.1.3) - claide (>= 1.0.2, < 2.0) - colored2 (~> 3.1) - nanaimo (~> 0.3.0) - -PLATFORMS - ruby - -DEPENDENCIES - generamba - slather - -BUNDLED WITH - 2.1.4 diff --git a/Makefile b/Makefile index 081cf7a4..7c5200b7 100644 --- a/Makefile +++ b/Makefile @@ -1,33 +1,27 @@ # Variables PRODUCT_NAME := UhooiPicBook -PROJECT_NAME := ${PRODUCT_NAME}.xcodeproj -SCHEME_NAME := ${PRODUCT_NAME} +WORKSPACE_NAME := ${PRODUCT_NAME}.xcworkspace UI_TESTS_TARGET_NAME := ${PRODUCT_NAME}UITests TEST_SDK := iphonesimulator TEST_CONFIGURATION := Debug TEST_PLATFORM := iOS Simulator -TEST_DEVICE ?= iPhone 12 Pro Max -TEST_OS ?= 15.0 +TEST_DEVICE ?= iPhone 14 Pro Max +TEST_OS ?= 16.1 TEST_DESTINATION := 'platform=${TEST_PLATFORM},name=${TEST_DEVICE},OS=${TEST_OS}' -COVERAGE_OUTPUT := html_report -XCODEBUILD_BUILD_LOG_NAME := xcodebuild_build.log -XCODEBUILD_TEST_LOG_NAME := xcodebuild_test.log +DEVELOP_PROJECT_NAME := Develop +PRODUCTION_PROJECT_NAME := Production -DEVELOP_ENVIRONMENT := DEVELOP -PRODUCTION_ENVIRONMENT := PRODUCTION - -DEVELOP_BUNDLE_IDENTIFIER :=com.theuhooi.UhooiPicBook-Develop -PRODUCTION_BUNDLE_IDENTIFIER :=com.theuhooi.UhooiPicBook - -CLI_TOOLS_PACKAGE_PATH := Tools/UhooiPicBookTools +CLI_TOOLS_PACKAGE_PATH := Tools/${PRODUCT_NAME}Tools CLI_TOOLS_PATH := ${CLI_TOOLS_PACKAGE_PATH}/.build/release -FIREBASE_VERSION := 8.6.0 +MOCK_FILE_PATH := ./Tests/AppModuleTests/Generated/MockResults.swift -MODULE_TEMPLATE_NAME ?= uhooi_viper +FIREBASE_VERSION := 9.0.0 + +REPORTS_PATH := ./Reports .DEFAULT_GOAL := help @@ -35,56 +29,29 @@ MODULE_TEMPLATE_NAME ?= uhooi_viper .PHONY: help help: - @grep -E '^[a-zA-Z_-]+:.*?# .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":[^#]*? #| #"}; {printf "%-42s%s\n", $$1 $$3, $$2}' + @grep -E '^[a-zA-Z_-]+:.*?# .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":[^#]*? #| #"}; {printf "%-36s%s\n", $$1 $$3, $$2}' .PHONY: setup setup: # Install dependencies and prepared development configuration - $(MAKE) install-ruby - $(MAKE) install-bundler - $(MAKE) install-templates $(MAKE) build-cli-tools - $(MAKE) build-mockolo $(MAKE) download-firebase-sdk $(MAKE) generate-licenses - $(MAKE) generate-xcodeproj-develop - -.PHONY: install-ruby -install-ruby: - cat .ruby-version | xargs rbenv install --skip-existing - -.PHONY: install-bundler -install-bundler: # Install Bundler dependencies - bundle config path vendor/bundle - bundle install --without=documentation --jobs 4 --retry 3 - -.PHONY: update-bundler -update-bundler: # Update Bundler dependencies - bundle config path vendor/bundle - bundle update --jobs 4 --retry 3 + $(MAKE) generate-mocks + $(MAKE) open .PHONY: build-cli-tools build-cli-tools: # Build CLI tools managed by SwiftPM - $(MAKE) build-cli-tool CLI_TOOL_NAME=xcodegen $(MAKE) build-cli-tool CLI_TOOL_NAME=swiftlint - $(MAKE) build-cli-tool CLI_TOOL_NAME=iblinter - $(MAKE) build-cli-tool CLI_TOOL_NAME=SpellChecker - # $(MAKE) build-cli-tool CLI_TOOL_NAME=mockolo +# $(MAKE) build-cli-tool CLI_TOOL_NAME=iblinter +# $(MAKE) build-cli-tool CLI_TOOL_NAME=SpellChecker + $(MAKE) build-cli-tool CLI_TOOL_NAME=mockolo $(MAKE) build-cli-tool CLI_TOOL_NAME=license-plist - $(MAKE) build-cli-tool CLI_TOOL_NAME=rswift $(MAKE) build-cli-tool CLI_TOOL_NAME=xcbeautify .PHONY: build-cli-tool build-cli-tool: swift build -c release --package-path ${CLI_TOOLS_PACKAGE_PATH} --product ${CLI_TOOL_NAME} -.PHONY: build-mockolo -build-mockolo: - swift build -c release --package-path Tools/UhooiPicBookMockolo --product mockolo - -.PHONY: install-templates -install-templates: # Install Generamba templates - bundle exec generamba template install - .PHONY: download-firebase-sdk download-firebase-sdk: # Download firebase-ios-sdk curl -OL https://github.com/firebase/firebase-ios-sdk/releases/download/${FIREBASE_VERSION}/Firebase.zip @@ -93,51 +60,27 @@ download-firebase-sdk: # Download firebase-ios-sdk .PHONY: generate-licenses generate-licenses: # Generate licenses with LicensePlist - ${CLI_TOOLS_PATH}/license-plist --output-path ${PRODUCT_NAME}/Settings.bundle --add-version-numbers --config-path lic-plist.yml - -.PHONY: generate-module -generate-module: # Generate module with Generamba # MODULE_NAME=[module name] - bundle exec generamba gen ${MODULE_NAME} ${MODULE_TEMPLATE_NAME} - -.PHONY: generate-xcodeproj-develop -generate-xcodeproj-develop: # Generate project with XcodeGen for develop - $(MAKE) copy-googleserviceinfo-develop - $(MAKE) generate-xcodeproj ENVIRONMENT=${DEVELOP_ENVIRONMENT} BUNDLE_IDENTIFIER=${DEVELOP_BUNDLE_IDENTIFIER} - -.PHONY: generate-xcodeproj-production -generate-xcodeproj-production: # Generate project with XcodeGen for production - $(MAKE) copy-googleserviceinfo-production - $(MAKE) generate-xcodeproj ENVIRONMENT=${PRODUCTION_ENVIRONMENT} BUNDLE_IDENTIFIER=${PRODUCTION_BUNDLE_IDENTIFIER} - -.PHONY: generate-xcodeproj -generate-xcodeproj: - ${CLI_TOOLS_PATH}/xcodegen generate - $(MAKE) open + ${CLI_TOOLS_PATH}/license-plist --output-path App/${PRODUCT_NAME}/Resources/Settings.bundle --add-version-numbers --config-path .lic-plist.yml -.PHONY: copy-googleserviceinfo-develop -copy-googleserviceinfo-develop: - $(MAKE) copy-googleserviceinfo ENVIRONMENT=Develop - -.PHONY: copy-googleserviceinfo-production -copy-googleserviceinfo-production: - $(MAKE) copy-googleserviceinfo ENVIRONMENT=Production - -.PHONY: copy-googleserviceinfo -copy-googleserviceinfo: - mkdir -p ./Shared/Resources/ - cp -f ./GoogleServiceInfo/GoogleService-Info-${ENVIRONMENT}.plist ./Shared/Resources/GoogleService-Info.plist +.PHONY: generate-mocks +generate-mocks: # Generate mocks with Mockolo + rm -f ${MOCK_FILE_PATH} + ${CLI_TOOLS_PATH}/mockolo --sourcedirs ./Sources --destination ${MOCK_FILE_PATH} --testable-imports AppModule --exclude-imports FirebaseMessaging --mock-final .PHONY: open -open: # Open project in Xcode - open ./${PROJECT_NAME} +open: # Open workspace in Xcode + open ./${WORKSPACE_NAME} .PHONY: clean clean: # Delete cache + rm -rf ./.swiftpm + rm -rf ./.build + rm -rf ./SourcePackages + rm -rf ./Reports + rm -rf ./.swiftlint + rm -rf ./App/.swiftlint rm -rf ./${CLI_TOOLS_PACKAGE_PATH}/.swiftpm rm -rf ./${CLI_TOOLS_PACKAGE_PATH}/.build - rm -rf ./vendor/bundle - rm -rf ./SourcePackages - rm -rf ./Templates xcodebuild clean -alltargets .PHONY: clean-cli-tools @@ -146,51 +89,75 @@ clean-cli-tools: # Delete build artifacts for CLI tools managed by SwiftPM .PHONY: analyze analyze: # Analyze with SwiftLint - $(MAKE) build-debug + $(MAKE) build-debug-develop ${CLI_TOOLS_PATH}/swiftlint analyze --autocorrect --compiler-log-path ./${XCODEBUILD_BUILD_LOG_NAME} +.PHONY: build-debug-develop +build-debug-develop: # Xcode debug build for develop + $(MAKE) build-debug PROJECT_NAME=${DEVELOP_PROJECT_NAME} + +.PHONY: build-debug-production +build-debug-production: # Xcode debug build for production + $(MAKE) build-debug PROJECT_NAME=${PRODUCTION_PROJECT_NAME} + .PHONY: build-debug -build-debug: # Xcode build for debug +build-debug: set -o pipefail \ && xcodebuild \ -sdk ${TEST_SDK} \ -configuration ${TEST_CONFIGURATION} \ --project ${PROJECT_NAME} \ --scheme ${SCHEME_NAME} \ +-workspace ${WORKSPACE_NAME} \ +-scheme '${PRODUCT_NAME} (${PROJECT_NAME} project)' \ -destination ${TEST_DESTINATION} \ -clonedSourcePackagesDirPath './SourcePackages' \ clean build \ -| tee ./${XCODEBUILD_BUILD_LOG_NAME} \ +| tee ${REPORTS_PATH}/${PRODUCT_NAME}_${PROJECT_NAME}_Build.log \ | ${CLI_TOOLS_PATH}/xcbeautify -.PHONY: test -test: # Xcode test # TEST_DEVICE=[device] TEST_OS=[OS] +.PHONY: test-debug-develop +test-debug-develop: # Xcode debug test for develop + $(MAKE) test-debug-project PROJECT_NAME=${DEVELOP_PROJECT_NAME} + +.PHONY: test-debug-production +test-debug-production: # Xcode debug test for production + $(MAKE) test-debug-project PROJECT_NAME=${PRODUCTION_PROJECT_NAME} + +.PHONY: test-debug-project +test-debug-project: + $(MAKE) test-debug SCHEME_NAME='${PRODUCT_NAME} (${PROJECT_NAME} project)' TEST_PLAN_NAME='${PROJECT_NAME}' XCRESULT_NAME=${PRODUCT_NAME}_${PROJECT_NAME} LOG_NAME=${PRODUCT_NAME}_${PROJECT_NAME} + +.PHONY: test-debug-app-module +test-debug-app-module: # Xcode debug test for AppModule + $(MAKE) test-debug-target TEST_TARGET_NAME='AppModuleTests' + +.PHONY: test-debug-target +test-debug-target: + $(MAKE) test-debug SCHEME_NAME='${TEST_TARGET_NAME}' TEST_PLAN_NAME='${TEST_TARGET_NAME}' XCRESULT_NAME='${TEST_TARGET_NAME}' LOG_NAME=${TEST_TARGET_NAME} + +.PHONY: test-debug +test-debug: + rm -rf ${REPORTS_PATH}/${XCRESULT_NAME}.xcresult/ set -o pipefail \ && NSUnbufferedIO=YES \ xcodebuild \ -sdk ${TEST_SDK} \ -configuration ${TEST_CONFIGURATION} \ --project ${PROJECT_NAME} \ --scheme ${SCHEME_NAME} \ +-workspace ${WORKSPACE_NAME} \ +-scheme '${SCHEME_NAME}' \ -destination ${TEST_DESTINATION} \ +-testPlan '${TEST_PLAN_NAME}' \ -skip-testing:${UI_TESTS_TARGET_NAME} \ -clonedSourcePackagesDirPath './SourcePackages' \ +-resultBundlePath '${REPORTS_PATH}/${XCRESULT_NAME}.xcresult' \ clean test \ 2>&1 \ -| tee ./${XCODEBUILD_TEST_LOG_NAME} \ +| tee ${REPORTS_PATH}/${LOG_NAME}_Test.log \ | ${CLI_TOOLS_PATH}/xcbeautify --is-ci -.PHONY: get-coverage-html -get-coverage-html: # Get code coverage for HTML - bundle exec slather coverage --html --output-directory ${COVERAGE_OUTPUT} - -.PHONY: get-coverage-cobertura -get-coverage-cobertura: # Get code coverage for Cobertura - bundle exec slather - -.PHONY: upload-coverage -upload-coverage: # Upload code coverage to Codecov - bash -c "bash <(curl -s https://codecov.io/bash) -f xml_report/cobertura.xml -X coveragepy -X gcov -X xcode" +.PHONY: merge-test-results +merge-test-results: # Merge test results + rm -rf ${REPORTS_PATH}/TestResults.xcresult/ + xcrun xcresulttool merge ${REPORTS_PATH}/${PRODUCT_NAME}_${DEVELOP_PROJECT_NAME}.xcresult ${REPORTS_PATH}/AppModuleTests.xcresult --output-path ${REPORTS_PATH}/TestResults.xcresult .PHONY: show-devices show-devices: # Show devices diff --git a/Package.swift b/Package.swift new file mode 100644 index 00000000..69c8894a --- /dev/null +++ b/Package.swift @@ -0,0 +1,225 @@ +// swift-tools-version:5.7 + +import PackageDescription + +let firebaseAnalyticsDependencies: [Target.Dependency] = [ + "FirebaseAnalytics", + "FirebaseCore", + "FirebaseCoreDiagnostics", + "FirebaseCoreInternal", + "FirebaseInstallations", + "GoogleAppMeasurement", + "GoogleDataTransport", + "GoogleUtilities", + "PromisesObjC", + "nanopb", +] + +let firebaseCrashlyticsDependencies: [Target.Dependency] = [ + "FirebaseCrashlytics", +] + +let firebasePerformanceDependencies: [Target.Dependency] = [ + "FirebaseABTesting", + "FirebasePerformance", + "FirebaseRemoteConfig", +] + +let firebaseMessagingDependencies: [Target.Dependency] = [ + "FirebaseMessaging", +] + +let firebaseFirestoreDependencies: [Target.Dependency] = [ + "BoringSSL-GRPC", + "FirebaseFirestore", + "Libuv-gRPC", + "abseil", + "gRPC-C++", + "gRPC-Core", + "leveldb-library", +] + +let otherSwiftFlags: [String] = [ + "-Xfrontend", "-warn-long-expression-type-checking=500", + "-Xfrontend", "-warn-long-function-bodies=500", + "-Xfrontend", "-warn-concurrency", + "-Xfrontend", "-enable-actor-data-race-checks", +] + +let package = Package( + name: "UhooiPicBookPackage", + defaultLocalization: "ja", + platforms: [ + .iOS(.v15), + .macOS(.v10_15), + ], + products: [ + .library(name: "FirebaseSetup", targets: ["FirebaseSetup"]), + .library(name: "FirebaseMessagingBridge", targets: ["FirebaseMessagingBridge"]), + .library(name: "AppModule", targets: ["AppModule"]), + .library(name: "MonsterWidgets", targets: ["MonsterWidgets"]), + .library(name: "MonstersRepository", targets: ["MonstersRepository"]), // TODO: Remove later + .library(name: "ImageLoader", targets: ["ImageLoader"]), // TODO: Remove later + ], + dependencies: [ + ], + targets: [ + .target( + name: "FirebaseSetup", + dependencies: firebaseCrashlyticsDependencies + firebasePerformanceDependencies + firebaseAnalyticsDependencies, + linkerSettings: [ + .unsafeFlags(["-ObjC"]), + ] + ), + .target( + name: "FirebaseMessagingBridge", + dependencies: firebaseMessagingDependencies + firebaseAnalyticsDependencies, + linkerSettings: [ + .unsafeFlags(["-ObjC"]), + ] + ), + .target( + name: "AppModule", + dependencies: [ + "MonstersRepository", + "Logger", + "ImageLoader", + ], + swiftSettings: [ + .unsafeFlags(otherSwiftFlags, .when(configuration: .debug)), + ] + ), + .testTarget( + name: "AppModuleTests", + dependencies: [ + "AppModule", + ] + ), + .target( + name: "MonsterWidgets", + dependencies: [ + "FirebaseSetup", + "MonstersRepository", + "Logger", + "ImageLoader", + ], + swiftSettings: [ + .unsafeFlags(otherSwiftFlags, .when(configuration: .debug)), + ] + ), + .target( + name: "MonstersRepository", + dependencies: firebaseFirestoreDependencies + firebaseAnalyticsDependencies, + swiftSettings: [ + .unsafeFlags(otherSwiftFlags, .when(configuration: .debug)), + ], + linkerSettings: [ + .unsafeFlags(["-ObjC"]), + ] + ), + .target( + name: "Logger", + dependencies: [ + ], + swiftSettings: [ + .unsafeFlags(otherSwiftFlags, .when(configuration: .debug)), + ] + ), + .target( + name: "ImageLoader", + dependencies: [ + ], + swiftSettings: [ + .unsafeFlags(otherSwiftFlags, .when(configuration: .debug)), + ] + ), + .binaryTarget( + name: "FirebaseAnalytics", + path: "./Frameworks/Firebase/FirebaseAnalytics/FirebaseAnalytics.xcframework" + ), + .binaryTarget( + name: "FirebaseCore", + path: "./Frameworks/Firebase/FirebaseAnalytics/FirebaseCore.xcframework" + ), + .binaryTarget( + name: "FirebaseCoreDiagnostics", + path: "./Frameworks/Firebase/FirebaseAnalytics/FirebaseCoreDiagnostics.xcframework" + ), + .binaryTarget( + name: "FirebaseCoreInternal", + path: "./Frameworks/Firebase/FirebaseAnalytics/FirebaseCoreInternal.xcframework" + ), + .binaryTarget( + name: "FirebaseInstallations", + path: "./Frameworks/Firebase/FirebaseAnalytics/FirebaseInstallations.xcframework" + ), + .binaryTarget( + name: "GoogleAppMeasurement", + path: "./Frameworks/Firebase/FirebaseAnalytics/GoogleAppMeasurement.xcframework" + ), + .binaryTarget( + name: "GoogleDataTransport", + path: "./Frameworks/Firebase/FirebaseAnalytics/GoogleDataTransport.xcframework" + ), + .binaryTarget( + name: "GoogleUtilities", + path: "./Frameworks/Firebase/FirebaseAnalytics/GoogleUtilities.xcframework" + ), + .binaryTarget( + name: "PromisesObjC", + path: "./Frameworks/Firebase/FirebaseAnalytics/PromisesObjC.xcframework" + ), + .binaryTarget( + name: "nanopb", + path: "./Frameworks/Firebase/FirebaseAnalytics/nanopb.xcframework" + ), + .binaryTarget( + name: "FirebaseCrashlytics", + path: "./Frameworks/Firebase/FirebaseCrashlytics/FirebaseCrashlytics.xcframework" + ), + .binaryTarget( + name: "FirebaseABTesting", + path: "./Frameworks/Firebase/FirebasePerformance/FirebaseABTesting.xcframework" + ), + .binaryTarget( + name: "FirebasePerformance", + path: "./Frameworks/Firebase/FirebasePerformance/FirebasePerformance.xcframework" + ), + .binaryTarget( + name: "FirebaseRemoteConfig", + path: "./Frameworks/Firebase/FirebasePerformance/FirebaseRemoteConfig.xcframework" + ), + .binaryTarget( + name: "FirebaseMessaging", + path: "./Frameworks/Firebase/FirebaseMessaging/FirebaseMessaging.xcframework" + ), + .binaryTarget( + name: "Libuv-gRPC", + path: "./Frameworks/Firebase/FirebaseFirestore/Libuv-gRPC.xcframework" + ), + .binaryTarget( + name: "abseil", + path: "./Frameworks/Firebase/FirebaseFirestore/abseil.xcframework" + ), + .binaryTarget( + name: "BoringSSL-GRPC", + path: "./Frameworks/Firebase/FirebaseFirestore/BoringSSL-GRPC.xcframework" + ), + .binaryTarget( + name: "FirebaseFirestore", + path: "./Frameworks/Firebase/FirebaseFirestore/FirebaseFirestore.xcframework" + ), + .binaryTarget( + name: "gRPC-C++", + path: "./Frameworks/Firebase/FirebaseFirestore/gRPC-C++.xcframework" + ), + .binaryTarget( + name: "gRPC-Core", + path: "./Frameworks/Firebase/FirebaseFirestore/gRPC-Core.xcframework" + ), + .binaryTarget( + name: "leveldb-library", + path: "./Frameworks/Firebase/FirebaseFirestore/leveldb-library.xcframework" + ), + ] +) diff --git a/README.ja.md b/README.ja.md new file mode 100644 index 00000000..cfdbc5e2 --- /dev/null +++ b/README.ja.md @@ -0,0 +1,128 @@ +[英語](./README.md) / 日本語 + +# UhooiPicBook-iOS + +[![Release](https://img.shields.io/github/v/release/uhooi/UhooiPicBook)](https://github.com/uhooi/UhooiPicBook/releases/latest) +[![License](https://img.shields.io/github/license/uhooi/UhooiPicBook)](https://github.com/uhooi/UhooiPicBook/blob/main/LICENSE) +[![Platform](https://img.shields.io/badge/platform-iOS-lightgrey)](https://github.com/uhooi/UhooiPicBook) +[![Twitter](https://img.shields.io/twitter/follow/the_uhooi?style=social)](https://twitter.com/the_uhooi) + +|ブランチ|CI|コードカバレッジ| +|:--|:--:|:--:| +|[main](https://github.com/uhooi/UhooiPicBook/tree/main)|[![CI](https://github.com/uhooi/UhooiPicBook/actions/workflows/main.yml/badge.svg?branch=main)](https://github.com/uhooi/UhooiPicBook/actions/workflows/main.yml)|-| +|[develop](https://github.com/uhooi/UhooiPicBook/tree/develop)|[![CI](https://github.com/uhooi/UhooiPicBook/actions/workflows/main.yml/badge.svg?branch=develop)](https://github.com/uhooi/UhooiPicBook/actions/workflows/main.yml)|-| + +![Logo](./Docs/Logo.png) + +UhooiPicBook-iOSは、ウホーイのiOS用キャラクター図鑑です。 + +Download on the App Store + +## 目次 + +- [スクリーンショット](#スクリーンショット) +- [開発](#開発) +- [貢献](#貢献) +- [スタッツ](#スタッツ) + +## スクリーンショット + +
スクリーンショット + +### ライト + +|モンスター一覧|モンスター詳細|画像ポップアップ| +|:--:|:--:|:--:| +|||| + +|モンスター一覧で開いたメニュー|Spotlight|iMessage| +|:--:|:--:|:--:| +|||| + +|ウィジェット| +|:--:| +|| + +### ダーク + +|モンスター一覧|モンスター詳細|画像ポップアップ| +|:--:|:--:|:--:| +|||| + +|モンスター一覧で開いたメニュー|Spotlight|iMessage| +|:--:|:--:|:--:| +|||| + +|ウィジェット| +|:--:| +|| + +
+ +## 開発 + +誰でもこのプロジェクトを開発できます。 + +### 必要条件 + +- macOS 12.5+ +- Xcode 14.1 (Swift 5.7.1) +- Make + +### 構成 + +- UIの実装: Storyboard + XIB +- アーキテクチャ: VIPER +- UIテストのアーキテクチャ: Page Object Pattern +- ブランチモデル: Git-flow + +### セットアップ + +1. このプロジェクトをクローンします。 + ```shell + $ git clone https://github.com/uhooi/UhooiPicBook.git + $ cd UhooiPicBook + ``` + +2. Swiftプロジェクトの高速ビルドを有効にします。(任意) + ```shell + $ defaults write com.apple.dt.XCBuild EnableSwiftBuildSystemIntegration 1 + ``` + +3. `make setup` を実行します。 +セットアップが完了すると、自動的にXcodeでワークスペースが開きます。 + +### ヘルプ + +`make help` を実行します。 + +```shell +$ make help +setup Install dependencies and prepared development configuration +build-cli-tools Build CLI tools managed by SwiftPM +download-firebase-sdk Download firebase-ios-sdk +generate-licenses Generate licenses with LicensePlist +generate-mocks Generate mocks with Mockolo +open Open workspace in Xcode +clean Delete cache +clean-cli-tools Delete build artifacts for CLI tools managed by SwiftPM +analyze Analyze with SwiftLint +build-debug-develop Xcode debug build for develop +build-debug-production Xcode debug build for production +test-debug-develop Xcode debug test for develop +test-debug-production Xcode debug test for production +test-debug-app-module Xcode debug test for AppModule +merge-test-results Merge test results +show-devices Show devices +``` + +## 貢献 + +貢献をお待ちしています :relaxed: + +- [新しいイシュー](https://github.com/uhooi/UhooiPicBook/issues/new) +- [新しいプルリクエスト](https://github.com/uhooi/UhooiPicBook/compare) + +## スタッツ + +[![Stats](https://repobeats.axiom.co/api/embed/1c29e1d49c64b444ae3a829603069d4fcfcf7596.svg "Repobeats analytics image")](https://github.com/uhooi/UhooiPicBook) diff --git a/README.md b/README.md index 39026136..e9b9f727 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +English / [Japanese](./README.ja.md) + # UhooiPicBook-iOS [![Release](https://img.shields.io/github/v/release/uhooi/UhooiPicBook)](https://github.com/uhooi/UhooiPicBook/releases/latest) @@ -6,54 +8,66 @@ [![Twitter](https://img.shields.io/twitter/follow/the_uhooi?style=social)](https://twitter.com/the_uhooi) |Branch|CI|Code coverage| -|:--|:--|:--| -|[main](https://github.com/uhooi/UhooiPicBook/tree/main)|[![CI](https://github.com/uhooi/UhooiPicBook/actions/workflows/main.yml/badge.svg?branch=main)](https://github.com/uhooi/UhooiPicBook/actions/workflows/main.yml)|[![codecov](https://codecov.io/gh/uhooi/UhooiPicBook/branch/main/graph/badge.svg?token=4HTK2YK2FG)](https://codecov.io/gh/uhooi/UhooiPicBook)| -|[develop](https://github.com/uhooi/UhooiPicBook/tree/develop)|[![CI](https://github.com/uhooi/UhooiPicBook/actions/workflows/main.yml/badge.svg?branch=develop)](https://github.com/uhooi/UhooiPicBook/actions/workflows/main.yml)|[![codecov](https://codecov.io/gh/uhooi/UhooiPicBook/branch/develop/graph/badge.svg?token=4HTK2YK2FG)](https://codecov.io/gh/uhooi/UhooiPicBook)| +|:--|:--:|:--:| +|[main](https://github.com/uhooi/UhooiPicBook/tree/main)|[![CI](https://github.com/uhooi/UhooiPicBook/actions/workflows/main.yml/badge.svg?branch=main)](https://github.com/uhooi/UhooiPicBook/actions/workflows/main.yml)|-| +|[develop](https://github.com/uhooi/UhooiPicBook/tree/develop)|[![CI](https://github.com/uhooi/UhooiPicBook/actions/workflows/main.yml/badge.svg?branch=develop)](https://github.com/uhooi/UhooiPicBook/actions/workflows/main.yml)|-| ![Logo](./Docs/Logo.png) UhooiPicBook-iOS is Uhooi's character book for iOS. -[![Download_on_the_App_Store_Badge](./Docs/Download_on_the_App_Store_Badge_US-UK_RGB_blk_092917.svg)](https://apps.apple.com/jp/app/id1501657213) +Download on the App Store + +## Table of Contents + +- [Screenshots](#screenshots) +- [Development](#development) +- [Contribution](#contribution) +- [Stats](#stats) ## Screenshots +
Screenshots + ### Light |MonsterList|MonsterDetail|ImagePopup| -|:--|:--|:--| -|||| +|:--:|:--:|:--:| +|||| |Menu opened in MonsterList|Spotlight|iMessage| -|:--|:--|:--| -|||| +|:--:|:--:|:--:| +|||| |Widgets| -|:--| +|:--:| || ### Dark |MonsterList|MonsterDetail|ImagePopup| -|:--|:--|:--| -|||| +|:--:|:--:|:--:| +|||| |Menu opened in MonsterList|Spotlight|iMessage| -|:--|:--|:--| -|||| +|:--:|:--:|:--:| +|||| |Widgets| -|:--| +|:--:| || +
+ ## Development You can develop this project. ### Environment -- [Xcode](https://apps.apple.com/jp/app/xcode/id497799835): 13.0 -- [rbenv](https://github.com/rbenv/rbenv): 1.1.2 +- macOS 12.5+ +- Xcode 14.1 (Swift 5.7.1) +- Make ### Configuration @@ -64,14 +78,18 @@ You can develop this project. ### Setup -1. Clone the project. +1. Clone the project. + ```shell + $ git clone https://github.com/uhooi/UhooiPicBook.git + $ cd UhooiPicBook + ``` -```shell -$ git clone https://github.com/uhooi/UhooiPicBook.git -$ cd UhooiPicBook -``` +2. Enable faster builds for Swift projects. (Optional) + ```shell + $ defaults write com.apple.dt.XCBuild EnableSwiftBuildSystemIntegration 1 + ``` -2. Run `make setup` . +3. Run `make setup` . After setup is complete, Workspace automatically opens in Xcode. ### Help @@ -80,26 +98,22 @@ Run `make help` . ```shell $ make help -setup Install dependencies and prepared development configuration -install-bundler Install Bundler dependencies -update-bundler Update Bundler dependencies -build-cli-tools Build CLI tools managed by SwiftPM -install-templates Install Generamba templates -download-firebase-sdk Download firebase-ios-sdk -generate-licenses Generate licenses with LicensePlist -generate-module MODULE_NAME=[module name] Generate module with Generamba -generate-xcodeproj-develop Generate project with XcodeGen for develop -generate-xcodeproj-production Generate project with XcodeGen for production -open Open project in Xcode -clean Delete cache -clean-cli-tools Delete build artifacts for CLI tools managed by SwiftPM -analyze Analyze with SwiftLint -build-debug Xcode build for debug -test TEST_DEVICE=[device] TEST_OS=[OS] Xcode test -get-coverage-html Get code coverage for HTML -get-coverage-cobertura Get code coverage for Cobertura -upload-coverage Upload code coverage to Codecov -show-devices Show devices +setup Install dependencies and prepared development configuration +build-cli-tools Build CLI tools managed by SwiftPM +download-firebase-sdk Download firebase-ios-sdk +generate-licenses Generate licenses with LicensePlist +generate-mocks Generate mocks with Mockolo +open Open workspace in Xcode +clean Delete cache +clean-cli-tools Delete build artifacts for CLI tools managed by SwiftPM +analyze Analyze with SwiftLint +build-debug-develop Xcode debug build for develop +build-debug-production Xcode debug build for production +test-debug-develop Xcode debug test for develop +test-debug-production Xcode debug test for production +test-debug-app-module Xcode debug test for AppModule +merge-test-results Merge test results +show-devices Show devices ``` ## Contribution @@ -108,3 +122,7 @@ I would be happy if you contribute :) - [New issue](https://github.com/uhooi/UhooiPicBook/issues/new) - [New pull request](https://github.com/uhooi/UhooiPicBook/compare) + +## Stats + +[![Stats](https://repobeats.axiom.co/api/embed/1c29e1d49c64b444ae3a829603069d4fcfcf7596.svg "Repobeats analytics image")](https://github.com/uhooi/UhooiPicBook) diff --git a/Rambafile b/Rambafile deleted file mode 100644 index ecc55d83..00000000 --- a/Rambafile +++ /dev/null @@ -1,37 +0,0 @@ -### Headers settings -company: THE Uhooi - -### Xcode project settings -project_name: UhooiPicBook -xcodeproj_path: UhooiPicBook.xcodeproj - -### Code generation settings section -# The main project target name -project_target: UhooiPicBook - -# The file path for new modules -project_file_path: ./UhooiPicBook/Modules - -# The Xcode group path to new modules -project_group_path: ./UhooiPicBook/Modules - -### Tests generation settings section -# The tests target name -test_target: UhooiPicBookTests - -# The file path for new tests -test_file_path: ./UhooiPicBookTests/Modules - -# The Xcode group path to new tests -test_group_path: ./UhooiPicBookTests/Modules - -### Templates -catalogs: -- 'https://github.com/uhooi/generamba-catalog' -templates: -- {name: rviper_controller} -- {name: mvvm_controller} -- {name: swifty_viper} -- {name: uhooi_viper} - - diff --git a/Reports/.gitkeep b/Reports/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Scripts/XcodeGen/iblinter.sh b/Scripts/XcodeGen/iblinter.sh deleted file mode 100644 index b76e828e..00000000 --- a/Scripts/XcodeGen/iblinter.sh +++ /dev/null @@ -1,3 +0,0 @@ -SDKROOT=$(xcrun --sdk macosx --show-sdk-path) -Tools/UhooiPicBookTools/.build/release/iblinter lint - diff --git a/Scripts/XcodeGen/mockolo.sh b/Scripts/XcodeGen/mockolo.sh deleted file mode 100644 index 7711c200..00000000 --- a/Scripts/XcodeGen/mockolo.sh +++ /dev/null @@ -1,4 +0,0 @@ -rm -f $SRCROOT/$TARGET_NAME/Generated/MockResults.swift -SDKROOT=$(xcrun --sdk macosx --show-sdk-path) -Tools/UhooiPicBookMockolo/.build/release/mockolo --sourcedirs $SRCROOT/$TARGET_NAME --sourcedirs $SRCROOT/Shared --destination $SRCROOT/$TARGET_NAME/Generated/MockResults.swift --mock-final - diff --git a/Scripts/XcodeGen/rswift.sh b/Scripts/XcodeGen/rswift.sh deleted file mode 100644 index 0e45e31b..00000000 --- a/Scripts/XcodeGen/rswift.sh +++ /dev/null @@ -1,3 +0,0 @@ -SDKROOT=$(xcrun --sdk macosx --show-sdk-path) -Tools/UhooiPicBookTools/.build/release/rswift generate "$SRCROOT/$TARGET_NAME/Generated/R.generated.swift" - diff --git a/Scripts/XcodeGen/spellchecker.sh b/Scripts/XcodeGen/spellchecker.sh deleted file mode 100644 index 2f080c90..00000000 --- a/Scripts/XcodeGen/spellchecker.sh +++ /dev/null @@ -1,16 +0,0 @@ -git_path=/usr/local/bin/git -files=$($git_path diff --diff-filter=d --name-only -- "*.swift" "*.h" "*.m") -if (test -z $files) || (test ${#files[@]} -eq 0); then - echo "no files changed." - exit 0 -fi - -options="" -for file in $files -do - options="$options $SRCROOT/$file" -done - -SDKROOT=$(xcrun --sdk macosx --show-sdk-path) -Tools/UhooiPicBookTools/.build/release/SpellChecker --yml $SRCROOT/spell-checker.yml -- $options - diff --git a/Scripts/XcodeGen/swiftlint.sh b/Scripts/XcodeGen/swiftlint.sh deleted file mode 100644 index c518a9bb..00000000 --- a/Scripts/XcodeGen/swiftlint.sh +++ /dev/null @@ -1,4 +0,0 @@ -SDKROOT=$(xcrun --sdk macosx --show-sdk-path) -Tools/UhooiPicBookTools/.build/release/swiftlint --fix --format -Tools/UhooiPicBookTools/.build/release/swiftlint - diff --git a/Shared/Repository/Monsters/MonsterDTO.swift b/Shared/Repository/Monsters/MonsterDTO.swift deleted file mode 100644 index 0f11fb60..00000000 --- a/Shared/Repository/Monsters/MonsterDTO.swift +++ /dev/null @@ -1,17 +0,0 @@ -// -// MonsterDTO.swift -// UhooiPicBook -// -// Created by uhooi on 2020/02/28. -// - -struct MonsterDTO { - let name: String - let description: String - let baseColorCode: String - let iconUrlString: String - let dancingUrlString: String - let order: Int -} - -extension MonsterDTO: Equatable { } diff --git a/Shared/Repository/Monsters/MonstersRepository.swift b/Shared/Repository/Monsters/MonstersRepository.swift deleted file mode 100644 index 40f88510..00000000 --- a/Shared/Repository/Monsters/MonstersRepository.swift +++ /dev/null @@ -1,52 +0,0 @@ -// -// MonstersRepository.swift -// UhooiPicBook -// -// Created by uhooi on 2020/02/28. -// - -import FirebaseFirestore - -/// @mockable -protocol MonstersRepository: AnyObject { // swiftlint:disable:this file_types_order - func loadMonsters(_ completion: @escaping (Result<[MonsterDTO], Error>) -> Void) -} - -final class MonstersFirebaseClient { - private let firestore = Firestore.firestore() -} - -extension MonstersFirebaseClient: MonstersRepository { - - func loadMonsters(_ completion: @escaping (Result<[MonsterDTO], Error>) -> Void) { - let monstersRef = self.firestore.collection("monsters") - monstersRef.getDocuments { querySnapshot, error in - if let error = error { - completion(.failure(error)) - return - } - - guard let querySnapshot = querySnapshot else { - fatalError("Fail to unwrap `querySnapshot`.") - } - - var monsters: [MonsterDTO] = [] - for document in querySnapshot.documents.filter({ $0.exists }) { - let monster = document.data() - guard let name = monster["name"] as? String, - let description = monster["description"] as? String, - let baseColorCode = monster["base_color"] as? String, - let iconUrlString = monster["icon_url"] as? String, - let dancingUrlString = monster["dancing_url"] as? String, - let order = monster["order"] as? Int else { - continue - } - - monsters.append(MonsterDTO(name: name, description: description, baseColorCode: baseColorCode, iconUrlString: iconUrlString, dancingUrlString: dancingUrlString, order: order)) - } - - completion(.success(monsters)) - } - } - -} diff --git a/Shared/Util/ImageCacheManager.swift b/Shared/Util/ImageCacheManager.swift deleted file mode 100644 index d08bc26c..00000000 --- a/Shared/Util/ImageCacheManager.swift +++ /dev/null @@ -1,66 +0,0 @@ -// -// ImageCacheManager.swift -// UhooiPicBook -// -// Created by uhooi on 2020/03/03. -// - -import UIKit - -enum ImageCacheError: Error { - case loadingFailure -} - -/// @mockable -protocol ImageCacheManagerProtocol: AnyObject { - func cacheImage(imageUrl: URL, completion: @escaping (Result) -> Void) - func cacheGIFImage(imageUrl: URL) -> UIImage? -} - -final class ImageCacheManager: ImageCacheManagerProtocol { - - static let imageCache = NSCache() - - func cacheImage(imageUrl: URL, completion: @escaping (Result) -> Void) { - if let imageFromCache = ImageCacheManager.imageCache.object(forKey: imageUrl as AnyObject) as? UIImage { - completion(.success(imageFromCache)) - return - } - - var imageToCache = UIImage() - - URLSession.shared.dataTask(with: imageUrl) { data, _, error in - if let error = error { - completion(.failure(error)) - return - } else { - guard let data = data, let image = UIImage(data: data) else { - completion(.failure(ImageCacheError.loadingFailure)) - return - } - - imageToCache = image - ImageCacheManager.imageCache.setObject(imageToCache, forKey: imageUrl as AnyObject) - } - - DispatchQueue.main.async { - completion(.success(imageToCache)) - } - }.resume() - } - - func cacheGIFImage(imageUrl: URL) -> UIImage? { - if let imageFromCache = ImageCacheManager.imageCache.object(forKey: imageUrl as AnyObject) as? UIImage { - return imageFromCache - } - - guard let imageToCache = UIImage.gifImage(with: imageUrl) else { - return nil - } - - ImageCacheManager.imageCache.setObject(imageToCache, forKey: imageUrl as AnyObject) - - return imageToCache - } - -} diff --git a/UhooiPicBook/Extensions/Foundation/Bundle+String.swift b/Sources/AppModule/Extensions/Foundation/Bundle+String.swift similarity index 100% rename from UhooiPicBook/Extensions/Foundation/Bundle+String.swift rename to Sources/AppModule/Extensions/Foundation/Bundle+String.swift diff --git a/UhooiPicBook/Extensions/UIKit/UICollectionView+Animation.swift b/Sources/AppModule/Extensions/UIKit/UICollectionView+Animation.swift similarity index 87% rename from UhooiPicBook/Extensions/UIKit/UICollectionView+Animation.swift rename to Sources/AppModule/Extensions/UIKit/UICollectionView+Animation.swift index 6aac0475..02c11d06 100644 --- a/UhooiPicBook/Extensions/UIKit/UICollectionView+Animation.swift +++ b/Sources/AppModule/Extensions/UIKit/UICollectionView+Animation.swift @@ -8,21 +8,20 @@ import UIKit extension UICollectionView { - func executeCellSlideUpAnimation() { // If not called first, `visibleCells` will be empty. layoutIfNeeded() // Temporarily bring visible cells under the collection view. - self.visibleCells.forEach { + visibleCells.forEach { $0.transform = CGAffineTransform( translationX: 0, - y: self.bounds.size.height + y: bounds.size.height ) } // Animate it back to where it should be. - self.visibleCells.enumerated().forEach { object in + visibleCells.enumerated().forEach { object in UIView.animate( withDuration: 0.6, delay: 0.04 * Double(object.offset), @@ -36,5 +35,4 @@ extension UICollectionView { ) } } - } diff --git a/UhooiPicBook/Extensions/UIKit/UIColor+Hex.swift b/Sources/AppModule/Extensions/UIKit/UIColor+Hex.swift similarity index 99% rename from UhooiPicBook/Extensions/UIKit/UIColor+Hex.swift rename to Sources/AppModule/Extensions/UIKit/UIColor+Hex.swift index 588f7d06..69ed0af6 100644 --- a/UhooiPicBook/Extensions/UIKit/UIColor+Hex.swift +++ b/Sources/AppModule/Extensions/UIKit/UIColor+Hex.swift @@ -8,7 +8,6 @@ import UIKit extension UIColor { - convenience init(hex: String, alpha: CGFloat = 1.0) { var hexString = hex if hex.prefix(1) == "#" { @@ -20,5 +19,4 @@ extension UIColor { let b = CGFloat(v / Int(powf(256, 0)) % 256) / 255 self.init(red: r, green: g, blue: b, alpha: min(max(alpha, 0), 1)) } - } diff --git a/UhooiPicBook/Extensions/UIKit/UIImage+Resize.swift b/Sources/AppModule/Extensions/UIKit/UIImage+Resize.swift similarity index 70% rename from UhooiPicBook/Extensions/UIKit/UIImage+Resize.swift rename to Sources/AppModule/Extensions/UIKit/UIImage+Resize.swift index 7f33a0fe..c7e4192d 100644 --- a/UhooiPicBook/Extensions/UIKit/UIImage+Resize.swift +++ b/Sources/AppModule/Extensions/UIKit/UIImage+Resize.swift @@ -9,11 +9,11 @@ import UIKit extension UIImage { func resize(_ afterSize: CGSize) -> UIImage? { - let widthRatio = afterSize.width / self.size.width - let heightRatio = afterSize.height / self.size.height + let widthRatio = afterSize.width / size.width + let heightRatio = afterSize.height / size.height let ratio = widthRatio < heightRatio ? widthRatio : heightRatio - let resizedSize = CGSize(width: self.size.width * ratio, height: self.size.height * ratio) + let resizedSize = CGSize(width: size.width * ratio, height: size.height * ratio) UIGraphicsBeginImageContextWithOptions(resizedSize, false, 0.0) draw(in: CGRect(origin: .zero, size: resizedSize)) diff --git a/UhooiPicBook/Extensions/UIKit/UINavigationBar+Color.swift b/Sources/AppModule/Extensions/UIKit/UINavigationBar+Color.swift similarity index 70% rename from UhooiPicBook/Extensions/UIKit/UINavigationBar+Color.swift rename to Sources/AppModule/Extensions/UIKit/UINavigationBar+Color.swift index e6001933..ad1c1ebd 100644 --- a/UhooiPicBook/Extensions/UIKit/UINavigationBar+Color.swift +++ b/Sources/AppModule/Extensions/UIKit/UINavigationBar+Color.swift @@ -1,6 +1,6 @@ // // UINavigationBar+Color.swift -// UINavigationBar+Color +// UhooiPicBook // // Created by uhooi on 2021/08/28. // @@ -11,7 +11,7 @@ extension UINavigationBar { func configureBackgroundColor(_ color: UIColor?) { let appearance = UINavigationBarAppearance() appearance.backgroundColor = color - self.standardAppearance = appearance - self.scrollEdgeAppearance = appearance + standardAppearance = appearance + scrollEdgeAppearance = appearance } } diff --git a/Sources/AppModule/Extensions/UIKit/UIView+Material.swift b/Sources/AppModule/Extensions/UIKit/UIView+Material.swift new file mode 100644 index 00000000..6d2af240 --- /dev/null +++ b/Sources/AppModule/Extensions/UIKit/UIView+Material.swift @@ -0,0 +1,23 @@ +// +// UIView+Material.swift +// UhooiPicBook +// +// Created by uhooi on 2020/03/01. +// + +import UIKit + +@MainActor +protocol MaterialView { + func elevate(elevation: Double) +} + +extension UIView: MaterialView { + func elevate(elevation: Double) { + layer.masksToBounds = false + layer.shadowColor = UIColor.black.cgColor + layer.shadowOffset = CGSize(width: 0.0, height: elevation) + layer.shadowRadius = abs(CGFloat(elevation)) + layer.shadowOpacity = 0.24 + } +} diff --git a/UhooiPicBook/Extensions/UIKit/UIViewController+Alert.swift b/Sources/AppModule/Extensions/UIKit/UIViewController+Alert.swift similarity index 100% rename from UhooiPicBook/Extensions/UIKit/UIViewController+Alert.swift rename to Sources/AppModule/Extensions/UIKit/UIViewController+Alert.swift diff --git a/UhooiPicBook/Modules/MonsterDetail/Interactors/MonsterDetailInteractor.swift b/Sources/AppModule/Modules/MonsterDetail/Interactors/MonsterDetailInteractor.swift similarity index 66% rename from UhooiPicBook/Modules/MonsterDetail/Interactors/MonsterDetailInteractor.swift rename to Sources/AppModule/Modules/MonsterDetail/Interactors/MonsterDetailInteractor.swift index ac6bd858..5bc28fb1 100644 --- a/UhooiPicBook/Modules/MonsterDetail/Interactors/MonsterDetailInteractor.swift +++ b/Sources/AppModule/Modules/MonsterDetail/Interactors/MonsterDetailInteractor.swift @@ -12,21 +12,20 @@ protocol MonsterDetailInteractorInput: AnyObject { final class MonsterDetailInteractor { - // MARK: Type Aliases - // MARK: Stored Instance Properties - weak var presenter: MonsterDetailInteractorOutput! - - // MARK: Computed Instance Properties + private weak var presenter: (any MonsterDetailInteractorOutput)! // MARK: Initializer init() { } - // MARK: Other Private Methods + // MARK: Other Internal Methods + func inject(presenter: some MonsterDetailInteractorOutput) { + self.presenter = presenter + } } extension MonsterDetailInteractor: MonsterDetailInteractorInput { diff --git a/UhooiPicBook/Modules/MonsterDetail/Presenters/MonsterDetailPresenter.swift b/Sources/AppModule/Modules/MonsterDetail/Presenters/MonsterDetailPresenter.swift similarity index 56% rename from UhooiPicBook/Modules/MonsterDetail/Presenters/MonsterDetailPresenter.swift rename to Sources/AppModule/Modules/MonsterDetail/Presenters/MonsterDetailPresenter.swift index 795d7ea8..dd455956 100644 --- a/UhooiPicBook/Modules/MonsterDetail/Presenters/MonsterDetailPresenter.swift +++ b/Sources/AppModule/Modules/MonsterDetail/Presenters/MonsterDetailPresenter.swift @@ -6,8 +6,10 @@ // Copyright © 2020 THE Uhooi. All rights reserved. // -import UIKit.UIImage +import class UIKit.UIView +import class UIKit.UIImage +@MainActor protocol MonsterDetailEventHandler: AnyObject { func viewDidLoad() func didTapDancingImageView(dancingImage: UIImage?) @@ -18,50 +20,50 @@ protocol MonsterDetailEventHandler: AnyObject { protocol MonsterDetailInteractorOutput: AnyObject { } -final class MonsterDetailPresenter { - - // MARK: Type Aliases +@MainActor +final class MonsterDetailPresenter< + View: MonsterDetailUserInterface, + Interactor: MonsterDetailInteractorInput, + Router: MonsterDetailRouterInput +> { // MARK: Stored Instance Properties - private unowned let view: MonsterDetailUserInterface - private let interactor: MonsterDetailInteractorInput - private let router: MonsterDetailRouterInput - - // MARK: Computed Instance Properties + private unowned let view: View + private let interactor: Interactor + private let router: Router // MARK: Initializers - init(view: MonsterDetailUserInterface, interactor: MonsterDetailInteractorInput, router: MonsterDetailRouterInput) { + init(view: View, interactor: Interactor, router: Router) { self.view = view self.interactor = interactor self.router = router } - - // MARK: Other Private Methods - } extension MonsterDetailPresenter: MonsterDetailEventHandler { - func viewDidLoad() { } func didTapDancingImageView(dancingImage: UIImage?) { - guard let dancingImage = dancingImage else { + guard let dancingImage else { return } - self.router.popupDancingImage(dancingImage) + router.popupDancingImage(dancingImage) } func didTapShareButton(_ senderView: UIView?, name: String?, description: String?, icon: UIImage?) { - guard let senderView = senderView, let name = name, let description = description, let icon = icon else { + guard let senderView, + let name, + let description, + let icon + else { return // TODO: エラーハンドリング } - let text = "\(name)\n\(description)\n\(R.string.localizable.uhooiPicBookHashtag())" - self.router.showActivity(senderView, text: text, icon: icon) + let text = "\(name)\n\(description)\n\(R.LocalizedString.uhooiPicBookHashtag)" + router.showActivity(senderView, text: text, icon: icon) } - } extension MonsterDetailPresenter: MonsterDetailInteractorOutput { diff --git a/UhooiPicBook/Modules/MonsterDetail/Routers/MonsterDetailRouter.swift b/Sources/AppModule/Modules/MonsterDetail/Routers/MonsterDetailRouter.swift similarity index 60% rename from UhooiPicBook/Modules/MonsterDetail/Routers/MonsterDetailRouter.swift rename to Sources/AppModule/Modules/MonsterDetail/Routers/MonsterDetailRouter.swift index 8164325f..6a37cbe9 100644 --- a/UhooiPicBook/Modules/MonsterDetail/Routers/MonsterDetailRouter.swift +++ b/Sources/AppModule/Modules/MonsterDetail/Routers/MonsterDetailRouter.swift @@ -9,12 +9,14 @@ import UIKit /// @mockable +@MainActor protocol MonsterDetailRouterInput: AnyObject { func popupDancingImage(_ dancingImage: UIImage) func showActivity(_ senderView: UIView, text: String, icon: UIImage) } -final class MonsterDetailRouter { +@MainActor +public final class MonsterDetailRouter { // MARK: Stored Instance Properties @@ -28,34 +30,25 @@ final class MonsterDetailRouter { // MARK: Type Methods - static func assembleModule(monster: MonsterEntity) -> MonsterDetailViewController { - guard let view = R.storyboard.monsterDetail.instantiateInitialViewController() else { - fatalError("Fail to load MonsterDetailViewController from Storyboard.") - } + public static func assembleModule(monster: MonsterItem) -> MonsterDetailViewController { + let view = R.Storyboard.MonsterDetail.instantiateInitialViewController() let interactor = MonsterDetailInteractor() let router = MonsterDetailRouter(viewController: view) let presenter = MonsterDetailPresenter(view: view, interactor: interactor, router: router) - view.presenter = presenter - view.imageCacheManager = ImageCacheManager() - view.monster = monster - interactor.presenter = presenter + view.inject(presenter: presenter, monster: monster) + interactor.inject(presenter: presenter) return view } - - // MARK: Other Private Methods - } extension MonsterDetailRouter: MonsterDetailRouterInput { - func popupDancingImage(_ dancingImage: UIImage) { - ImagePopupRouter.show(self.viewController, image: dancingImage) + ImagePopupRouter.show(viewController, image: dancingImage) } func showActivity(_ senderView: UIView, text: String, icon: UIImage) { - ActivityRouter.show(self.viewController, sourceView: senderView, text: text, url: nil, image: icon) + ActivityRouter.show(viewController, sourceView: senderView, text: text, url: nil, image: icon) } - } diff --git a/UhooiPicBook/Modules/MonsterDetail/Views/MonsterDetail.storyboard b/Sources/AppModule/Modules/MonsterDetail/Views/MonsterDetail.storyboard similarity index 96% rename from UhooiPicBook/Modules/MonsterDetail/Views/MonsterDetail.storyboard rename to Sources/AppModule/Modules/MonsterDetail/Views/MonsterDetail.storyboard index 9326a6b9..88a4d39f 100644 --- a/UhooiPicBook/Modules/MonsterDetail/Views/MonsterDetail.storyboard +++ b/Sources/AppModule/Modules/MonsterDetail/Views/MonsterDetail.storyboard @@ -1,9 +1,9 @@ - + - + @@ -12,7 +12,7 @@ - + @@ -21,7 +21,7 @@ - + @@ -31,16 +31,16 @@ diff --git a/UhooiPicBook/Modules/MonsterDetail/Views/MonsterDetailViewController.swift b/Sources/AppModule/Modules/MonsterDetail/Views/MonsterDetailViewController.swift similarity index 50% rename from UhooiPicBook/Modules/MonsterDetail/Views/MonsterDetailViewController.swift rename to Sources/AppModule/Modules/MonsterDetail/Views/MonsterDetailViewController.swift index 6795c5bd..c644d6c9 100644 --- a/UhooiPicBook/Modules/MonsterDetail/Views/MonsterDetailViewController.swift +++ b/Sources/AppModule/Modules/MonsterDetail/Views/MonsterDetailViewController.swift @@ -7,23 +7,21 @@ // import UIKit +import ImageLoader /// @mockable +@MainActor protocol MonsterDetailUserInterface: AnyObject { } -final class MonsterDetailViewController: UIViewController { - - // MARK: Type Aliases +@MainActor +public final class MonsterDetailViewController: UIViewController { // MARK: Stored Instance Properties - var presenter: MonsterDetailEventHandler! - var imageCacheManager: ImageCacheManagerProtocol! - - var monster: MonsterEntity! + private var presenter: (any MonsterDetailEventHandler)! - // MARK: Computed Instance Properties + private var monster: MonsterItem! // MARK: IBOutlets @@ -51,45 +49,50 @@ final class MonsterDetailViewController: UIViewController { // MARK: View Life-Cycle Methods - override func viewDidLoad() { + override public func viewDidLoad() { super.viewDidLoad() configureView() - self.presenter.viewDidLoad() + presenter.viewDidLoad() } // MARK: IBActions @IBAction private func didTapShareButton(_ sender: UIBarButtonItem) { - self.presenter.didTapShareButton(sender.value(forKey: "view") as? UIView, name: self.nameLabel.text, description: self.descriptionLabel.text, - icon: self.iconImageView.image) + presenter.didTapShareButton( + sender.value(forKey: "view") as? UIView, + name: nameLabel.text, + description: descriptionLabel.text, + icon: iconImageView.image + ) + } + + // MARK: Other Internal Methods + + func inject( + presenter: some MonsterDetailEventHandler, + monster: MonsterItem + ) { + self.presenter = presenter + self.monster = monster } // MARK: Other Private Methods @objc private func didTapDancingImageView(_ sender: UITapGestureRecognizer) { - self.presenter.didTapDancingImageView(dancingImage: self.dancingImageView.image) + presenter.didTapDancingImageView(dancingImage: dancingImageView.image) } private func configureView() { - self.imageCacheManager.cacheImage(imageUrl: monster.iconUrl) { result in - switch result { - case let .success(icon): - DispatchQueue.main.async { - self.iconImageView.image = icon - } - case let .failure(error): - // TODO: エラーハンドリング - print(error) - } + Task { + await iconImageView.loadImage(with: monster.iconURL) } - self.dancingImageView.image = self.imageCacheManager.cacheGIFImage(imageUrl: monster.dancingUrl) - self.nameLabel.text = monster.name - self.descriptionLabel.text = monster.description - self.navigationController?.navigationBar.configureBackgroundColor(.init(hex: monster.baseColorCode)) + nameLabel.text = monster.name + descriptionLabel.text = monster.description + navigationController?.navigationBar.configureBackgroundColor(UIColor(hex: monster.baseColorCode)) + dancingImageView.loadGIFImage(with: monster.dancingURL) } - } extension MonsterDetailViewController: MonsterDetailUserInterface { diff --git a/Sources/AppModule/Modules/MonsterList/Entities/MonsterEntity.swift b/Sources/AppModule/Modules/MonsterList/Entities/MonsterEntity.swift new file mode 100644 index 00000000..fcbcf3b5 --- /dev/null +++ b/Sources/AppModule/Modules/MonsterList/Entities/MonsterEntity.swift @@ -0,0 +1,53 @@ +// +// MonsterEntity.swift +// UhooiPicBook +// +// Created by uhooi on 2020/02/28. +// + +import Foundation +import MonstersRepository + +public struct MonsterEntity { + let name: String + let description: String + let baseColorCode: String + let iconURL: URL + let dancingURL: URL + + // For unit tests + init( + name: String, + description: String, + baseColorCode: String, + iconURL: URL, + dancingURL: URL + ) { + self.name = name + self.description = description + self.baseColorCode = baseColorCode + self.iconURL = iconURL + self.dancingURL = dancingURL + } + + public init(dto: MonsterDTO) { + guard let iconURL = URL(string: dto.iconURLString) else { + fatalError("Fail to load icon.") + } + guard let dancingURL = URL(string: dto.dancingURLString) else { + fatalError("Fail to load dancing image.") + } + + self.name = dto.name + self.description = dto.description.replacingOccurrences(of: "\\n", with: "\n") + self.baseColorCode = dto.baseColorCode + self.iconURL = iconURL + self.dancingURL = dancingURL + } +} + +extension MonsterEntity: Codable {} // For saving in UserDefaults + +extension MonsterEntity: Sendable {} + +extension MonsterEntity: Equatable {} // For unit tests diff --git a/Sources/AppModule/Modules/MonsterList/Entities/MonsterItem.swift b/Sources/AppModule/Modules/MonsterList/Entities/MonsterItem.swift new file mode 100644 index 00000000..4ff74ffe --- /dev/null +++ b/Sources/AppModule/Modules/MonsterList/Entities/MonsterItem.swift @@ -0,0 +1,28 @@ +// +// MonsterItem.swift +// +// +// Created by uhooi on 2022/01/12. +// + +import Foundation + +public struct MonsterItem { + let name: String + let description: String + let baseColorCode: String + let iconURL: URL + let dancingURL: URL + + public init(entity: MonsterEntity) { + self.name = entity.name + self.description = entity.description + self.baseColorCode = entity.baseColorCode + self.iconURL = entity.iconURL + self.dancingURL = entity.dancingURL + } +} + +extension MonsterItem: Hashable {} // For diffable data source + +extension MonsterItem: Sendable {} diff --git a/Sources/AppModule/Modules/MonsterList/Interactors/MonsterListInteractor.swift b/Sources/AppModule/Modules/MonsterList/Interactors/MonsterListInteractor.swift new file mode 100644 index 00000000..59676a57 --- /dev/null +++ b/Sources/AppModule/Modules/MonsterList/Interactors/MonsterListInteractor.swift @@ -0,0 +1,56 @@ +// +// MonsterListInteractor.swift +// UhooiPicBook +// +// Created by uhooi on 28/02/2020. +// Copyright © 2020 THE Uhooi. All rights reserved. +// + +import MonstersRepository + +/// @mockable +protocol MonsterListInteractorInput: AnyObject { + func monsters() async throws -> [MonsterDTO] + func saveMonsterInSpotlight(_ monster: MonsterEntity) async +} + +final class MonsterListInteractor { + + // MARK: Stored Instance Properties + + private weak var presenter: (any MonsterListInteractorOutput)! + + private let spotlightRepository: SR + private let monstersRepository: MR + private let monstersTempRepository: MTR + + // MARK: Initializer + + init( + spotlightRepository: SR, + monstersRepository: MR = MonstersFirestoreClient.shared, + monstersTempRepository: MTR = UserDefaultsClient.shared + ) { + self.spotlightRepository = spotlightRepository + self.monstersRepository = monstersRepository + self.monstersTempRepository = monstersTempRepository + } + + // MARK: Other Internal Methods + + func inject(presenter: some MonsterListInteractorOutput) { + self.presenter = presenter + } +} + +extension MonsterListInteractor: MonsterListInteractorInput { + func monsters() async throws -> [MonsterDTO] { + try await monstersRepository.monsters() + } + + func saveMonsterInSpotlight(_ monster: MonsterEntity) async { + let key = "spotlight_\(monster.name)" + monstersTempRepository.saveMonster(monster, forKey: key) + await spotlightRepository.saveMonster(monster, forKey: key) + } +} diff --git a/Sources/AppModule/Modules/MonsterList/Presenters/MonsterListPresenter.swift b/Sources/AppModule/Modules/MonsterList/Presenters/MonsterListPresenter.swift new file mode 100644 index 00000000..ef6bce50 --- /dev/null +++ b/Sources/AppModule/Modules/MonsterList/Presenters/MonsterListPresenter.swift @@ -0,0 +1,97 @@ +// +// MonsterListPresenter.swift +// UhooiPicBook +// +// Created by uhooi on 28/02/2020. +// Copyright © 2020 THE Uhooi. All rights reserved. +// + +@MainActor +protocol MonsterListEventHandler: AnyObject { + func viewDidLoad() async + + // Menu + func didTapContactUs() + func didTapPrivacyPolicy() + func didTapLicenses() + func didTapAboutThisApp() +} + +@MainActor +protocol MonsterSectionEventHandler: AnyObject { + func didSelectMonster(at row: Int) async +} + +/// @mockable +protocol MonsterListInteractorOutput: AnyObject { +} + +@MainActor +final class MonsterListPresenter< + View: MonsterListUserInterface, + Interactor: MonsterListInteractorInput, + Router: MonsterListRouterInput +> { + + // MARK: Stored Instance Properties + + private unowned let view: View + private let interactor: Interactor + private let router: Router + + private var monsters: [MonsterEntity] = [] + + // MARK: Initializers + + init(view: View, interactor: Interactor, router: Router) { + self.view = view + self.interactor = interactor + self.router = router + } +} + +extension MonsterListPresenter: MonsterListEventHandler { + func viewDidLoad() async { + do { + view.startIndicator() + let monsterDTOs = try await interactor.monsters() + let monsterEntities = monsterDTOs + .sorted { $0.order < $1.order } + .map { MonsterEntity(dto: $0) } + self.monsters = monsterEntities + let monsterItems = monsterEntities.map { MonsterItem(entity: $0) } + view.showMonsters(monsterItems) + view.stopIndicator() + } catch { + // TODO: エラーハンドリング + view.stopIndicator() + } + } + + func didTapContactUs() { + router.showContactUs() + } + + func didTapPrivacyPolicy() { + router.showPrivacyPolicy() + } + + func didTapLicenses() { + router.showSettings() + } + + func didTapAboutThisApp() { + router.showAboutThisApp() + } +} + +extension MonsterListPresenter: MonsterSectionEventHandler { + func didSelectMonster(at row: Int) async { + let entity = monsters[row] + router.showMonsterDetail(monster: MonsterItem(entity: entity)) + await interactor.saveMonsterInSpotlight(entity) + } +} + +extension MonsterListPresenter: MonsterListInteractorOutput { +} diff --git a/Sources/AppModule/Modules/MonsterList/Routers/MonsterListRouter.swift b/Sources/AppModule/Modules/MonsterList/Routers/MonsterListRouter.swift new file mode 100644 index 00000000..1bfebe58 --- /dev/null +++ b/Sources/AppModule/Modules/MonsterList/Routers/MonsterListRouter.swift @@ -0,0 +1,101 @@ +// +// MonsterListRouter.swift +// UhooiPicBook +// +// Created by uhooi on 28/02/2020. +// Copyright © 2020 THE Uhooi. All rights reserved. +// + +import UIKit +import MonstersRepository + +/// @mockable +@MainActor +protocol MonsterListRouterInput: AnyObject { + func showMonsterDetail(monster: MonsterItem) + + // Menu + func showContactUs() + func showPrivacyPolicy() + func showSettings() + func showAboutThisApp() +} + +@MainActor +public final class MonsterListRouter { + + // MARK: Stored Instance Properties + + private unowned let viewController: MonsterListViewController + + // MARK: Initializers + + private init(viewController: MonsterListViewController) { + self.viewController = viewController + } + + // MARK: Type Methods + + public static func assembleModule() -> MonsterListViewController { + let view = R.Storyboard.MonsterList.instantiateInitialViewController() + typealias SC = SpotlightClient // swiftlint:disable:this type_name + let interactor = MonsterListInteractor< + SC, + MonstersFirestoreClient, + UserDefaultsClient + >(spotlightRepository: SC()) + let router = MonsterListRouter(viewController: view) + let presenter = MonsterListPresenter(view: view, interactor: interactor, router: router) + + let sections: [any CollectionSectionProtocol] = [ + MonsterCollectionSection(presenter: presenter) + ] + view.inject(presenter: presenter, sections: sections) + interactor.inject(presenter: presenter) + + return view + } +} + +extension MonsterListRouter: MonsterListRouterInput { + func showMonsterDetail(monster: MonsterItem) { + let vc = MonsterDetailRouter.assembleModule(monster: monster) + viewController.navigationController?.pushViewController(vc, animated: true) + } + + func showContactUs() { + guard let contactUsURL = URL(string: R.LocalizedString.contactUsURL) else { + fatalError("Fail to initialize contact us URL.") + } + InAppWebBrowserRouter.show(viewController, url: contactUsURL) + } + + func showPrivacyPolicy() { + guard let privacyPolicyURL = URL(string: R.LocalizedString.privacyPolicyURL) else { + fatalError("Fail to initialize privacy policy URL.") + } + UIApplication.shared.open(privacyPolicyURL) + } + + func showSettings() { + guard let settingsURL = URL(string: UIApplication.openSettingsURLString), + UIApplication.shared.canOpenURL(settingsURL) + else { + fatalError("Fail to open Settings URL.") + } + UIApplication.shared.open(settingsURL) + } + + func showAboutThisApp() { + let title = Bundle.main.displayName + let message = """ +\(R.LocalizedString.thisAppIsOpenSourceSoftware) +\(R.LocalizedString.uhooiPicBookGitHubURL) + +\(R.LocalizedString.version) \(Bundle.main.version) (\(Bundle.main.build)) +\(R.LocalizedString.copyright) +""" + let okAction = UIAlertAction(title: R.LocalizedString.oK, style: .default) { _ in } + viewController.showAlert(title: title, message: message, actions: [okAction]) + } +} diff --git a/Sources/AppModule/Modules/MonsterList/Views/MonsterCollectionSection.swift b/Sources/AppModule/Modules/MonsterList/Views/MonsterCollectionSection.swift new file mode 100644 index 00000000..0c1fc0e1 --- /dev/null +++ b/Sources/AppModule/Modules/MonsterList/Views/MonsterCollectionSection.swift @@ -0,0 +1,44 @@ +// +// MonsterCollectionSection.swift +// +// +// Created by uhooi on 2022/01/11. +// + +import UIKit + +@MainActor +final class MonsterCollectionSection { + private unowned let presenter: Presenter + + init(presenter: Presenter) { + self.presenter = presenter + } +} + +extension MonsterCollectionSection: CollectionSectionProtocol { + func layoutSection() -> NSCollectionLayoutSection { + let itemSize = NSCollectionLayoutSize( + widthDimension: .fractionalWidth(1.0), + heightDimension: .fractionalHeight(1.0) + ) + let item = NSCollectionLayoutItem(layoutSize: itemSize) + + let groupSize = NSCollectionLayoutSize( + widthDimension: .fractionalWidth(1.0), + heightDimension: .absolute(116.0) + ) + let group = NSCollectionLayoutGroup.vertical(layoutSize: groupSize, subitems: [item]) + + let section = NSCollectionLayoutSection(group: group) + section.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: 16.0, bottom: 0, trailing: 16.0) + section.interGroupSpacing = 12.0 + return section + } + + func didSelectItem(at row: Int) { + Task { + await presenter.didSelectMonster(at: row) + } + } +} diff --git a/UhooiPicBook/Modules/MonsterList/Views/MonsterCollectionViewCell.swift b/Sources/AppModule/Modules/MonsterList/Views/MonsterCollectionViewCell.swift similarity index 67% rename from UhooiPicBook/Modules/MonsterList/Views/MonsterCollectionViewCell.swift rename to Sources/AppModule/Modules/MonsterList/Views/MonsterCollectionViewCell.swift index bbb78d62..c02c860d 100644 --- a/UhooiPicBook/Modules/MonsterList/Views/MonsterCollectionViewCell.swift +++ b/Sources/AppModule/Modules/MonsterList/Views/MonsterCollectionViewCell.swift @@ -7,13 +7,14 @@ import UIKit +@MainActor final class MonsterCollectionViewCell: UICollectionViewCell { // MARK: Stored Instance Properties @IBInspectable private var masksToBounds: Bool = false { willSet { - self.layer.masksToBounds = newValue + layer.masksToBounds = newValue } } @@ -32,16 +33,17 @@ final class MonsterCollectionViewCell: UICollectionViewCell { override func prepareForReuse() { super.prepareForReuse() - self.iconImageView.image = nil - self.nameLabel.text = nil + iconImageView.image = nil + nameLabel.text = nil } // MARK: Other Internal Methods - func setup(name: String, icon: UIImage, elevation: Double) { - self.nameLabel.text = name - self.iconImageView.image = icon - self.baseView.elevate(elevation: elevation) + func setupWith(name: String, iconURL: URL, elevation: Double) { + nameLabel.text = name + baseView.elevate(elevation: elevation) + Task { + await iconImageView.loadImage(with: iconURL) + } } - } diff --git a/UhooiPicBook/Modules/MonsterList/Views/MonsterCollectionViewCell.xib b/Sources/AppModule/Modules/MonsterList/Views/MonsterCollectionViewCell.xib similarity index 87% rename from UhooiPicBook/Modules/MonsterList/Views/MonsterCollectionViewCell.xib rename to Sources/AppModule/Modules/MonsterList/Views/MonsterCollectionViewCell.xib index b841e572..6bac7e85 100644 --- a/UhooiPicBook/Modules/MonsterList/Views/MonsterCollectionViewCell.xib +++ b/Sources/AppModule/Modules/MonsterList/Views/MonsterCollectionViewCell.xib @@ -1,15 +1,17 @@ - + - + + + - + @@ -20,8 +22,8 @@ @@ -33,7 +35,7 @@ - + @@ -48,13 +50,13 @@ + - @@ -66,4 +68,9 @@ + + + + + diff --git a/UhooiPicBook/Modules/MonsterList/Views/MonsterList.storyboard b/Sources/AppModule/Modules/MonsterList/Views/MonsterList.storyboard similarity index 62% rename from UhooiPicBook/Modules/MonsterList/Views/MonsterList.storyboard rename to Sources/AppModule/Modules/MonsterList/Views/MonsterList.storyboard index 976dc6b0..ef6c6db3 100644 --- a/UhooiPicBook/Modules/MonsterList/Views/MonsterList.storyboard +++ b/Sources/AppModule/Modules/MonsterList/Views/MonsterList.storyboard @@ -1,9 +1,9 @@ - + - + @@ -12,26 +12,11 @@ - + - - - - - - - - - - - - - - - @@ -41,10 +26,6 @@ - - - - @@ -57,7 +38,6 @@ - diff --git a/Sources/AppModule/Modules/MonsterList/Views/MonsterListViewController.swift b/Sources/AppModule/Modules/MonsterList/Views/MonsterListViewController.swift new file mode 100644 index 00000000..15555cd5 --- /dev/null +++ b/Sources/AppModule/Modules/MonsterList/Views/MonsterListViewController.swift @@ -0,0 +1,167 @@ +// +// MonsterListViewController.swift +// UhooiPicBook +// +// Created by uhooi on 28/02/2020. +// Copyright © 2020 THE Uhooi. All rights reserved. +// + +import UIKit + +/// @mockable +@MainActor +protocol MonsterListUserInterface: AnyObject { + func showMonsters(_ monsters: [MonsterItem]) + func startIndicator() + func stopIndicator() +} + +@MainActor +public final class MonsterListViewController: UIViewController { + + // MARK: Enums + + private enum Section: Int, CaseIterable { + case monster + } + + private enum Item: Hashable { + case monster(_ monster: MonsterItem) + } + + // MARK: Stored Instance Properties + + private var presenter: (any MonsterListEventHandler)! + + private var sections: [any CollectionSectionProtocol]! + + private lazy var monstersCollectionView: UICollectionView = { + let layout = UICollectionViewCompositionalLayout { [weak self] section, _ in + self?.sections[section].layoutSection() + } + let collectionView = UICollectionView(frame: .null, collectionViewLayout: layout) + collectionView.backgroundColor = .systemBackground + return collectionView + }() + + private lazy var dataSource: UICollectionViewDiffableDataSource = { + let monsterCellRegistration = UICollectionView.CellRegistration( + cellNib: R.Nib.monsterCollectionViewCell) { cell, _, monster in + cell.setupWith(name: monster.name, iconURL: monster.iconURL, elevation: 1.0) + } + + return .init(collectionView: monstersCollectionView) { collectionView, indexPath, item in + switch item { + case let .monster(monster): + return collectionView.dequeueConfiguredReusableCell( + using: monsterCellRegistration, + for: indexPath, + item: monster + ) + } + } + }() + + // MARK: IBOutlets + + @IBOutlet private weak var menuButton: UIBarButtonItem! { + willSet { + newValue.menu = UIMenu( + title: "", + children: [ + UIAction(title: R.LocalizedString.contactUs) { [weak self] _ in + self?.presenter.didTapContactUs() + }, + UIAction(title: R.LocalizedString.privacyPolicy) { [weak self] _ in + self?.presenter.didTapPrivacyPolicy() + }, + UIAction(title: R.LocalizedString.licenses) { [weak self] _ in + self?.presenter.didTapLicenses() + }, + UIAction(title: R.LocalizedString.aboutThisApp) { [weak self] _ in + self?.presenter.didTapAboutThisApp() + } + ] + ) + } + } + + @IBOutlet private weak var activityIndicatorView: UIActivityIndicatorView! + + // MARK: View Life-Cycle Methods + + override public func viewDidLoad() { + super.viewDidLoad() + + navigationController?.navigationBar.tintColor = .white + configureMonstersCollectionView() + + Task { + await presenter.viewDidLoad() + } + } + + override public func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + + navigationController?.navigationBar.configureBackgroundColor(R.Color.navigationBar) + } + + // MARK: Other Internal Methods + + func inject( + presenter: some MonsterListEventHandler, + sections: [any CollectionSectionProtocol] + ) { + self.presenter = presenter + self.sections = sections + } + + // MARK: Other Private Methods + + private func configureMonstersCollectionView() { + monstersCollectionView.delegate = self + + view.addSubview(monstersCollectionView) + monstersCollectionView.translatesAutoresizingMaskIntoConstraints = false + + NSLayoutConstraint.activate([ + monstersCollectionView.leadingAnchor.constraint(equalTo: view.leadingAnchor), + monstersCollectionView.trailingAnchor.constraint(equalTo: view.trailingAnchor), + monstersCollectionView.topAnchor.constraint(equalTo: view.topAnchor), + monstersCollectionView.bottomAnchor.constraint(equalTo: view.bottomAnchor) + ]) + } + + private func applyToDataSource(monsters: [MonsterItem]) { + var snapshot = NSDiffableDataSourceSnapshot() + snapshot.appendSections(Section.allCases) + + let monsterItems: [Item] = monsters.map { .monster($0) } + snapshot.appendItems(monsterItems, toSection: .monster) + + dataSource.apply(snapshot, animatingDifferences: false) + } +} + +extension MonsterListViewController: UICollectionViewDelegate { + public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { + sections[indexPath.section].didSelectItem(at: indexPath.row) + } +} + +extension MonsterListViewController: MonsterListUserInterface { + func showMonsters(_ monsters: [MonsterItem]) { + applyToDataSource(monsters: monsters) + monstersCollectionView.executeCellSlideUpAnimation() + } + + func startIndicator() { + view.bringSubviewToFront(activityIndicatorView) + activityIndicatorView.startAnimating() + } + + func stopIndicator() { + activityIndicatorView.stopAnimating() + } +} diff --git a/Sources/AppModule/R.swift b/Sources/AppModule/R.swift new file mode 100644 index 00000000..9172f6f0 --- /dev/null +++ b/Sources/AppModule/R.swift @@ -0,0 +1,121 @@ +// +// R.swift +// +// +// Created by uhooi on 2022/01/10. +// + +import UIKit + +enum R { // swiftlint:disable:this type_name + enum LocalizedString { + + // MARK: Internal Stored Type Properties + + // Monster detail + static let uhooiPicBookHashtag = string(localized: "UhooiPicBook hashtag") + + // Menu + static let contactUs = string(localized: "Contact us") + static let privacyPolicy = string(localized: "Privacy policy") + static let licenses = string(localized: "Licenses") + static let aboutThisApp = string(localized: "About this app") + + // Contact us + static let contactUsURL = string(localized: "Contact us URL") + + // Privacy policy + static let privacyPolicyURL = string(localized: "Privacy policy URL") + + // About this app + static let thisAppIsOpenSourceSoftware = string(localized: "This app is open source software") + static let uhooiPicBookGitHubURL = string(localized: "UhooiPicBook GitHub URL") + static let version = string(localized: "Version") + static let copyright = string(localized: "Copyright") + + // Alert + static let oK = string(localized: "OK") + + // MARK: Other Private Type Methods + + private static func string(localized keyAndValue: String.LocalizationValue) -> String { + String(localized: keyAndValue, bundle: .module) + } + } + + enum Color { + + // MARK: Internal Stored Type Properties + + static let navigationBar = uiColor(named: "NavigationBar") + + // MARK: Other Private Type Methods + + private static func uiColor(named name: String) -> UIColor { + guard let color = UIColor(named: name, in: .module, compatibleWith: nil) else { + fatalError("Fail to load '\(name)' color.") + } + return color + } + } + + @MainActor + enum Storyboard { + + // MARK: Enums + + // swiftlint:disable nesting + @MainActor + enum MonsterList { + static func instantiateInitialViewController() -> MonsterListViewController { + Storyboard.instantiateInitialViewController(named: "MonsterList") + } + } + @MainActor + enum MonsterDetail { + static func instantiateInitialViewController() -> MonsterDetailViewController { + Storyboard.instantiateInitialViewController(named: "MonsterDetail") + } + } + @MainActor + enum ImagePopup { + static func instantiateInitialViewController() -> ImagePopupViewController { + Storyboard.instantiateInitialViewController(named: "ImagePopup") + } + } + @MainActor + enum InAppWebBrowser { + static func instantiateInitialViewController() -> InAppWebBrowserViewController { + Storyboard.instantiateInitialViewController(named: "InAppWebBrowser") + } + } + // swiftlint:enable nesting + + // MARK: Other Private Type Methods + + private static func instantiateInitialViewController(named name: String) -> T { + guard let vc = uiStoryboard(name: name).instantiateInitialViewController() as? T else { + fatalError("Fail to load \(T.self) from '\(name)' Storyboard.") + } + return vc + } + + private static func uiStoryboard(name: String) -> UIStoryboard { + UIStoryboard(name: name, bundle: .module) + } + } + + @MainActor + enum Nib { + + // MARK: Internal Stored Type Properties + + static let monsterCollectionViewCell = uiNib(name: "MonsterCollectionViewCell") + + // MARK: Other Private Type Methods + + private static func uiNib(name: String) -> UINib { + UINib(nibName: name, bundle: .module) + } + } +} diff --git a/Sources/AppModule/Repository/Spotlight/SpotlightRepository.swift b/Sources/AppModule/Repository/Spotlight/SpotlightRepository.swift new file mode 100644 index 00000000..c27e6f86 --- /dev/null +++ b/Sources/AppModule/Repository/Spotlight/SpotlightRepository.swift @@ -0,0 +1,66 @@ +// +// SpotlightRepository.swift +// UhooiPicBook +// +// Created by Tomosuke Okada on 2020/05/11. +// + +import class UIKit.UIImage +import CoreGraphics.CGGeometry +import CoreSpotlight +import ImageLoader +import Logger + +/// @mockable +protocol SpotlightRepository: AnyObject { // swiftlint:disable:this file_types_order + func saveMonster(_ monster: MonsterEntity, forKey key: String) async +} + +final class SpotlightClient { + + // MARK: Stored Instance Properties + + private let searchableIndex = CSSearchableIndex.default() + private let logger: LP + + // MARK: Initializer + + init(logger: LP = Logger.default) { + self.logger = logger + } +} + +extension SpotlightClient: SpotlightRepository { + func saveMonster(_ monster: MonsterEntity, forKey key: String) async { + guard let icon = await UIImage.create(with: monster.iconURL) else { + return + } + let thumbnailData = icon.resize(CGSize(width: 180.0, height: 180.0))?.pngData() + let item = CSSearchableItem( + uniqueIdentifier: key, + domainIdentifier: Bundle.main.infoDictionary?[kCFBundleNameKey as String] as? String, + attributeSet: attributeSet( + title: monster.name, + contentDescription: monster.description, + thumbnailData: thumbnailData + ) + ) + do { + try await searchableIndex.indexSearchableItems([item]) + } catch { + // No need for error handling, as there is no need to give the user feedback on save failures for Spotlight search. + logger.exception(error, file: #file, function: #function, line: #line, column: #column) + return + } + } + + // MARK: Other Private Methods + + private func attributeSet(title: String, contentDescription: String, thumbnailData: Data?) -> CSSearchableItemAttributeSet { + let attributeSet = CSSearchableItemAttributeSet(contentType: .data) + attributeSet.title = title + attributeSet.contentDescription = contentDescription + attributeSet.thumbnailData = thumbnailData + return attributeSet + } +} diff --git a/UhooiPicBook/Repository/Temp/TempRepository.swift b/Sources/AppModule/Repository/Temp/TempRepository.swift similarity index 82% rename from UhooiPicBook/Repository/Temp/TempRepository.swift rename to Sources/AppModule/Repository/Temp/TempRepository.swift index 19f20c0a..f10b5d80 100644 --- a/UhooiPicBook/Repository/Temp/TempRepository.swift +++ b/Sources/AppModule/Repository/Temp/TempRepository.swift @@ -8,6 +8,6 @@ /// @mockable protocol MonstersTempRepository { - func loadMonster(key: String) -> MonsterEntity? + func monster(key: String) -> MonsterEntity? func saveMonster(_ monster: MonsterEntity, forKey key: String) } diff --git a/Sources/AppModule/Repository/Temp/UserDefaultsClient.swift b/Sources/AppModule/Repository/Temp/UserDefaultsClient.swift new file mode 100644 index 00000000..6d0c9b57 --- /dev/null +++ b/Sources/AppModule/Repository/Temp/UserDefaultsClient.swift @@ -0,0 +1,47 @@ +// +// UserDefaultsClient.swift +// UhooiPicBook +// +// Created by uhooi on 2020/05/12. +// + +import Foundation + +public final class UserDefaultsClient { + + // MARK: Stored Type Properties + + public static let shared = UserDefaultsClient() + + // MARK: Stored Instance Properties + + private let userDefaults = UserDefaults.standard + + // MARK: Initializers + + private init() {} + + // MARK: Other Internal Methods + + // For unit tests + func removeAll() { + userDefaults.dictionaryRepresentation().keys.forEach { userDefaults.removeObject(forKey: $0) } + } +} + +extension UserDefaultsClient: MonstersTempRepository { + public func monster(key: String) -> MonsterEntity? { + guard let data = userDefaults.data(forKey: key), + let monster = try? JSONDecoder().decode(MonsterEntity.self, from: data) else { + return nil + } + return monster + } + + func saveMonster(_ monster: MonsterEntity, forKey key: String) { + guard let data = try? JSONEncoder().encode(monster) else { + return + } + userDefaults.set(data, forKey: key) + } +} diff --git a/UhooiPicBook/Resources/Assets.xcassets/Colors/Contents.json b/Sources/AppModule/Resources/Assets.xcassets/Colors/Contents.json similarity index 100% rename from UhooiPicBook/Resources/Assets.xcassets/Colors/Contents.json rename to Sources/AppModule/Resources/Assets.xcassets/Colors/Contents.json diff --git a/UhooiPicBook/Resources/Assets.xcassets/Colors/Functional/Contents.json b/Sources/AppModule/Resources/Assets.xcassets/Colors/Functional/Contents.json similarity index 100% rename from UhooiPicBook/Resources/Assets.xcassets/Colors/Functional/Contents.json rename to Sources/AppModule/Resources/Assets.xcassets/Colors/Functional/Contents.json diff --git a/UhooiPicBook/Resources/Assets.xcassets/Colors/Functional/ImagePopupBackground.colorset/Contents.json b/Sources/AppModule/Resources/Assets.xcassets/Colors/Functional/ImagePopupBackground.colorset/Contents.json similarity index 100% rename from UhooiPicBook/Resources/Assets.xcassets/Colors/Functional/ImagePopupBackground.colorset/Contents.json rename to Sources/AppModule/Resources/Assets.xcassets/Colors/Functional/ImagePopupBackground.colorset/Contents.json diff --git a/UhooiPicBook/Resources/Assets.xcassets/Colors/Functional/NavigationBar.colorset/Contents.json b/Sources/AppModule/Resources/Assets.xcassets/Colors/Functional/NavigationBar.colorset/Contents.json similarity index 100% rename from UhooiPicBook/Resources/Assets.xcassets/Colors/Functional/NavigationBar.colorset/Contents.json rename to Sources/AppModule/Resources/Assets.xcassets/Colors/Functional/NavigationBar.colorset/Contents.json diff --git a/Sources/AppModule/Resources/Assets.xcassets/Contents.json b/Sources/AppModule/Resources/Assets.xcassets/Contents.json new file mode 100644 index 00000000..73c00596 --- /dev/null +++ b/Sources/AppModule/Resources/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/UhooiPicBook/Resources/en.lproj/Localizable.strings b/Sources/AppModule/Resources/en.lproj/Localizable.strings similarity index 100% rename from UhooiPicBook/Resources/en.lproj/Localizable.strings rename to Sources/AppModule/Resources/en.lproj/Localizable.strings diff --git a/UhooiPicBook/Resources/ja.lproj/Localizable.strings b/Sources/AppModule/Resources/ja.lproj/Localizable.strings similarity index 100% rename from UhooiPicBook/Resources/ja.lproj/Localizable.strings rename to Sources/AppModule/Resources/ja.lproj/Localizable.strings diff --git a/UhooiPicBook/UIParts/Activity/ActivityRouter.swift b/Sources/AppModule/UIParts/Activity/ActivityRouter.swift similarity index 98% rename from UhooiPicBook/UIParts/Activity/ActivityRouter.swift rename to Sources/AppModule/UIParts/Activity/ActivityRouter.swift index 8a0130dc..b86c87d1 100644 --- a/UhooiPicBook/UIParts/Activity/ActivityRouter.swift +++ b/Sources/AppModule/UIParts/Activity/ActivityRouter.swift @@ -7,6 +7,7 @@ import UIKit +@MainActor enum ActivityRouter { // MARK: Type Methods @@ -20,5 +21,4 @@ enum ActivityRouter { activityVC.popoverPresentationController?.sourceView = sourceView parent.present(activityVC, animated: true) } - } diff --git a/UhooiPicBook/UIParts/BaseView.swift b/Sources/AppModule/UIParts/BaseView.swift similarity index 84% rename from UhooiPicBook/UIParts/BaseView.swift rename to Sources/AppModule/UIParts/BaseView.swift index 69b2f329..1f123ddc 100644 --- a/UhooiPicBook/UIParts/BaseView.swift +++ b/Sources/AppModule/UIParts/BaseView.swift @@ -8,14 +8,14 @@ import UIKit @IBDesignable +@MainActor final class BaseView: UIView { // MARK: Stored Instance Properties @IBInspectable private var cornerRadius: CGFloat = 0.0 { willSet { - self.layer.cornerRadius = newValue + layer.cornerRadius = newValue } } - } diff --git a/Sources/AppModule/UIParts/CollectionSectionProtocol.swift b/Sources/AppModule/UIParts/CollectionSectionProtocol.swift new file mode 100644 index 00000000..b15b6fdc --- /dev/null +++ b/Sources/AppModule/UIParts/CollectionSectionProtocol.swift @@ -0,0 +1,14 @@ +// +// CollectionSectionProtocol.swift +// +// +// Created by uhooi on 2022/01/11. +// + +import UIKit + +@MainActor +protocol CollectionSectionProtocol { + func layoutSection() -> NSCollectionLayoutSection + func didSelectItem(at row: Int) +} diff --git a/UhooiPicBook/UIParts/ImagePopup/ImagePopup.storyboard b/Sources/AppModule/UIParts/ImagePopup/ImagePopup.storyboard similarity index 96% rename from UhooiPicBook/UIParts/ImagePopup/ImagePopup.storyboard rename to Sources/AppModule/UIParts/ImagePopup/ImagePopup.storyboard index 9cff82d7..9a1900e6 100644 --- a/UhooiPicBook/UIParts/ImagePopup/ImagePopup.storyboard +++ b/Sources/AppModule/UIParts/ImagePopup/ImagePopup.storyboard @@ -1,9 +1,9 @@ - + - + @@ -12,7 +12,7 @@ - + diff --git a/UhooiPicBook/UIParts/ImagePopup/ImagePopupRouter.swift b/Sources/AppModule/UIParts/ImagePopup/ImagePopupRouter.swift similarity index 73% rename from UhooiPicBook/UIParts/ImagePopup/ImagePopupRouter.swift rename to Sources/AppModule/UIParts/ImagePopup/ImagePopupRouter.swift index eeb636b0..988c745d 100644 --- a/UhooiPicBook/UIParts/ImagePopup/ImagePopupRouter.swift +++ b/Sources/AppModule/UIParts/ImagePopup/ImagePopupRouter.swift @@ -7,6 +7,7 @@ import UIKit +@MainActor enum ImagePopupRouter { // MARK: Type Methods @@ -19,12 +20,9 @@ enum ImagePopupRouter { // MARK: Other Private Methods private static func assembleModule(image: UIImage) -> ImagePopupViewController { - guard let view = R.storyboard.imagePopup.instantiateInitialViewController() else { - fatalError("Fail to load ImagePopupViewController from Storyboard.") - } + let view = R.Storyboard.ImagePopup.instantiateInitialViewController() view.image = image return view } - } diff --git a/UhooiPicBook/UIParts/ImagePopup/ImagePopupViewController.swift b/Sources/AppModule/UIParts/ImagePopup/ImagePopupViewController.swift similarity index 86% rename from UhooiPicBook/UIParts/ImagePopup/ImagePopupViewController.swift rename to Sources/AppModule/UIParts/ImagePopup/ImagePopupViewController.swift index 90355021..39bbc007 100644 --- a/UhooiPicBook/UIParts/ImagePopup/ImagePopupViewController.swift +++ b/Sources/AppModule/UIParts/ImagePopup/ImagePopupViewController.swift @@ -7,16 +7,13 @@ import UIKit +@MainActor final class ImagePopupViewController: UIViewController { - // MARK: Type Aliases - // MARK: Stored Instance Properties var image: UIImage! - // MARK: Computed Instance Properties - // MARK: IBOutlets @IBOutlet private weak var imageView: UIImageView! { @@ -42,7 +39,6 @@ final class ImagePopupViewController: UIViewController { // MARK: Other Private Methods private func configureView() { - self.imageView.image = image + imageView.image = image } - } diff --git a/UhooiPicBook/UIParts/InAppWebBrowser/InAppWebBrowser.storyboard b/Sources/AppModule/UIParts/InAppWebBrowser/InAppWebBrowser.storyboard similarity index 94% rename from UhooiPicBook/UIParts/InAppWebBrowser/InAppWebBrowser.storyboard rename to Sources/AppModule/UIParts/InAppWebBrowser/InAppWebBrowser.storyboard index fe011ea7..2b7f1443 100644 --- a/UhooiPicBook/UIParts/InAppWebBrowser/InAppWebBrowser.storyboard +++ b/Sources/AppModule/UIParts/InAppWebBrowser/InAppWebBrowser.storyboard @@ -1,9 +1,9 @@ - + - + @@ -12,7 +12,7 @@ - + diff --git a/UhooiPicBook/UIParts/InAppWebBrowser/InAppWebBrowserRouter.swift b/Sources/AppModule/UIParts/InAppWebBrowser/InAppWebBrowserRouter.swift similarity index 73% rename from UhooiPicBook/UIParts/InAppWebBrowser/InAppWebBrowserRouter.swift rename to Sources/AppModule/UIParts/InAppWebBrowser/InAppWebBrowserRouter.swift index e6bd987c..6c4cdfbc 100644 --- a/UhooiPicBook/UIParts/InAppWebBrowser/InAppWebBrowserRouter.swift +++ b/Sources/AppModule/UIParts/InAppWebBrowser/InAppWebBrowserRouter.swift @@ -8,6 +8,7 @@ import UIKit +@MainActor enum InAppWebBrowserRouter { // MARK: Type Methods @@ -20,12 +21,9 @@ enum InAppWebBrowserRouter { // MARK: Other Private Methods private static func assembleModule(url: URL) -> InAppWebBrowserViewController { - guard let view = R.storyboard.inAppWebBrowser.instantiateInitialViewController() else { - fatalError("Fail to load InAppWebBrowserViewController from Storyboard.") - } + let view = R.Storyboard.InAppWebBrowser.instantiateInitialViewController() view.url = url return view } - } diff --git a/UhooiPicBook/UIParts/InAppWebBrowser/InAppWebBrowserViewController.swift b/Sources/AppModule/UIParts/InAppWebBrowser/InAppWebBrowserViewController.swift similarity index 50% rename from UhooiPicBook/UIParts/InAppWebBrowser/InAppWebBrowserViewController.swift rename to Sources/AppModule/UIParts/InAppWebBrowser/InAppWebBrowserViewController.swift index 70ee0b80..a3c75f95 100644 --- a/UhooiPicBook/UIParts/InAppWebBrowser/InAppWebBrowserViewController.swift +++ b/Sources/AppModule/UIParts/InAppWebBrowser/InAppWebBrowserViewController.swift @@ -9,10 +9,9 @@ import UIKit import WebKit +@MainActor final class InAppWebBrowserViewController: UIViewController { - // MARK: Type Aliases - // MARK: Stored Instance Properties var url: URL! @@ -20,8 +19,6 @@ final class InAppWebBrowserViewController: UIViewController { private var progressView = UIProgressView(progressViewStyle: .bar) private var estimatedProgressObservation: NSKeyValueObservation? - // MARK: Computed Instance Properties - // MARK: IBOutlets @IBOutlet private weak var webView: WKWebView! @@ -35,8 +32,6 @@ final class InAppWebBrowserViewController: UIViewController { loadWebView() } - // MARK: IBActions - // MARK: Other Private Methods private func configureView() { @@ -45,8 +40,8 @@ final class InAppWebBrowserViewController: UIViewController { } private func configureProgressView() { - self.progressView.frame = CGRect(x: 0.0, y: 0.0, width: self.view.frame.size.width, height: 0.0) - self.view.addSubview(self.progressView) + progressView.frame = CGRect(x: 0.0, y: 0.0, width: self.view.frame.size.width, height: 0.0) + view.addSubview(progressView) } private func configureWebView() { @@ -54,33 +49,24 @@ final class InAppWebBrowserViewController: UIViewController { } private func observeWebView() { - self.estimatedProgressObservation = self.webView.observe(\.estimatedProgress, options: [.new]) { webView, _ in - // swiftlint:disable:next trailing_closure - UIView.animate( - withDuration: 0.33, - animations: { - self.progressView.alpha = 1.0 - } - ) - self.progressView.setProgress(Float(webView.estimatedProgress), animated: true) + estimatedProgressObservation = webView.observe(\.estimatedProgress, options: [.new]) { @MainActor [weak self] webView, _ in + UIView.animate(withDuration: 0.33) { [weak self] in + self?.progressView.alpha = 1.0 + } + self?.progressView.setProgress(Float(webView.estimatedProgress), animated: true) if webView.estimatedProgress >= 1.0 { - UIView.animate( - withDuration: 0.33, - animations: { - self.progressView.alpha = 0.0 - }, - completion: { _ in - self.progressView.setProgress(0.0, animated: false) - } - ) + UIView.animate(withDuration: 0.33) { [weak self] in + self?.progressView.alpha = 0.0 + } completion: { [weak self] _ in + self?.progressView.setProgress(0.0, animated: false) + } } } } private func loadWebView() { - let request = URLRequest(url: self.url) - self.webView.load(request) + let request = URLRequest(url: url) + _ = webView.load(request) } - } diff --git a/Sources/AppModuleTests.xctestplan b/Sources/AppModuleTests.xctestplan new file mode 100644 index 00000000..504ff612 --- /dev/null +++ b/Sources/AppModuleTests.xctestplan @@ -0,0 +1,52 @@ +{ + "configurations" : [ + { + "id" : "46FAD0A7-ED9D-499A-B76E-7804ABC07C74", + "name" : "English", + "options" : { + "language" : "en", + "locationScenario" : { + "identifier" : "New York, NY, USA", + "referenceType" : "built-in" + }, + "region" : "US" + } + }, + { + "id" : "EC121CEA-82D0-46F6-8DE2-770C04BABD7B", + "name" : "Japanese", + "options" : { + "language" : "ja", + "locationScenario" : { + "identifier" : "Tokyo, Japan", + "referenceType" : "built-in" + }, + "region" : "JP" + } + } + ], + "defaultOptions" : { + "codeCoverage" : { + "targets" : [ + { + "containerPath" : "container:", + "identifier" : "AppModule", + "name" : "AppModule" + } + ] + }, + "defaultTestExecutionTimeAllowance" : 60, + "testTimeoutsEnabled" : true + }, + "testTargets" : [ + { + "parallelizable" : true, + "target" : { + "containerPath" : "container:", + "identifier" : "AppModuleTests", + "name" : "AppModuleTests" + } + } + ], + "version" : 1 +} diff --git a/Sources/FirebaseMessagingBridge/FirebaseMessagingBridge.swift b/Sources/FirebaseMessagingBridge/FirebaseMessagingBridge.swift new file mode 100644 index 00000000..cc873af6 --- /dev/null +++ b/Sources/FirebaseMessagingBridge/FirebaseMessagingBridge.swift @@ -0,0 +1,28 @@ +// +// FirebaseMessagingBridge.swift +// +// +// Created by uhooi on 2022/01/06. +// + +import FirebaseMessaging + +public protocol MessagingBridgeDelegate: AnyObject { + @MainActor func didReceiveRegistrationToken(_ fcmToken: String?) +} + +@MainActor +public final class FirebaseMessagingBridge: NSObject { + public weak var delegate: (any MessagingBridgeDelegate)? + + override public init() { + super.init() + Messaging.messaging().delegate = self + } +} + +extension FirebaseMessagingBridge: MessagingDelegate { + public func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) { + delegate?.didReceiveRegistrationToken(fcmToken) + } +} diff --git a/Sources/FirebaseSetup/FirebaseSetup.swift b/Sources/FirebaseSetup/FirebaseSetup.swift new file mode 100644 index 00000000..5a4d1d1e --- /dev/null +++ b/Sources/FirebaseSetup/FirebaseSetup.swift @@ -0,0 +1,14 @@ +// +// FirebaseSetup.swift +// +// +// Created by uhooi on 2022/01/05. +// + +import FirebaseCore + +public enum FirebaseSetup { + public static func configure() { + FirebaseApp.configure() + } +} diff --git a/Sources/ImageLoader/Core/ImageCacheError.swift b/Sources/ImageLoader/Core/ImageCacheError.swift new file mode 100644 index 00000000..c5f28de3 --- /dev/null +++ b/Sources/ImageLoader/Core/ImageCacheError.swift @@ -0,0 +1,10 @@ +// +// ImageCacheError.swift +// +// +// Created by uhooi on 2022/01/05. +// + +enum ImageCacheError: Error { + case loadingFailure +} diff --git a/Sources/ImageLoader/Core/ImageCacheManager.swift b/Sources/ImageLoader/Core/ImageCacheManager.swift new file mode 100644 index 00000000..03f8ef18 --- /dev/null +++ b/Sources/ImageLoader/Core/ImageCacheManager.swift @@ -0,0 +1,40 @@ +// +// ImageCacheManager.swift +// UhooiPicBook +// +// Created by uhooi on 2020/03/03. +// + +import Foundation +import class UIKit.UIImage + +final class ImageCacheManager { + static let imageCache = NSCache() + + func cacheImage(with url: URL) async throws -> UIImage { + if let imageFromCache = Self.imageCache.object(forKey: url as AnyObject) as? UIImage { + return imageFromCache + } + + let (data, _) = try await URLSession.shared.data(from: url) + guard let image = UIImage(data: data) else { + throw ImageCacheError.loadingFailure + } + Self.imageCache.setObject(image, forKey: url as AnyObject) + return image + } + + func cacheGIFImage(with url: URL) -> UIImage? { + if let imageFromCache = Self.imageCache.object(forKey: url as AnyObject) as? UIImage { + return imageFromCache + } + + guard let imageToCache = UIImage.gifImage(with: url) else { + return nil + } + + Self.imageCache.setObject(imageToCache, forKey: url as AnyObject) + + return imageToCache + } +} diff --git a/Shared/Extensions/UIKit/UIImage+GIF.swift b/Sources/ImageLoader/Extensions/UIKit/UIImage+GIF.swift similarity index 98% rename from Shared/Extensions/UIKit/UIImage+GIF.swift rename to Sources/ImageLoader/Extensions/UIKit/UIImage+GIF.swift index 291cecff..089da8e8 100644 --- a/Shared/Extensions/UIKit/UIImage+GIF.swift +++ b/Sources/ImageLoader/Extensions/UIKit/UIImage+GIF.swift @@ -9,7 +9,6 @@ import UIKit import ImageIO extension UIImage { - static func gifImage(with url: URL) -> UIImage? { guard let imageData = try? Data(contentsOf: url) else { return nil @@ -26,7 +25,7 @@ extension UIImage { return animatedImage(with: source) } - // MARK: Private Methods + // MARK: Other Private Methods private static func animatedImage(with source: CGImageSource) -> UIImage? { let count = CGImageSourceGetCount(source) @@ -105,5 +104,4 @@ extension UIImage { b = a % b } } - } diff --git a/Sources/ImageLoader/UIImage+URL.swift b/Sources/ImageLoader/UIImage+URL.swift new file mode 100644 index 00000000..fd0eecb5 --- /dev/null +++ b/Sources/ImageLoader/UIImage+URL.swift @@ -0,0 +1,20 @@ +// +// UIImage+URL.swift +// +// +// Created by uhooi on 2022/01/16. +// + +import Foundation +import class UIKit.UIImage + +@MainActor +extension UIImage { + public static func create(with url: URL) async -> UIImage? { + try? await ImageCacheManager().cacheImage(with: url) + } + + static func createGIF(with url: URL) -> UIImage? { + ImageCacheManager().cacheGIFImage(with: url) + } +} diff --git a/Sources/ImageLoader/UIImageView+URL.swift b/Sources/ImageLoader/UIImageView+URL.swift new file mode 100644 index 00000000..1a3618b6 --- /dev/null +++ b/Sources/ImageLoader/UIImageView+URL.swift @@ -0,0 +1,21 @@ +// +// UIImageView+URL.swift +// +// +// Created by uhooi on 2022/01/14. +// + +import Foundation +import class UIKit.UIImage +import class UIKit.UIImageView + +@MainActor +public extension UIImageView { + func loadImage(with url: URL) async { + image = await UIImage.create(with: url) + } + + func loadGIFImage(with url: URL) { + image = UIImage.createGIF(with: url) + } +} diff --git a/Sources/Logger/Logger.swift b/Sources/Logger/Logger.swift new file mode 100644 index 00000000..4c18acb4 --- /dev/null +++ b/Sources/Logger/Logger.swift @@ -0,0 +1,122 @@ +// +// Logger.swift +// UhooiPicBook +// +// Created by uhooi on 2021/12/30. +// + +import Foundation +import os.log + +public enum LogCategory: String { + case `default` +} + +/// @mockable +public protocol LoggerProtocol { + func debug(_ message: String, file: String, function: String, line: Int, column: Int) + func info(_ message: String, file: String, function: String, line: Int, column: Int) + func notice(_ message: String, file: String, function: String, line: Int, column: Int) + func error(_ message: String, file: String, function: String, line: Int, column: Int) + func fault(_ message: String, file: String, function: String, line: Int, column: Int) + func exception(_ error: Error, file: String, function: String, line: Int, column: Int) +} + +public final class Logger { + + // MARK: Stored Type Properties + + public static let `default` = Logger(category: .default) + + // MARK: Stored Instance Properties + + private let logger: os.Logger + + // MARK: Initializers + + public init(category: LogCategory) { + self.logger = os.Logger( + subsystem: Bundle.main.bundleIdentifier!, // swiftlint:disable:this force_unwrapping + category: category.rawValue + ) + } +} + +extension Logger: LoggerProtocol { + public func debug( + _ message: String, + file: String = #file, + function: String = #function, + line: Int = #line, + column: Int = #column + ) { + let logRow = logRow(message, file: file, function: function, line: line, column: column) + logger.debug("\(logRow, privacy: .public)") + } + + public func info( + _ message: String, + file: String = #file, + function: String = #function, + line: Int = #line, + column: Int = #column + ) { + let logRow = logRow(message, file: file, function: function, line: line, column: column) + logger.info("\(logRow, privacy: .public)") + } + + public func notice( + _ message: String, + file: String = #file, + function: String = #function, + line: Int = #line, + column: Int = #column + ) { + let logRow = logRow(message, file: file, function: function, line: line, column: column) + logger.notice("\(logRow, privacy: .public)") + } + + public func error( + _ message: String, + file: String = #file, + function: String = #function, + line: Int = #line, + column: Int = #column + ) { + let logRow = logRow(message, file: file, function: function, line: line, column: column) + logger.error("\(logRow, privacy: .public)") + } + + public func fault( + _ message: String, + file: String = #file, + function: String = #function, + line: Int = #line, + column: Int = #column + ) { + let logRow = logRow(message, file: file, function: function, line: line, column: column) + logger.fault("\(logRow, privacy: .public)") + } + + public func exception( + _ error: Error, + file: String = #file, + function: String = #function, + line: Int = #line, + column: Int = #column + ) { + self.error(error.localizedDescription, file: file, function: function, line: line, column: column) + } + + // MARK: Other Private Methods + + private func logRow( + _ message: String, + file: String, + function: String, + line: Int, + column: Int + ) -> String { + "\(file) \(function) (Line: \(line), Column: \(column)): \(message)" + } +} diff --git a/Sources/MonsterWidgets/MonsterEntry.swift b/Sources/MonsterWidgets/MonsterEntry.swift new file mode 100644 index 00000000..1f96a74c --- /dev/null +++ b/Sources/MonsterWidgets/MonsterEntry.swift @@ -0,0 +1,37 @@ +// +// MonsterEntry.swift +// UhooiPicBookWidgets +// +// Created by uhooi on 2020/12/14. +// + +import class UIKit.UIImage +import WidgetKit + +public struct MonsterEntry: TimelineEntry { + public let date: Date + public let name: String + public let description: String + public let icon: UIImage + + public init( + date: Date, + name: String, + description: String, + icon: UIImage + ) { + self.date = date + self.name = name + self.description = description + self.icon = icon + } + + public static func placeholder() -> Self { + .init( + date: Date(), + name: "uhooi", + description: "ゆかいな みどりの せいぶつ。\nわるそうに みえるが むがい。", + icon: R.Image.uhooiIcon + ) + } +} diff --git a/UhooiPicBookWidgets/Monster/MonsterEntryView.swift b/Sources/MonsterWidgets/MonsterEntryView.swift similarity index 74% rename from UhooiPicBookWidgets/Monster/MonsterEntryView.swift rename to Sources/MonsterWidgets/MonsterEntryView.swift index 17b767e4..cd0ebb14 100644 --- a/UhooiPicBookWidgets/Monster/MonsterEntryView.swift +++ b/Sources/MonsterWidgets/MonsterEntryView.swift @@ -8,11 +8,11 @@ import WidgetKit import SwiftUI -struct MonsterEntryView: View { +public struct MonsterEntryView: View { var entry: MonsterEntry @Environment(\.widgetFamily) private var family - var body: some View { + public var body: some View { switch family { case .systemSmall: ZStack { @@ -40,6 +40,9 @@ struct MonsterEntryView: View { } case .systemLarge, .systemExtraLarge: EmptyView() + case .accessoryCircular, .accessoryRectangular, .accessoryInline: + // TODO: Implement for the Lock Screen. + EmptyView() @unknown default: EmptyView() } @@ -49,6 +52,7 @@ struct MonsterEntryView: View { Image(uiImage: entry.icon) .resizable() .aspectRatio(contentMode: .fit) + .accessibilityLabel(Text(entry.name)) } private var name: some View { @@ -60,6 +64,10 @@ struct MonsterEntryView: View { Text(entry.description) .font(.body) } + + public init(entry: MonsterEntry) { + self.entry = entry + } } struct MonsterEntryView_Previews: PreviewProvider { @@ -76,31 +84,31 @@ struct MonsterEntryView_Previews: PreviewProvider { private static var previewEntryViewGroup: some View { Group { - MonsterEntryView(entry: .createDefault()) + MonsterEntryView(entry: .placeholder()) .redacted(reason: .placeholder) - MonsterEntryView(entry: .createDefault()) - MonsterEntryView(entry: .createDefault()) + MonsterEntryView(entry: .placeholder()) + MonsterEntryView(entry: .placeholder()) .environment(\.colorScheme, .dark) - MonsterEntryView(entry: createShortEntry()) - MonsterEntryView(entry: createLongEntry()) + MonsterEntryView(entry: shortEntry()) + MonsterEntryView(entry: longEntry()) } } - private static func createShortEntry() -> Entry { + private static func shortEntry() -> Entry { .init( date: Date(), name: "1", description: "1", - icon: UIImage(named: "Uhooi")! // swiftlint:disable:this force_unwrapping + icon: R.Image.uhooiIcon ) } - private static func createLongEntry() -> Entry { + private static func longEntry() -> Entry { .init( date: Date(), name: "123456789012345678901234567890", description: "12345678901234567890\n12345678901234567890\n12345678901234567890", - icon: UIImage(named: "Uhooi")! // swiftlint:disable:this force_unwrapping + icon: R.Image.uhooiIcon ) } } diff --git a/Sources/MonsterWidgets/MonsterWidget.swift b/Sources/MonsterWidgets/MonsterWidget.swift new file mode 100644 index 00000000..34bfec70 --- /dev/null +++ b/Sources/MonsterWidgets/MonsterWidget.swift @@ -0,0 +1,85 @@ +// +// MonsterWidget.swift +// UhooiPicBookWidgets +// +// Created by uhooi on 2020/11/09. +// + +import WidgetKit +import SwiftUI +import FirebaseSetup +import MonstersRepository +import ImageLoader +import Logger + +private struct MonsterProvider { + typealias Entry = MonsterEntry + + private let monstersRepository: MR + private let logger: LP + + init( + monstersRepository: MR = MonstersFirestoreClient.shared, + logger: LP = Logger.default + ) { + self.monstersRepository = monstersRepository + self.logger = logger + } +} + +public struct MonsterWidget: Widget { + public var body: some WidgetConfiguration { + StaticConfiguration( + kind: "Monster", + provider: MonsterProvider() + ) { entry in + MonsterEntryView(entry: entry) + } + .configurationDisplayName(R.LocalizedString.configurationDisplayName) + .description(R.LocalizedString.description) + .supportedFamilies([.systemSmall, .systemMedium]) + } + + public init() { + FirebaseSetup.configure() + } +} + +extension MonsterProvider: TimelineProvider { + func placeholder(in context: Context) -> Entry { + .placeholder() + } + + func getSnapshot(in context: Context, completion: @escaping (Entry) -> Void) { + completion(.placeholder()) + } + + func getTimeline(in context: Context, completion: @escaping (Timeline) -> Void) { + Task { + var entries: [Entry] = [] + do { + let monsters = try await monstersRepository.monsters() + let currentDate = Date() + var hourOffset = 0 + for monster in monsters.sorted(by: { $0.order < $1.order }) { + guard let iconURL = URL(string: monster.iconURLString), + let icon = await UIImage.create(with: iconURL) + else { + continue + } + + guard let entryDate = Calendar.current.date(byAdding: .hour, value: hourOffset, to: currentDate) else { + fatalError("Fail to unwrap `entryDate`. hourOffset: \(hourOffset), currentDate: \(currentDate)") + } + let description = monster.description.replacingOccurrences(of: "\\n", with: "\n") + let entry = Entry(date: entryDate, name: monster.name, description: description, icon: icon) + entries.append(entry) + hourOffset += 1 + } + } catch { + logger.exception(error, file: #file, function: #function, line: #line, column: #column) + } + completion(Timeline(entries: entries, policy: .atEnd)) + } + } +} diff --git a/Sources/MonsterWidgets/R.swift b/Sources/MonsterWidgets/R.swift new file mode 100644 index 00000000..97e1df97 --- /dev/null +++ b/Sources/MonsterWidgets/R.swift @@ -0,0 +1,45 @@ +// +// R.swift +// +// +// Created by uhooi on 2022/01/09. +// + +import Foundation +import class UIKit.UIImage + +public enum R { // swiftlint:disable:this type_name + public enum LocalizedString { + + // MARK: Public Stored Type Properties + + public static let configurationDisplayName = string(localized: "Configuration display name") + public static let configurableDescription = string(localized: "Configurable description") + + // MARK: Internal Stored Type Properties + + static let description = string(localized: "Description") + + // MARK: Other Private Type Methods + + private static func string(localized keyAndValue: String.LocalizationValue) -> String { + String(localized: keyAndValue, bundle: .module) + } + } + + enum Image { + + // MARK: Internal Stored Type Properties + + static let uhooiIcon = uiImage(named: "Uhooi") + + // MARK: Other Private Type Methods + + private static func uiImage(named name: String) -> UIImage { + guard let image = UIImage(named: name, in: .module, with: nil) else { + fatalError("Fail to load '\(name)' image.") + } + return image + } + } +} diff --git a/UhooiPicBookWidgets/Assets.xcassets/AccentColor.colorset/Contents.json b/Sources/MonsterWidgets/Resources/Assets.xcassets/AccentColor.colorset/Contents.json similarity index 100% rename from UhooiPicBookWidgets/Assets.xcassets/AccentColor.colorset/Contents.json rename to Sources/MonsterWidgets/Resources/Assets.xcassets/AccentColor.colorset/Contents.json diff --git a/Sources/MonsterWidgets/Resources/Assets.xcassets/Contents.json b/Sources/MonsterWidgets/Resources/Assets.xcassets/Contents.json new file mode 100644 index 00000000..73c00596 --- /dev/null +++ b/Sources/MonsterWidgets/Resources/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/UhooiPicBookWidgets/Assets.xcassets/Uhooi.imageset/Contents.json b/Sources/MonsterWidgets/Resources/Assets.xcassets/Uhooi.imageset/Contents.json similarity index 100% rename from UhooiPicBookWidgets/Assets.xcassets/Uhooi.imageset/Contents.json rename to Sources/MonsterWidgets/Resources/Assets.xcassets/Uhooi.imageset/Contents.json diff --git a/UhooiPicBookWidgets/Assets.xcassets/Uhooi.imageset/uhooi.png b/Sources/MonsterWidgets/Resources/Assets.xcassets/Uhooi.imageset/uhooi.png similarity index 100% rename from UhooiPicBookWidgets/Assets.xcassets/Uhooi.imageset/uhooi.png rename to Sources/MonsterWidgets/Resources/Assets.xcassets/Uhooi.imageset/uhooi.png diff --git a/UhooiPicBookWidgets/Assets.xcassets/WidgetBackground.colorset/Contents.json b/Sources/MonsterWidgets/Resources/Assets.xcassets/WidgetBackground.colorset/Contents.json similarity index 100% rename from UhooiPicBookWidgets/Assets.xcassets/WidgetBackground.colorset/Contents.json rename to Sources/MonsterWidgets/Resources/Assets.xcassets/WidgetBackground.colorset/Contents.json diff --git a/UhooiPicBookWidgets/en.lproj/Localizable.strings b/Sources/MonsterWidgets/Resources/en.lproj/Localizable.strings similarity index 100% rename from UhooiPicBookWidgets/en.lproj/Localizable.strings rename to Sources/MonsterWidgets/Resources/en.lproj/Localizable.strings diff --git a/UhooiPicBookWidgets/ja.lproj/Localizable.strings b/Sources/MonsterWidgets/Resources/ja.lproj/Localizable.strings similarity index 100% rename from UhooiPicBookWidgets/ja.lproj/Localizable.strings rename to Sources/MonsterWidgets/Resources/ja.lproj/Localizable.strings diff --git a/Sources/MonstersRepository/MonsterDTO.swift b/Sources/MonstersRepository/MonsterDTO.swift new file mode 100644 index 00000000..8c41a906 --- /dev/null +++ b/Sources/MonstersRepository/MonsterDTO.swift @@ -0,0 +1,35 @@ +// +// MonsterDTO.swift +// UhooiPicBook +// +// Created by uhooi on 2020/02/28. +// + +public struct MonsterDTO { + public let name: String + public let description: String + public let baseColorCode: String + public let iconURLString: String + public let dancingURLString: String + public let order: Int + + public init( + name: String, + description: String, + baseColorCode: String, + iconURLString: String, + dancingURLString: String, + order: Int + ) { + self.name = name + self.description = description + self.baseColorCode = baseColorCode + self.iconURLString = iconURLString + self.dancingURLString = dancingURLString + self.order = order + } +} + +extension MonsterDTO: Sendable {} + +extension MonsterDTO: Equatable {} // For unit tests diff --git a/Sources/MonstersRepository/MonstersFirestoreClient.swift b/Sources/MonstersRepository/MonstersFirestoreClient.swift new file mode 100644 index 00000000..90ec3fdd --- /dev/null +++ b/Sources/MonstersRepository/MonstersFirestoreClient.swift @@ -0,0 +1,54 @@ +// +// MonstersFirestoreClient.swift +// UhooiPicBook +// +// Created by uhooi on 2020/02/28. +// + +import FirebaseFirestore + +public final class MonstersFirestoreClient { + + // MARK: Stored Type Properties + + public static let shared = MonstersFirestoreClient() + + // MARK: Stored Instance Properties + + private let firestore = Firestore.firestore() + + // MARK: Initializers + + private init() {} +} + +extension MonstersFirestoreClient: MonstersRepository { + public func monsters() async throws -> [MonsterDTO] { + let monstersRef = firestore.collection("monsters") + let querySnapshot = try await monstersRef.getDocuments() + + var monsters: [MonsterDTO] = [] + for document in querySnapshot.documents.filter({ $0.exists }) { + let monster = document.data() + guard let name = monster["name"] as? String, + let description = monster["description"] as? String, + let baseColorCode = monster["base_color"] as? String, + let iconURLString = monster["icon_url"] as? String, + let dancingURLString = monster["dancing_url"] as? String, + let order = monster["order"] as? Int else { + continue + } + + monsters.append(MonsterDTO( + name: name, + description: description, + baseColorCode: baseColorCode, + iconURLString: iconURLString, + dancingURLString: dancingURLString, + order: order + )) + } + + return monsters + } +} diff --git a/Sources/MonstersRepository/MonstersRepository.swift b/Sources/MonstersRepository/MonstersRepository.swift new file mode 100644 index 00000000..1e0e1027 --- /dev/null +++ b/Sources/MonstersRepository/MonstersRepository.swift @@ -0,0 +1,11 @@ +// +// MonstersRepository.swift +// +// +// Created by uhooi on 2022/01/16. +// + +/// @mockable +public protocol MonstersRepository: AnyObject { + func monsters() async throws -> [MonsterDTO] +} diff --git a/Tests/AppModuleTests/Generated/.gitkeep b/Tests/AppModuleTests/Generated/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/UhooiPicBookTests/Modules/MonsterDetail/Interactors/MonsterDetailInteractorTests.swift b/Tests/AppModuleTests/Modules/MonsterDetail/Interactors/MonsterDetailInteractorTests.swift similarity index 91% rename from UhooiPicBookTests/Modules/MonsterDetail/Interactors/MonsterDetailInteractorTests.swift rename to Tests/AppModuleTests/Modules/MonsterDetail/Interactors/MonsterDetailInteractorTests.swift index f7be27f3..c9c57c90 100644 --- a/UhooiPicBookTests/Modules/MonsterDetail/Interactors/MonsterDetailInteractorTests.swift +++ b/Tests/AppModuleTests/Modules/MonsterDetail/Interactors/MonsterDetailInteractorTests.swift @@ -7,13 +7,14 @@ // import XCTest -@testable import UhooiPicBook +@testable import AppModule final class MonsterDetailInteractorTests: XCTestCase { // MARK: Stored Instance Properties private var presenterMock: MonsterDetailInteractorOutputMock! + private var interactor: MonsterDetailInteractor! // MARK: TestCase Life-Cycle Methods @@ -35,7 +36,6 @@ final class MonsterDetailInteractorTests: XCTestCase { private func reset() { self.presenterMock = MonsterDetailInteractorOutputMock() self.interactor = MonsterDetailInteractor() - self.interactor.presenter = self.presenterMock + self.interactor.inject(presenter: self.presenterMock) } - } diff --git a/UhooiPicBookTests/Modules/MonsterDetail/Presenters/MonsterDetailPresenterTests.swift b/Tests/AppModuleTests/Modules/MonsterDetail/Presenters/MonsterDetailPresenterTests.swift similarity index 67% rename from UhooiPicBookTests/Modules/MonsterDetail/Presenters/MonsterDetailPresenterTests.swift rename to Tests/AppModuleTests/Modules/MonsterDetail/Presenters/MonsterDetailPresenterTests.swift index 8b373745..2593c2a0 100644 --- a/UhooiPicBookTests/Modules/MonsterDetail/Presenters/MonsterDetailPresenterTests.swift +++ b/Tests/AppModuleTests/Modules/MonsterDetail/Presenters/MonsterDetailPresenterTests.swift @@ -7,8 +7,9 @@ // import XCTest -@testable import UhooiPicBook +@testable import AppModule +@MainActor final class MonsterDetailPresenterTests: XCTestCase { // MARK: Stored Instance Properties @@ -16,10 +17,16 @@ final class MonsterDetailPresenterTests: XCTestCase { private var viewMock: MonsterDetailUserInterfaceMock! private var interactorMock: MonsterDetailInteractorInputMock! private var routerMock: MonsterDetailRouterInputMock! - private var presenter: MonsterDetailPresenter! + + private var presenter: MonsterDetailPresenter< + MonsterDetailUserInterfaceMock, + MonsterDetailInteractorInputMock, + MonsterDetailRouterInputMock + >! // MARK: TestCase Life-Cycle Methods + @MainActor override func setUpWithError() throws { reset() } @@ -35,21 +42,21 @@ final class MonsterDetailPresenterTests: XCTestCase { // MARK: viewDidLoad() func test_viewDidLoad() { - self.presenter.viewDidLoad() + presenter.viewDidLoad() } // MARK: didTapDancingImageView() func test_didTapDancingImageView_notNil() { - self.presenter.didTapDancingImageView(dancingImage: UIImage()) + presenter.didTapDancingImageView(dancingImage: UIImage()) - XCTAssertEqual(self.routerMock.popupDancingImageCallCount, 1) + XCTAssertEqual(routerMock.popupDancingImageCallCount, 1) } func test_didTapDancingImageView_nil() { - self.presenter.didTapDancingImageView(dancingImage: nil) + presenter.didTapDancingImageView(dancingImage: nil) - XCTAssertEqual(self.routerMock.popupDancingImageCallCount, 0) + XCTAssertEqual(routerMock.popupDancingImageCallCount, 0) } // MARK: didTapShareButton() @@ -64,8 +71,8 @@ final class MonsterDetailPresenterTests: XCTestCase { ] for (senderView, name, description, icon, line) in testCases { - self.presenter.didTapShareButton(senderView, name: name, description: description, icon: icon) - XCTAssertEqual(self.routerMock.showActivityCallCount, 0, line: line) + presenter.didTapShareButton(senderView, name: name, description: description, icon: icon) + XCTAssertEqual(routerMock.showActivityCallCount, 0, line: line) } } @@ -74,15 +81,15 @@ final class MonsterDetailPresenterTests: XCTestCase { let name = "name" let description = "description" let icon = UIImage() - self.routerMock.showActivityHandler = { sourceView, text, image in + routerMock.showActivityHandler = { sourceView, text, image in XCTAssertEqual(text, "\(name)\n\(description)\n#UhooiPicBook") XCTAssertEqual(sourceView, senderView) XCTAssertEqual(image, icon) } - self.presenter.didTapShareButton(senderView, name: name, description: description, icon: icon) + presenter.didTapShareButton(senderView, name: name, description: description, icon: icon) - XCTAssertEqual(self.routerMock.showActivityCallCount, 1) + XCTAssertEqual(routerMock.showActivityCallCount, 1) } // MARK: MonsterDetailInteractorOutput @@ -93,7 +100,10 @@ final class MonsterDetailPresenterTests: XCTestCase { self.viewMock = MonsterDetailUserInterfaceMock() self.interactorMock = MonsterDetailInteractorInputMock() self.routerMock = MonsterDetailRouterInputMock() - self.presenter = MonsterDetailPresenter(view: self.viewMock, interactor: self.interactorMock, router: self.routerMock) + self.presenter = MonsterDetailPresenter( + view: self.viewMock, + interactor: self.interactorMock, + router: self.routerMock + ) } - } diff --git a/Tests/AppModuleTests/Modules/MonsterList/Interactors/MonsterListInteractorTests.swift b/Tests/AppModuleTests/Modules/MonsterList/Interactors/MonsterListInteractorTests.swift new file mode 100644 index 00000000..d54e6d1a --- /dev/null +++ b/Tests/AppModuleTests/Modules/MonsterList/Interactors/MonsterListInteractorTests.swift @@ -0,0 +1,95 @@ +// +// MonsterListInteractorTests.swift +// UhooiPicBookTests +// +// Created by uhooi on 28/02/2020. +// Copyright © 2020 THE Uhooi. All rights reserved. +// + +import XCTest +@testable import AppModule +import MonstersRepository + +final class MonsterListInteractorTests: XCTestCase { + + // MARK: Stored Instance Properties + + private var presenterMock: MonsterListInteractorOutputMock! + private var monstersRepositoryMock: MonstersRepositoryMock! + private var monstersTempRepositoryMock: MonstersTempRepositoryMock! + private var spotlightRepositoryMock: SpotlightRepositoryMock! + + private var interactor: MonsterListInteractor< + SpotlightRepositoryMock, + MonstersRepositoryMock, + MonstersTempRepositoryMock + >! + + // MARK: TestCase Life-Cycle Methods + + override func setUpWithError() throws { + reset() + } + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + // MARK: - Test Methods + + // MARK: MonsterListInteractorInput + + // MARK: monsters() + + func test_monsters_success() async { + let monsterDTOs: [MonsterDTO] = [] + monstersRepositoryMock.monstersHandler = { monsterDTOs } + + do { + let monsters = try await interactor.monsters() + XCTAssertEqual(monsters, monsterDTOs) + } catch { + XCTFail("Error: \(error)") + } + XCTAssertEqual(monstersRepositoryMock.monstersCallCount, 1) + } + + func test_monsters_failure() async { + struct TestError: Error {} + monstersRepositoryMock.monstersHandler = { throw TestError() } + + do { + let monsters = try await interactor.monsters() + XCTFail("Monsters: \(monsters)") + } catch { + XCTAssertTrue(error is TestError) + } + XCTAssertEqual(monstersRepositoryMock.monstersCallCount, 1) + } + + // saveMonsterInSpotlight() + + func test_saveMonsterInSpotlight() async { + let uhooiEntity = MonsterEntity(name: "uhooi", description: "uhooi's description\nuhooi", baseColorCode: "#FFFFFF", iconURL: URL(string: "https://theuhooi.com/uhooi")!, dancingURL: URL(string: "https://theuhooi.com/uhooi-dancing")!) + + await interactor.saveMonsterInSpotlight(uhooiEntity) + + XCTAssertEqual(monstersTempRepositoryMock.saveMonsterCallCount, 1) + XCTAssertEqual(spotlightRepositoryMock.saveMonsterCallCount, 1) + } + + // MARK: - Other Private Methods + + private func reset() { + self.presenterMock = MonsterListInteractorOutputMock() + self.monstersRepositoryMock = MonstersRepositoryMock() + self.monstersTempRepositoryMock = MonstersTempRepositoryMock() + self.spotlightRepositoryMock = SpotlightRepositoryMock() + self.interactor = MonsterListInteractor( + spotlightRepository: self.spotlightRepositoryMock, + monstersRepository: self.monstersRepositoryMock, + monstersTempRepository: self.monstersTempRepositoryMock + ) + self.interactor.inject(presenter: self.presenterMock) + } +} diff --git a/Tests/AppModuleTests/Modules/MonsterList/Presenters/MonsterListPresenterTests.swift b/Tests/AppModuleTests/Modules/MonsterList/Presenters/MonsterListPresenterTests.swift new file mode 100644 index 00000000..ffc5ca8d --- /dev/null +++ b/Tests/AppModuleTests/Modules/MonsterList/Presenters/MonsterListPresenterTests.swift @@ -0,0 +1,212 @@ +// +// MonsterListPresenterTests.swift +// UhooiPicBookTests +// +// Created by uhooi on 28/02/2020. +// Copyright © 2020 THE Uhooi. All rights reserved. +// + +import XCTest +@testable import AppModule +import MonstersRepository + +@MainActor +final class MonsterListPresenterTests: XCTestCase { + + // MARK: Stored Instance Properties + + private var viewMock: MonsterListUserInterfaceMock! + private var interactorMock: MonsterListInteractorInputMock! + private var routerMock: MonsterListRouterInputMock! + + private var presenter: MonsterListPresenter< + MonsterListUserInterfaceMock, + MonsterListInteractorInputMock, + MonsterListRouterInputMock + >! + + // MARK: TestCase Life-Cycle Methods + + @MainActor + override func setUpWithError() throws { + reset() + } + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + // MARK: - Test Methods + + // MARK: MonsterListEventHandler + + // MARK: viewDidLoad() + + func test_viewDidLoad_success_zero() async { + let monsterDTOs: [MonsterDTO] = [] + interactorMock.monstersHandler = { monsterDTOs } + viewMock.showMonstersHandler = { monsters in + for _ in 0 ..< monsterDTOs.count { + XCTFail("There shouldn't be any monsters.") + } + } + + await presenter.viewDidLoad() + + XCTAssertEqual(viewMock.startIndicatorCallCount, 1) + XCTAssertEqual(interactorMock.monstersCallCount, 1) + XCTAssertEqual(viewMock.showMonstersCallCount, 1) + XCTAssertEqual(viewMock.stopIndicatorCallCount, 1) + } + + func test_viewDidLoad_success_three() async { + let uhooiDTO = MonsterDTO(name: "uhooi", description: "uhooi's description", baseColorCode: "#FFFFFF", iconURLString: "https://theuhooi.com/uhooi", dancingURLString: "https://theuhooi.com/uhooi-dancing", order: 1) + let ayausaDTO = MonsterDTO(name: "ayausa", description: "ayausa's description", baseColorCode: "#000000", iconURLString: "https://theuhooi.com/ayausa", dancingURLString: "https://theuhooi.com/ayausa-dancing", order: 2) + let chibirdDTO = MonsterDTO(name: "chibird", description: "chibird's description", baseColorCode: "#999999", iconURLString: "https://theuhooi.com/chibird", dancingURLString: "https://theuhooi.com/chibird-dancing", order: 3) + let monsterDTOs = [uhooiDTO, ayausaDTO, chibirdDTO] + interactorMock.monstersHandler = { monsterDTOs } + viewMock.showMonstersHandler = { monsterItems in + for index in 0 ..< monsterDTOs.count { + let actual = MonsterItem(entity: MonsterEntity(dto: monsterDTOs[index])) + let expected = monsterItems[index] + XCTAssertEqual(actual, expected) + } + } + + await presenter.viewDidLoad() + + XCTAssertEqual(viewMock.startIndicatorCallCount, 1) + XCTAssertEqual(interactorMock.monstersCallCount, 1) + XCTAssertEqual(viewMock.showMonstersCallCount, 1) + XCTAssertEqual(viewMock.stopIndicatorCallCount, 1) + } + + func test_viewDidLoad_newLine() async { + typealias TestCase = (description: String, expected: String, line: UInt) + let testCases: [TestCase] = [ + ("", "" , #line), + ("¥¥n", "¥¥n" , #line), + ("\n", "\n" , #line), + ("\\n", "\n" , #line), + // ("\\\n", "\\n" ,#line), + ("\\n\\n", "\n\n" , #line), + ("test\\nuhooi", "test\nuhooi" , #line), + ] + + for (description, expected, line) in testCases { + reset() + let monsterDTO = MonsterDTO( + name: "monster's name", + description: description, + baseColorCode: "#FFFFFF", + iconURLString: "https://theuhooi.com/monster", + dancingURLString: "https://theuhooi.com/monster-dancing", + order: 1 + ) + interactorMock.monstersHandler = { [monsterDTO] } + viewMock.showMonstersHandler = { monsters in + XCTAssertEqual(monsters[0].description, expected, line: line) + } + + await presenter.viewDidLoad() + + XCTAssertEqual(viewMock.startIndicatorCallCount, 1) + XCTAssertEqual(interactorMock.monstersCallCount, 1) + XCTAssertEqual(viewMock.showMonstersCallCount, 1) + XCTAssertEqual(viewMock.stopIndicatorCallCount, 1) + } + } + + func test_viewDidLoad_failure() async { + struct TestError: Error {} + interactorMock.monstersHandler = { throw TestError() } + + await presenter.viewDidLoad() + + XCTAssertEqual(viewMock.startIndicatorCallCount, 1) + XCTAssertEqual(interactorMock.monstersCallCount, 1) + XCTAssertEqual(viewMock.showMonstersCallCount, 0) + XCTAssertEqual(viewMock.stopIndicatorCallCount, 1) + } + + // MARK: didTapContactUs() + + func test_didTapContactUs() { + presenter.didTapContactUs() + + XCTAssertEqual(routerMock.showContactUsCallCount, 1) + XCTAssertEqual(routerMock.showPrivacyPolicyCallCount, 0) + XCTAssertEqual(routerMock.showSettingsCallCount, 0) + XCTAssertEqual(routerMock.showAboutThisAppCallCount, 0) + } + + // MARK: didTapPrivacyPolicy() + + func test_didTapPrivacyPolicy() { + presenter.didTapPrivacyPolicy() + + XCTAssertEqual(routerMock.showContactUsCallCount, 0) + XCTAssertEqual(routerMock.showPrivacyPolicyCallCount, 1) + XCTAssertEqual(routerMock.showSettingsCallCount, 0) + XCTAssertEqual(routerMock.showAboutThisAppCallCount, 0) + } + + // MARK: didTapLicenses() + + func test_didTapLicenses() { + presenter.didTapLicenses() + + XCTAssertEqual(routerMock.showContactUsCallCount, 0) + XCTAssertEqual(routerMock.showPrivacyPolicyCallCount, 0) + XCTAssertEqual(routerMock.showSettingsCallCount, 1) + XCTAssertEqual(routerMock.showAboutThisAppCallCount, 0) + } + + // MARK: didTapAboutThisApp() + + func test_didTapAboutThisApp() { + presenter.didTapAboutThisApp() + + XCTAssertEqual(routerMock.showContactUsCallCount, 0) + XCTAssertEqual(routerMock.showPrivacyPolicyCallCount, 0) + XCTAssertEqual(routerMock.showSettingsCallCount, 0) + XCTAssertEqual(routerMock.showAboutThisAppCallCount, 1) + } + + // MARK: MonsterSectionEventHandler + + // MARK: didSelectMonster() + + func test_didSelectMonster() async { + let uhooiDTO = MonsterDTO(name: "uhooi", description: "uhooi's description", baseColorCode: "#FFFFFF", iconURLString: "https://theuhooi.com/uhooi", dancingURLString: "https://theuhooi.com/uhooi-dancing", order: 1) + let monsterDTOs = [uhooiDTO] + interactorMock.monstersHandler = { monsterDTOs } + viewMock.showMonstersHandler = { monsters in + for index in 0 ..< monsterDTOs.count { + XCTAssertEqual(monsters[index].name, monsterDTOs[index].name) + } + } + await presenter.viewDidLoad() + + await presenter.didSelectMonster(at: 0) + + XCTAssertEqual(routerMock.showMonsterDetailCallCount, 1) + XCTAssertEqual(interactorMock.saveMonsterInSpotlightCallCount, 1) + } + + // MARK: MonsterListInteractorOutput + + // MARK: - Other Private Methods + + private func reset() { + self.viewMock = MonsterListUserInterfaceMock() + self.interactorMock = MonsterListInteractorInputMock() + self.routerMock = MonsterListRouterInputMock() + self.presenter = MonsterListPresenter( + view: self.viewMock, + interactor: self.interactorMock, + router: self.routerMock + ) + } + +} diff --git a/UhooiPicBookTests/Repository/Temp/UserDefaultsClientTests.swift b/Tests/AppModuleTests/Repository/Temp/UserDefaultsClientTests.swift similarity index 57% rename from UhooiPicBookTests/Repository/Temp/UserDefaultsClientTests.swift rename to Tests/AppModuleTests/Repository/Temp/UserDefaultsClientTests.swift index 09b28e66..512db4da 100644 --- a/UhooiPicBookTests/Repository/Temp/UserDefaultsClientTests.swift +++ b/Tests/AppModuleTests/Repository/Temp/UserDefaultsClientTests.swift @@ -6,13 +6,13 @@ // import XCTest -@testable import UhooiPicBook +@testable import AppModule final class UserDefaultsClientTests: XCTestCase { // MARK: Stored Instance Properties - private var userDefaults: UserDefaultsClient! + private let userDefaults = UserDefaultsClient.shared // MARK: TestCase Life-Cycle Methods @@ -26,35 +26,33 @@ final class UserDefaultsClientTests: XCTestCase { // MARK: - Test Methods func test_monster() { - var uhooiEntity = MonsterEntity(name: "uhooi", description: "uhooi's description\nuhooi", baseColorCode: "#FFFFFF", iconUrl: URL(string: "https://theuhooi.com/uhooi")!, dancingUrl: URL(string: "https://theuhooi.com/uhooi-dancing")!) + var uhooiEntity = MonsterEntity(name: "uhooi", description: "uhooi's description\nuhooi", baseColorCode: "#FFFFFF", iconURL: URL(string: "https://theuhooi.com/uhooi")!, dancingURL: URL(string: "https://theuhooi.com/uhooi-dancing")!) let key = "spotlight_\(uhooiEntity.name)" XCTContext.runActivity(named: "Unsaved") { _ in - XCTAssertNil(self.userDefaults.loadMonster(key: key)) + XCTAssertNil(userDefaults.monster(key: key)) } XCTContext.runActivity(named: "Add") { _ in - self.userDefaults.saveMonster(uhooiEntity, forKey: key) - XCTAssertEqual(uhooiEntity, self.userDefaults.loadMonster(key: key)) + userDefaults.saveMonster(uhooiEntity, forKey: key) + XCTAssertEqual(uhooiEntity, userDefaults.monster(key: key)) } - uhooiEntity = MonsterEntity(name: "uhooi", description: "uhooi's description\nuhooi", baseColorCode: "#000000", iconUrl: URL(string: "https://theuhooi.com/uhooi")!, dancingUrl: URL(string: "https://theuhooi.com/uhooi-dancing")!) + uhooiEntity = MonsterEntity(name: "uhooi", description: "uhooi's description\nuhooi", baseColorCode: "#000000", iconURL: URL(string: "https://theuhooi.com/uhooi")!, dancingURL: URL(string: "https://theuhooi.com/uhooi-dancing")!) XCTContext.runActivity(named: "Update") { _ in - self.userDefaults.saveMonster(uhooiEntity, forKey: key) - XCTAssertEqual(uhooiEntity, self.userDefaults.loadMonster(key: key)) + userDefaults.saveMonster(uhooiEntity, forKey: key) + XCTAssertEqual(uhooiEntity, userDefaults.monster(key: key)) } XCTContext.runActivity(named: "Remove") { _ in - self.userDefaults.removeAll() - XCTAssertNil(self.userDefaults.loadMonster(key: key)) + userDefaults.removeAll() + XCTAssertNil(userDefaults.monster(key: key)) } } // MARK: - Other Private Methods private func reset() { - self.userDefaults = UserDefaultsClient() - self.userDefaults.removeAll() + userDefaults.removeAll() } - } diff --git a/Tools/UhooiPicBookMockolo/.gitignore b/Tools/UhooiPicBookMockolo/.gitignore deleted file mode 100644 index bb460e7b..00000000 --- a/Tools/UhooiPicBookMockolo/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -.DS_Store -/.build -/Packages -/*.xcodeproj -xcuserdata/ -DerivedData/ -.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata diff --git a/Tools/UhooiPicBookMockolo/Empty.swift b/Tools/UhooiPicBookMockolo/Empty.swift deleted file mode 100644 index 8b137891..00000000 --- a/Tools/UhooiPicBookMockolo/Empty.swift +++ /dev/null @@ -1 +0,0 @@ - diff --git a/Tools/UhooiPicBookMockolo/Package.resolved b/Tools/UhooiPicBookMockolo/Package.resolved deleted file mode 100644 index 922f3e32..00000000 --- a/Tools/UhooiPicBookMockolo/Package.resolved +++ /dev/null @@ -1,43 +0,0 @@ -{ - "object": { - "pins": [ - { - "package": "Mockolo", - "repositoryURL": "https://github.com/uber/mockolo", - "state": { - "branch": null, - "revision": "e1d3e7b34ec44239d3eb022d109fd3dc9d6ade40", - "version": "1.6.1" - } - }, - { - "package": "swift-argument-parser", - "repositoryURL": "https://github.com/apple/swift-argument-parser", - "state": { - "branch": null, - "revision": "d2930e8fcf9c33162b9fcc1d522bc975e2d4179b", - "version": "1.0.1" - } - }, - { - "package": "SwiftSyntax", - "repositoryURL": "https://github.com/apple/swift-syntax.git", - "state": { - "branch": null, - "revision": "75e60475d9d8fd5bbc16a12e0eaa2cb01b0c322e", - "version": "0.50500.0" - } - }, - { - "package": "swift-tools-support-core", - "repositoryURL": "https://github.com/apple/swift-tools-support-core.git", - "state": { - "branch": null, - "revision": "3b6b97d612b56e25d80d0807f5bc38ea08b7bdf3", - "version": "0.2.3" - } - } - ] - }, - "version": 1 -} diff --git a/Tools/UhooiPicBookMockolo/Package.swift b/Tools/UhooiPicBookMockolo/Package.swift deleted file mode 100644 index 6be7831b..00000000 --- a/Tools/UhooiPicBookMockolo/Package.swift +++ /dev/null @@ -1,13 +0,0 @@ -// swift-tools-version:5.4 -import PackageDescription - -let package = Package( - name: "UhooiPicBookMockolo", - platforms: [ - .macOS(.v11) - ], - dependencies: [ - .package(url: "https://github.com/uber/mockolo", .exact("1.6.1")) - ], - targets: [.target(name: "UhooiPicBookMockolo", path: "")] -) diff --git a/Tools/UhooiPicBookTools/Package.resolved b/Tools/UhooiPicBookTools/Package.resolved index 42f3748e..0ce3d1c5 100644 --- a/Tools/UhooiPicBookTools/Package.resolved +++ b/Tools/UhooiPicBookTools/Package.resolved @@ -1,322 +1,194 @@ { - "object": { - "pins": [ - { - "package": "AEXML", - "repositoryURL": "https://github.com/tadija/AEXML.git", - "state": { - "branch": null, - "revision": "38f7d00b23ecd891e1ee656fa6aeebd6ba04ecc3", - "version": "4.6.1" - } - }, - { - "package": "APIKit", - "repositoryURL": "https://github.com/ishkawa/APIKit.git", - "state": { - "branch": null, - "revision": "c8f5320d84c4c34c0fd965da3c7957819a1ccdd4", - "version": "5.2.0" - } - }, - { - "package": "Colorizer", - "repositoryURL": "https://github.com/getGuaka/Colorizer.git", - "state": { - "branch": null, - "revision": "2ccc99bf1715e73c4139e8d40b6e6b30be975586", - "version": "0.2.1" - } - }, - { - "package": "Commandant", - "repositoryURL": "https://github.com/Carthage/Commandant.git", - "state": { - "branch": null, - "revision": "ab68611013dec67413628ac87c1f29e8427bc8e4", - "version": "0.17.0" - } - }, - { - "package": "Commander", - "repositoryURL": "https://github.com/kylef/Commander.git", - "state": { - "branch": null, - "revision": "4b6133c3071d521489a80c38fb92d7983f19d438", - "version": "0.9.1" - } - }, - { - "package": "GraphViz", - "repositoryURL": "https://github.com/SwiftDocOrg/GraphViz.git", - "state": { - "branch": null, - "revision": "70bebcf4597b9ce33e19816d6bbd4ba9b7bdf038", - "version": "0.2.0" - } - }, - { - "package": "HeliumLogger", - "repositoryURL": "https://github.com/Kitura/HeliumLogger.git", - "state": { - "branch": null, - "revision": "55fd2f0b70793017acee853c53cfcf8da0bd8d8d", - "version": "1.9.200" - } - }, - { - "package": "IBDecodable", - "repositoryURL": "https://github.com/IBDecodable/IBDecodable.git", - "state": { - "branch": null, - "revision": "4b31d99845357ccc55586e23a523cc3515aabdfa", - "version": "0.4.3" - } - }, - { - "package": "IBLinter", - "repositoryURL": "https://github.com/IBDecodable/IBLinter", - "state": { - "branch": null, - "revision": "2633cb882bda66846742f09eabc6f09f250c7e7c", - "version": "0.4.27" - } - }, - { - "package": "JSONUtilities", - "repositoryURL": "https://github.com/yonaskolb/JSONUtilities.git", - "state": { - "branch": null, - "revision": "128d2ffc22467f69569ef8ff971683e2393191a0", - "version": "4.2.0" - } - }, - { - "package": "LicensePlist", - "repositoryURL": "https://github.com/mono0926/LicensePlist", - "state": { - "branch": null, - "revision": "38db6f435cc77513a528780d14b1b29daf042439", - "version": "3.13.0" - } - }, - { - "package": "LoggerAPI", - "repositoryURL": "https://github.com/Kitura/LoggerAPI.git", - "state": { - "branch": null, - "revision": "e82d34eab3f0b05391082b11ea07d3b70d2f65bb", - "version": "1.9.200" - } - }, - { - "package": "Nimble", - "repositoryURL": "https://github.com/Quick/Nimble.git", - "state": { - "branch": null, - "revision": "7a46a5fc86cb917f69e3daf79fcb045283d8f008", - "version": "8.1.2" - } - }, - { - "package": "PathKit", - "repositoryURL": "https://github.com/kylef/PathKit.git", - "state": { - "branch": null, - "revision": "3bfd2737b700b9a36565a8c94f4ad2b050a5e574", - "version": "1.0.1" - } - }, - { - "package": "Quick", - "repositoryURL": "https://github.com/Quick/Quick.git", - "state": { - "branch": null, - "revision": "09b3becb37cb2163919a3842a4c5fa6ec7130792", - "version": "2.2.1" - } - }, - { - "package": "rswift", - "repositoryURL": "https://github.com/mac-cain13/R.swift", - "state": { - "branch": null, - "revision": "18ad905c6f8f0865042e1d1ee4effc7291aa899d", - "version": "5.4.0" - } - }, - { - "package": "Rainbow", - "repositoryURL": "https://github.com/onevcat/Rainbow.git", - "state": { - "branch": null, - "revision": "626c3d4b6b55354b4af3aa309f998fae9b31a3d9", - "version": "3.2.0" - } - }, - { - "package": "SourceKitten", - "repositoryURL": "https://github.com/jpsim/SourceKitten.git", - "state": { - "branch": null, - "revision": "7f4be006fe73211b0fd9666c73dc2f2303ffa756", - "version": "0.31.0" - } - }, - { - "package": "Spectre", - "repositoryURL": "https://github.com/kylef/Spectre.git", - "state": { - "branch": null, - "revision": "26cc5e9ae0947092c7139ef7ba612e34646086c7", - "version": "0.10.1" - } - }, - { - "package": "SpellChecker", - "repositoryURL": "https://github.com/fromkk/SpellChecker", - "state": { - "branch": null, - "revision": "d1ffdd96acf9c117b7eefcb93b5b60aa1b0a4db9", - "version": "0.1.0" - } - }, - { - "package": "swift-argument-parser", - "repositoryURL": "https://github.com/apple/swift-argument-parser.git", - "state": { - "branch": null, - "revision": "9564d61b08a5335ae0a36f789a7d71493eacadfc", - "version": "0.3.2" - } - }, - { - "package": "HTMLEntities", - "repositoryURL": "https://github.com/Kitura/swift-html-entities.git", - "state": { - "branch": null, - "revision": "2b14531d0c36dbb7c1c45a4d38db9c2e7898a307", - "version": "3.0.200" - } - }, - { - "package": "swift-log", - "repositoryURL": "https://github.com/apple/swift-log.git", - "state": { - "branch": null, - "revision": "5d66f7ba25daf4f94100e7022febf3c75e37a6c7", - "version": "1.4.2" - } - }, - { - "package": "SwiftCLI", - "repositoryURL": "https://github.com/jakeheis/SwiftCLI.git", - "state": { - "branch": null, - "revision": "2e949055d9797c1a6bddcda0e58dada16cc8e970", - "version": "6.0.3" - } - }, - { - "package": "SwiftLint", - "repositoryURL": "https://github.com/realm/SwiftLint", - "state": { - "branch": null, - "revision": "180d94132758dd183124ab1e63d6aa8e10023ec2", - "version": "0.43.1" - } - }, - { - "package": "SwiftyTextTable", - "repositoryURL": "https://github.com/scottrhoyt/SwiftyTextTable.git", - "state": { - "branch": null, - "revision": "c6df6cf533d120716bff38f8ff9885e1ce2a4ac3", - "version": "0.9.0" - } - }, - { - "package": "SWXMLHash", - "repositoryURL": "https://github.com/drmohundro/SWXMLHash.git", - "state": { - "branch": null, - "revision": "9183170d20857753d4f331b0ca63f73c60764bf3", - "version": "5.0.2" - } - }, - { - "package": "Version", - "repositoryURL": "https://github.com/mxcl/Version", - "state": { - "branch": null, - "revision": "a94b48f36763c05629fc102837398505032dead9", - "version": "2.0.0" - } - }, - { - "package": "xcbeautify", - "repositoryURL": "https://github.com/thii/xcbeautify", - "state": { - "branch": null, - "revision": "21c64495bb3eb9a46ecc9b5eea056d06383eb17c", - "version": "0.9.1" - } - }, - { - "package": "XcodeEdit", - "repositoryURL": "https://github.com/tomlokhorst/XcodeEdit", - "state": { - "branch": null, - "revision": "dab519997ca05833470c88f0926b27498911ecbf", - "version": "2.7.7" - } - }, - { - "package": "XcodeGen", - "repositoryURL": "https://github.com/yonaskolb/XcodeGen", - "state": { - "branch": null, - "revision": "c8b2a4ac8a495f984ce7a321afdba19a8e9d436d", - "version": "2.25.0" - } - }, - { - "package": "XcodeProj", - "repositoryURL": "https://github.com/tuist/XcodeProj.git", - "state": { - "branch": null, - "revision": "446f3a0db73e141c7f57e26fcdb043096b1db52c", - "version": "8.3.1" - } - }, - { - "package": "XcodeProjKit", - "repositoryURL": "https://github.com/phimage/XcodeProjKit.git", - "state": { - "branch": null, - "revision": "1fc861d368831f751341f804298e78ebb789592e", - "version": "2.2.0" - } - }, - { - "package": "Yaml", - "repositoryURL": "https://github.com/behrang/YamlSwift.git", - "state": { - "branch": null, - "revision": "287f5cab7da0d92eb947b5fd8151b203ae04a9a3", - "version": "3.4.4" - } - }, - { - "package": "Yams", - "repositoryURL": "https://github.com/jpsim/Yams.git", - "state": { - "branch": null, - "revision": "9ff1cc9327586db4e0c8f46f064b6a82ec1566fa", - "version": "4.0.6" - } + "pins" : [ + { + "identity" : "apikit", + "kind" : "remoteSourceControl", + "location" : "https://github.com/ishkawa/APIKit.git", + "state" : { + "revision" : "c8f5320d84c4c34c0fd965da3c7957819a1ccdd4", + "version" : "5.2.0" } - ] - }, - "version": 1 + }, + { + "identity" : "collectionconcurrencykit", + "kind" : "remoteSourceControl", + "location" : "https://github.com/JohnSundell/CollectionConcurrencyKit.git", + "state" : { + "revision" : "b4f23e24b5a1bff301efc5e70871083ca029ff95", + "version" : "0.2.0" + } + }, + { + "identity" : "colorizer", + "kind" : "remoteSourceControl", + "location" : "https://github.com/getGuaka/Colorizer.git", + "state" : { + "revision" : "2ccc99bf1715e73c4139e8d40b6e6b30be975586", + "version" : "0.2.1" + } + }, + { + "identity" : "heliumlogger", + "kind" : "remoteSourceControl", + "location" : "https://github.com/Kitura/HeliumLogger.git", + "state" : { + "revision" : "55fd2f0b70793017acee853c53cfcf8da0bd8d8d", + "version" : "1.9.200" + } + }, + { + "identity" : "licenseplist", + "kind" : "remoteSourceControl", + "location" : "https://github.com/mono0926/LicensePlist", + "state" : { + "revision" : "b6929adffb31749a9930fdb295f79e4027a18e25", + "version" : "3.19.1" + } + }, + { + "identity" : "loggerapi", + "kind" : "remoteSourceControl", + "location" : "https://github.com/Kitura/LoggerAPI.git", + "state" : { + "revision" : "e82d34eab3f0b05391082b11ea07d3b70d2f65bb", + "version" : "1.9.200" + } + }, + { + "identity" : "mockolo", + "kind" : "remoteSourceControl", + "location" : "https://github.com/uber/mockolo", + "state" : { + "revision" : "421fade55ae1636df0a28033938bfac345748374", + "version" : "1.7.1" + } + }, + { + "identity" : "sourcekitten", + "kind" : "remoteSourceControl", + "location" : "https://github.com/jpsim/SourceKitten.git", + "state" : { + "revision" : "b5f9bb749057dd396e93f97956bef64672bc2a04", + "version" : "0.33.0" + } + }, + { + "identity" : "swift-argument-parser", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-argument-parser.git", + "state" : { + "revision" : "9f39744e025c7d377987f30b03770805dcb0bcd1", + "version" : "1.1.4" + } + }, + { + "identity" : "swift-html-entities", + "kind" : "remoteSourceControl", + "location" : "https://github.com/Kitura/swift-html-entities.git", + "state" : { + "revision" : "2b14531d0c36dbb7c1c45a4d38db9c2e7898a307", + "version" : "3.0.200" + } + }, + { + "identity" : "swift-log", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-log.git", + "state" : { + "revision" : "5d66f7ba25daf4f94100e7022febf3c75e37a6c7", + "version" : "1.4.2" + } + }, + { + "identity" : "swift-syntax", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-syntax.git", + "state" : { + "revision" : "0b6c22b97f8e9320bca62e82cdbee601cf37ad3f", + "version" : "0.50600.1" + } + }, + { + "identity" : "swift-system", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-system.git", + "state" : { + "revision" : "836bc4557b74fe6d2660218d56e3ce96aff76574", + "version" : "1.1.1" + } + }, + { + "identity" : "swift-tools-support-core", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-tools-support-core.git", + "state" : { + "revision" : "4f07be3dc201f6e2ee85b6942d0c220a16926811", + "version" : "0.2.7" + } + }, + { + "identity" : "swiftlint", + "kind" : "remoteSourceControl", + "location" : "https://github.com/realm/SwiftLint", + "state" : { + "revision" : "57dc1c9532d660ff547dd8ba2176ad82c1175787", + "version" : "0.49.1" + } + }, + { + "identity" : "swiftytexttable", + "kind" : "remoteSourceControl", + "location" : "https://github.com/scottrhoyt/SwiftyTextTable.git", + "state" : { + "revision" : "c6df6cf533d120716bff38f8ff9885e1ce2a4ac3", + "version" : "0.9.0" + } + }, + { + "identity" : "swxmlhash", + "kind" : "remoteSourceControl", + "location" : "https://github.com/drmohundro/SWXMLHash.git", + "state" : { + "revision" : "4d0f62f561458cbe1f732171e625f03195151b60", + "version" : "7.0.1" + } + }, + { + "identity" : "xcbeautify", + "kind" : "remoteSourceControl", + "location" : "https://github.com/tuist/xcbeautify", + "state" : { + "revision" : "b14660cc03d96889d2144265fbca471ea0076e40", + "version" : "0.11.0" + } + }, + { + "identity" : "xmlcoder", + "kind" : "remoteSourceControl", + "location" : "https://github.com/MaxDesiatov/XMLCoder.git", + "state" : { + "revision" : "f30119af03996939cc4f54e0bf0dda9f88a84da5", + "version" : "0.13.1" + } + }, + { + "identity" : "yamlswift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/behrang/YamlSwift.git", + "state" : { + "revision" : "287f5cab7da0d92eb947b5fd8151b203ae04a9a3", + "version" : "3.4.4" + } + }, + { + "identity" : "yams", + "kind" : "remoteSourceControl", + "location" : "https://github.com/jpsim/Yams.git", + "state" : { + "revision" : "01835dc202670b5bb90d07f3eae41867e9ed29f6", + "version" : "5.0.1" + } + } + ], + "version" : 2 } diff --git a/Tools/UhooiPicBookTools/Package.swift b/Tools/UhooiPicBookTools/Package.swift index df2a0342..efa27289 100644 --- a/Tools/UhooiPicBookTools/Package.swift +++ b/Tools/UhooiPicBookTools/Package.swift @@ -1,20 +1,19 @@ -// swift-tools-version:5.4 +// swift-tools-version:5.7 + import PackageDescription let package = Package( name: "UhooiPicBookTools", platforms: [ - .macOS(.v11) + .macOS(.v12), ], dependencies: [ - .package(url: "https://github.com/yonaskolb/XcodeGen", .exact("2.25.0")), - .package(url: "https://github.com/realm/SwiftLint", .exact("0.43.1")), - .package(url: "https://github.com/IBDecodable/IBLinter", .exact("0.4.27")), - .package(url: "https://github.com/fromkk/SpellChecker", .exact("0.1.0")), - // .package(url: "https://github.com/uber/mockolo", .exact("1.6.1")), - .package(url: "https://github.com/mono0926/LicensePlist", .exact("3.13.0")), - .package(url: "https://github.com/mac-cain13/R.swift", .exact("5.4.0")), - .package(url: "https://github.com/thii/xcbeautify", .exact("0.9.1")) + .package(url: "https://github.com/realm/SwiftLint", exact: "0.49.1"), +// .package(url: "https://github.com/IBDecodable/IBLinter", exact: "0.5.0"), +// .package(url: "https://github.com/fromkk/SpellChecker", exact: "0.1.0"), + .package(url: "https://github.com/uber/mockolo", exact: "1.7.1"), + .package(url: "https://github.com/mono0926/LicensePlist", exact: "3.19.1"), + .package(url: "https://github.com/tuist/xcbeautify", exact: "0.11.0"), ], targets: [.target(name: "UhooiPicBookTools", path: "")] ) diff --git a/UhooiPicBook.xcworkspace/contents.xcworkspacedata b/UhooiPicBook.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..869475a2 --- /dev/null +++ b/UhooiPicBook.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,13 @@ + + + + + + + + + diff --git a/UhooiPicBook.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/UhooiPicBook.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/UhooiPicBook.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/UhooiPicBook.xcworkspace/xcshareddata/xcdebugger/Breakpoints_v2.xcbkptlist b/UhooiPicBook.xcworkspace/xcshareddata/xcdebugger/Breakpoints_v2.xcbkptlist new file mode 100644 index 00000000..80db7452 --- /dev/null +++ b/UhooiPicBook.xcworkspace/xcshareddata/xcdebugger/Breakpoints_v2.xcbkptlist @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + diff --git a/UhooiPicBook.xcworkspace/xcshareddata/xcschemes/AppModuleTests.xcscheme b/UhooiPicBook.xcworkspace/xcshareddata/xcschemes/AppModuleTests.xcscheme new file mode 100644 index 00000000..2b4c6293 --- /dev/null +++ b/UhooiPicBook.xcworkspace/xcshareddata/xcschemes/AppModuleTests.xcscheme @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/UhooiPicBook/Extensions/UIKit/UIView+Material.swift b/UhooiPicBook/Extensions/UIKit/UIView+Material.swift deleted file mode 100644 index e1cc2f4b..00000000 --- a/UhooiPicBook/Extensions/UIKit/UIView+Material.swift +++ /dev/null @@ -1,24 +0,0 @@ -// -// UIView+Material.swift -// UhooiPicBook -// -// Created by uhooi on 2020/03/01. -// - -import UIKit - -protocol MaterialView { - func elevate(elevation: Double) -} - -extension UIView: MaterialView { - - func elevate(elevation: Double) { - self.layer.masksToBounds = false - self.layer.shadowColor = UIColor.black.cgColor - self.layer.shadowOffset = CGSize(width: 0.0, height: elevation) - self.layer.shadowRadius = abs(CGFloat(elevation)) - self.layer.shadowOpacity = 0.24 - } - -} diff --git a/UhooiPicBook/Modules/MonsterList/Entities/MonsterEntity.swift b/UhooiPicBook/Modules/MonsterList/Entities/MonsterEntity.swift deleted file mode 100644 index 3fec356a..00000000 --- a/UhooiPicBook/Modules/MonsterList/Entities/MonsterEntity.swift +++ /dev/null @@ -1,18 +0,0 @@ -// -// MonsterEntity.swift -// UhooiPicBook -// -// Created by uhooi on 2020/02/28. -// - -import Foundation - -struct MonsterEntity: Equatable { - let name: String - let description: String - let baseColorCode: String - let iconUrl: URL - let dancingUrl: URL -} - -extension MonsterEntity: Codable {} diff --git a/UhooiPicBook/Modules/MonsterList/Interactors/MonsterListInteractor.swift b/UhooiPicBook/Modules/MonsterList/Interactors/MonsterListInteractor.swift deleted file mode 100644 index 608de367..00000000 --- a/UhooiPicBook/Modules/MonsterList/Interactors/MonsterListInteractor.swift +++ /dev/null @@ -1,53 +0,0 @@ -// -// MonsterListInteractor.swift -// UhooiPicBook -// -// Created by uhooi on 28/02/2020. -// Copyright © 2020 THE Uhooi. All rights reserved. -// - -/// @mockable -protocol MonsterListInteractorInput: AnyObject { - func fetchMonsters(_ completion: @escaping (Result<[MonsterDTO], Error>) -> Void) - func saveForSpotlight(_ monster: MonsterEntity) -} - -final class MonsterListInteractor { - - // MARK: Type Aliases - - // MARK: Stored Instance Properties - - weak var presenter: MonsterListInteractorOutput! - - private let monstersRepository: MonstersRepository - private let monstersTempRepository: MonstersTempRepository - private let spotlightRepository: SpotlightRepository - - // MARK: Computed Instance Properties - - // MARK: Initializer - - init(monstersRepository: MonstersRepository, monstersTempRepository: MonstersTempRepository, spotlightRepository: SpotlightRepository) { - self.monstersRepository = monstersRepository - self.monstersTempRepository = monstersTempRepository - self.spotlightRepository = spotlightRepository - } - - // MARK: Other Private Methods - -} - -extension MonsterListInteractor: MonsterListInteractorInput { - - func fetchMonsters(_ completion: @escaping (Result<[MonsterDTO], Error>) -> Void) { - self.monstersRepository.loadMonsters { completion($0) } - } - - func saveForSpotlight(_ monster: MonsterEntity) { - let key = "spotlight_\(monster.name)" - self.monstersTempRepository.saveMonster(monster, forKey: key) - self.spotlightRepository.saveMonster(monster, forKey: key) - } - -} diff --git a/UhooiPicBook/Modules/MonsterList/Presenters/MonsterListPresenter.swift b/UhooiPicBook/Modules/MonsterList/Presenters/MonsterListPresenter.swift deleted file mode 100644 index c142e0ad..00000000 --- a/UhooiPicBook/Modules/MonsterList/Presenters/MonsterListPresenter.swift +++ /dev/null @@ -1,110 +0,0 @@ -// -// MonsterListPresenter.swift -// UhooiPicBook -// -// Created by uhooi on 28/02/2020. -// Copyright © 2020 THE Uhooi. All rights reserved. -// - -import Foundation - -protocol MonsterListEventHandler: AnyObject { - func viewDidLoad() - func didSelectMonster(monster: MonsterEntity) - - // Menu - func didTapContactUs() - func didTapPrivacyPolicy() - func didTapLicenses() - func didTapAboutThisApp() -} - -/// @mockable -protocol MonsterListInteractorOutput: AnyObject { -} - -final class MonsterListPresenter { - - // MARK: Type Aliases - - // MARK: Stored Instance Properties - - private unowned let view: MonsterListUserInterface - private let interactor: MonsterListInteractorInput - private let router: MonsterListRouterInput - - // MARK: Computed Instance Properties - - // MARK: Initializers - - init(view: MonsterListUserInterface, interactor: MonsterListInteractorInput, router: MonsterListRouterInput) { - self.view = view - self.interactor = interactor - self.router = router - } - - // MARK: Other Private Methods - -} - -extension MonsterListPresenter: MonsterListEventHandler { - - func viewDidLoad() { - self.view.startIndicator() - self.interactor.fetchMonsters { result in - switch result { - case let .success(monsters): - let monsterEntities = monsters - .sorted { $0.order < $1.order } - .map { self.convertDTOToEntity(dto: $0) } - self.view.showMonsters(monsterEntities) - self.view.stopIndicator() - case let .failure(error): - // TODO: エラーハンドリング - self.view.stopIndicator() - } - } - } - - func didTapContactUs() { - self.router.showContactUs() - } - - func didTapPrivacyPolicy() { - self.router.showPrivacyPolicy() - } - - func didTapLicenses() { - self.router.showSettings() - } - - func didTapAboutThisApp() { - self.router.showAboutThisApp() - } - - func didSelectMonster(monster: MonsterEntity) { - self.interactor.saveForSpotlight(monster) - self.router.showMonsterDetail(monster: monster) - } - - // MARK: Other Private Methods - - private func convertDTOToEntity(dto: MonsterDTO) -> MonsterEntity { - guard let iconUrl = URL(string: dto.iconUrlString) else { - fatalError("Fail to load icon.") // TODO: エラーハンドリング - } - guard let dancingUrl = URL(string: dto.dancingUrlString) else { - fatalError("Fail to load dancing image.") // TODO: エラーハンドリング - } - - return MonsterEntity(name: dto.name, - description: dto.description.replacingOccurrences(of: "\\n", with: "\n"), - baseColorCode: dto.baseColorCode, - iconUrl: iconUrl, - dancingUrl: dancingUrl) - } - -} - -extension MonsterListPresenter: MonsterListInteractorOutput { -} diff --git a/UhooiPicBook/Modules/MonsterList/Routers/MonsterListRouter.swift b/UhooiPicBook/Modules/MonsterList/Routers/MonsterListRouter.swift deleted file mode 100644 index 51ae2677..00000000 --- a/UhooiPicBook/Modules/MonsterList/Routers/MonsterListRouter.swift +++ /dev/null @@ -1,101 +0,0 @@ -// -// MonsterListRouter.swift -// UhooiPicBook -// -// Created by uhooi on 28/02/2020. -// Copyright © 2020 THE Uhooi. All rights reserved. -// - -import UIKit - -/// @mockable -protocol MonsterListRouterInput: AnyObject { - func showMonsterDetail(monster: MonsterEntity) - - // Menu - func showContactUs() - func showPrivacyPolicy() - func showSettings() - func showAboutThisApp() -} - -final class MonsterListRouter { - - // MARK: Stored Instance Properties - - private unowned let viewController: MonsterListViewController - - // MARK: Initializers - - private init(viewController: MonsterListViewController) { - self.viewController = viewController - } - - // MARK: Type Methods - - static func assembleModule() -> MonsterListViewController { - guard let view = R.storyboard.monsterList.instantiateInitialViewController() else { - fatalError("Fail to load MonsterListViewController from Storyboard.") - } - let imageCacheManager: ImageCacheManagerProtocol = ImageCacheManager() - let interactor = MonsterListInteractor(monstersRepository: MonstersFirebaseClient(), - monstersTempRepository: UserDefaultsClient(), - spotlightRepository: SpotlightClient(imageCacheManager: imageCacheManager)) - let router = MonsterListRouter(viewController: view) - let presenter = MonsterListPresenter(view: view, interactor: interactor, router: router) - - view.presenter = presenter - view.imageCacheManager = imageCacheManager - interactor.presenter = presenter - - return view - } - - // MARK: Other Private Methods - -} - -extension MonsterListRouter: MonsterListRouterInput { - - func showMonsterDetail(monster: MonsterEntity) { - let vc = MonsterDetailRouter.assembleModule(monster: monster) - self.viewController.navigationController?.pushViewController(vc, animated: true) - } - - func showContactUs() { - guard let contactUsUrl = URL(string: R.string.localizable.contactUsURL()) else { - fatalError("Fail to initialize contact us URL.") - } - InAppWebBrowserRouter.show(self.viewController, url: contactUsUrl) - } - - func showPrivacyPolicy() { - guard let privacyPolicyUrl = URL(string: R.string.localizable.privacyPolicyURL()) else { - fatalError("Fail to initialize privacy policy URL.") - } - UIApplication.shared.open(privacyPolicyUrl) - } - - func showSettings() { - guard let settingsUrl = URL(string: UIApplication.openSettingsURLString), - UIApplication.shared.canOpenURL(settingsUrl) - else { - fatalError("Fail to open Settings URL.") - } - UIApplication.shared.open(settingsUrl) - } - - func showAboutThisApp() { - let title = Bundle.main.displayName - let message = """ -\(R.string.localizable.thisAppIsOpenSourceSoftware()) -\(R.string.localizable.uhooiPicBookGitHubURL()) - -\(R.string.localizable.version()) \(Bundle.main.version) (\(Bundle.main.build)) -\(R.string.localizable.copyright()) -""" - let okAction = UIAlertAction(title: R.string.localizable.oK(), style: .default) { _ in } - self.viewController.showAlert(title: title, message: message, actions: [okAction]) - } - -} diff --git a/UhooiPicBook/Modules/MonsterList/Views/MonsterListViewController.swift b/UhooiPicBook/Modules/MonsterList/Views/MonsterListViewController.swift deleted file mode 100644 index 93bef64f..00000000 --- a/UhooiPicBook/Modules/MonsterList/Views/MonsterListViewController.swift +++ /dev/null @@ -1,161 +0,0 @@ -// -// MonsterListViewController.swift -// UhooiPicBook -// -// Created by uhooi on 28/02/2020. -// Copyright © 2020 THE Uhooi. All rights reserved. -// - -import UIKit - -/// @mockable -protocol MonsterListUserInterface: AnyObject { - func showMonsters(_ monsters: [MonsterEntity]) - func startIndicator() - func stopIndicator() -} - -final class MonsterListViewController: UIViewController { - - // MARK: Type Aliases - - // MARK: Stored Instance Properties - - var presenter: MonsterListEventHandler! - var imageCacheManager: ImageCacheManagerProtocol! - - private var monsters: [MonsterEntity] = [] - - // MARK: Computed Instance Properties - - // MARK: IBOutlets - - @IBOutlet private weak var menuButton: UIBarButtonItem! { - willSet { - newValue.menu = UIMenu( - title: "", - children: [ - UIAction(title: R.string.localizable.contactUs()) { _ in - self.presenter.didTapContactUs() - }, - UIAction(title: R.string.localizable.privacyPolicy()) { _ in - self.presenter.didTapPrivacyPolicy() - }, - UIAction(title: R.string.localizable.licenses()) { _ in - self.presenter.didTapLicenses() - }, - UIAction(title: R.string.localizable.aboutThisApp()) { _ in - self.presenter.didTapAboutThisApp() - } - ] - ) - } - } - - @IBOutlet private weak var monstersCollectionView: UICollectionView! { - willSet { - newValue.register(R.nib.monsterCollectionViewCell) - } - } - - @IBOutlet private weak var activityIndicatorView: UIActivityIndicatorView! - - // MARK: View Life-Cycle Methods - - override func viewDidLoad() { - super.viewDidLoad() - - self.navigationController?.navigationBar.tintColor = .white - self.presenter.viewDidLoad() - } - - override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - - self.navigationController?.navigationBar.configureBackgroundColor(R.color.navigationBar()) - } - - // MARK: IBActions - - // MARK: Other Private Methods - -} - -extension MonsterListViewController: UICollectionViewDataSource { - - func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { - self.monsters.count - } - - func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { - guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: R.reuseIdentifier.monsterCollectionViewCell, for: indexPath) else { - fatalError("Fail to load MonsterCollectionViewCell.") - } - - let monster = self.monsters[indexPath.row] - - self.imageCacheManager.cacheImage(imageUrl: monster.iconUrl) { result in - switch result { - case let .success(icon): - DispatchQueue.main.async { - cell.setup(name: monster.name, icon: icon, elevation: 1.0) - } - case let .failure(error): - // TODO: エラーハンドリング - print(error) - } - } - - return cell - } - -} - -extension MonsterListViewController: UICollectionViewDelegateFlowLayout { - - func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { - CGSize(width: self.monstersCollectionView.frame.width - 16.0 * 2, height: 116.0) - } - - func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat { - 12.0 - } - - func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat { - 12.0 - } - -} - -extension MonsterListViewController: UICollectionViewDelegate { - - func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { - self.presenter.didSelectMonster(monster: self.monsters[indexPath.row]) - } - -} - -extension MonsterListViewController: MonsterListUserInterface { - - func showMonsters(_ monsters: [MonsterEntity]) { - self.monsters = monsters - DispatchQueue.main.async { - self.monstersCollectionView.reloadData() - self.monstersCollectionView.executeCellSlideUpAnimation() - } - } - - func startIndicator() { - DispatchQueue.main.async { - self.view.bringSubviewToFront(self.activityIndicatorView) - self.activityIndicatorView.startAnimating() - } - } - - func stopIndicator() { - DispatchQueue.main.async { - self.activityIndicatorView.stopAnimating() - } - } - -} diff --git a/UhooiPicBook/Repository/Spotlight/SpotlightRepository.swift b/UhooiPicBook/Repository/Spotlight/SpotlightRepository.swift deleted file mode 100644 index a751163e..00000000 --- a/UhooiPicBook/Repository/Spotlight/SpotlightRepository.swift +++ /dev/null @@ -1,59 +0,0 @@ -// -// SpotlightRepository.swift -// UhooiPicBook -// -// Created by Tomosuke Okada on 2020/05/11. -// - -import CoreGraphics.CGGeometry -import CoreSpotlight - -/// @mockable -protocol SpotlightRepository: AnyObject { // swiftlint:disable:this file_types_order - func saveMonster(_ monster: MonsterEntity, forKey key: String) -} - -final class SpotlightClient { - - // MARK: Stored Instance Properties - - private let searchableIndex = CSSearchableIndex.default() - private let imageCacheManager: ImageCacheManagerProtocol - - // MARK: Initializer - - init(imageCacheManager: ImageCacheManagerProtocol) { - self.imageCacheManager = imageCacheManager - } - -} - -extension SpotlightClient: SpotlightRepository { - - func saveMonster(_ monster: MonsterEntity, forKey key: String) { - self.imageCacheManager.cacheImage(imageUrl: monster.iconUrl) { result in - switch result { - case .success(let image): - let thumbnailData = image.resize(CGSize(width: 180.0, height: 180.0))?.pngData() - let item = CSSearchableItem( - uniqueIdentifier: key, - domainIdentifier: Bundle.main.infoDictionary?[kCFBundleNameKey as String] as? String, - attributeSet: self.createAttributeSet(title: monster.name, contentDescription: monster.description, thumbnailData: thumbnailData) - ) - self.searchableIndex.indexSearchableItems([item], completionHandler: nil) - case .failure: - // No need for error handling, as there is no need to give the user feedback on save failures for Spotlight search. - break - } - } - } - - private func createAttributeSet(title: String, contentDescription: String, thumbnailData: Data?) -> CSSearchableItemAttributeSet { - let attributeSet = CSSearchableItemAttributeSet(contentType: .data) - attributeSet.title = title - attributeSet.contentDescription = contentDescription - attributeSet.thumbnailData = thumbnailData - return attributeSet - } - -} diff --git a/UhooiPicBook/Repository/Temp/UserDefaultsClient.swift b/UhooiPicBook/Repository/Temp/UserDefaultsClient.swift deleted file mode 100644 index 28dacea4..00000000 --- a/UhooiPicBook/Repository/Temp/UserDefaultsClient.swift +++ /dev/null @@ -1,47 +0,0 @@ -// -// UserDefaultsClient.swift -// UhooiPicBook -// -// Created by uhooi on 2020/05/12. -// - -import Foundation - -final class UserDefaultsClient { - - // MARK: Stored Instance Properties - - private let userDefaults = UserDefaults.standard - - // MARK: Other Internal Methods - - func removeAll() { - self.userDefaults.dictionaryRepresentation().keys.forEach { self.userDefaults.removeObject(forKey: $0) } - } - -} - -extension UserDefaultsClient: MonstersTempRepository { - - func loadMonster(key: String) -> MonsterEntity? { - let jsonDecoder = JSONDecoder() - jsonDecoder.keyDecodingStrategy = .convertFromSnakeCase - - guard let data = self.userDefaults.data(forKey: key), - let monster = try? jsonDecoder.decode(MonsterEntity.self, from: data) else { - return nil - } - return monster - } - - func saveMonster(_ monster: MonsterEntity, forKey key: String) { - let jsonEncoder = JSONEncoder() - jsonEncoder.keyEncodingStrategy = .convertToSnakeCase - - guard let data = try? jsonEncoder.encode(monster) else { - return - } - self.userDefaults.set(data, forKey: key) - } - -} diff --git a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-DEVELOP.appiconset/Contents.json b/UhooiPicBook/Resources/Assets.xcassets/AppIcon-DEVELOP.appiconset/Contents.json deleted file mode 100644 index 0c6f80cb..00000000 --- a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-DEVELOP.appiconset/Contents.json +++ /dev/null @@ -1,116 +0,0 @@ -{ - "images" : [ - { - "filename" : "icon_develop_iPhone_Notifications@2x.png", - "idiom" : "iphone", - "scale" : "2x", - "size" : "20x20" - }, - { - "filename" : "icon_develop_iPhone_Notifications@3x.png", - "idiom" : "iphone", - "scale" : "3x", - "size" : "20x20" - }, - { - "filename" : "icon_develop_iPhone_Settings@2x.png", - "idiom" : "iphone", - "scale" : "2x", - "size" : "29x29" - }, - { - "filename" : "icon_develop_iPhone_Settings@3x.png", - "idiom" : "iphone", - "scale" : "3x", - "size" : "29x29" - }, - { - "filename" : "icon_develop_iPhone_Spotlight@2x.png", - "idiom" : "iphone", - "scale" : "2x", - "size" : "40x40" - }, - { - "filename" : "icon_develop_iPhone_Spotlight@3x.png", - "idiom" : "iphone", - "scale" : "3x", - "size" : "40x40" - }, - { - "filename" : "icon_develop_iPhone_App@2x.png", - "idiom" : "iphone", - "scale" : "2x", - "size" : "60x60" - }, - { - "filename" : "icon_develop_iPhone_App@3x.png", - "idiom" : "iphone", - "scale" : "3x", - "size" : "60x60" - }, - { - "filename" : "icon_develop_iPad_Notifications.png", - "idiom" : "ipad", - "scale" : "1x", - "size" : "20x20" - }, - { - "filename" : "icon_develop_iPad_Notifications@2x.png", - "idiom" : "ipad", - "scale" : "2x", - "size" : "20x20" - }, - { - "filename" : "icon_develop_iPad_Settings.png", - "idiom" : "ipad", - "scale" : "1x", - "size" : "29x29" - }, - { - "filename" : "icon_develop_iPad_Settings@2x.png", - "idiom" : "ipad", - "scale" : "2x", - "size" : "29x29" - }, - { - "filename" : "icon_develop_iPad_Spotlight.png", - "idiom" : "ipad", - "scale" : "1x", - "size" : "40x40" - }, - { - "filename" : "icon_develop_iPad_Spotlight@2x.png", - "idiom" : "ipad", - "scale" : "2x", - "size" : "40x40" - }, - { - "filename" : "icon_develop_iPad_App.png", - "idiom" : "ipad", - "scale" : "1x", - "size" : "76x76" - }, - { - "filename" : "icon_develop_iPad_App@2x.png", - "idiom" : "ipad", - "scale" : "2x", - "size" : "76x76" - }, - { - "filename" : "icon_develop_iPadPro_App@2x.png", - "idiom" : "ipad", - "scale" : "2x", - "size" : "83.5x83.5" - }, - { - "filename" : "icon_develop_AppStore.png", - "idiom" : "ios-marketing", - "scale" : "1x", - "size" : "1024x1024" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-DEVELOP.appiconset/icon_develop_iPadPro_App@2x.png b/UhooiPicBook/Resources/Assets.xcassets/AppIcon-DEVELOP.appiconset/icon_develop_iPadPro_App@2x.png deleted file mode 100644 index bf4fb660..00000000 Binary files a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-DEVELOP.appiconset/icon_develop_iPadPro_App@2x.png and /dev/null differ diff --git a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-DEVELOP.appiconset/icon_develop_iPad_App.png b/UhooiPicBook/Resources/Assets.xcassets/AppIcon-DEVELOP.appiconset/icon_develop_iPad_App.png deleted file mode 100644 index 5e8d3634..00000000 Binary files a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-DEVELOP.appiconset/icon_develop_iPad_App.png and /dev/null differ diff --git a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-DEVELOP.appiconset/icon_develop_iPad_App@2x.png b/UhooiPicBook/Resources/Assets.xcassets/AppIcon-DEVELOP.appiconset/icon_develop_iPad_App@2x.png deleted file mode 100644 index 25228a52..00000000 Binary files a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-DEVELOP.appiconset/icon_develop_iPad_App@2x.png and /dev/null differ diff --git a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-DEVELOP.appiconset/icon_develop_iPad_Notifications.png b/UhooiPicBook/Resources/Assets.xcassets/AppIcon-DEVELOP.appiconset/icon_develop_iPad_Notifications.png deleted file mode 100644 index 5eace0f8..00000000 Binary files a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-DEVELOP.appiconset/icon_develop_iPad_Notifications.png and /dev/null differ diff --git a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-DEVELOP.appiconset/icon_develop_iPad_Notifications@2x.png b/UhooiPicBook/Resources/Assets.xcassets/AppIcon-DEVELOP.appiconset/icon_develop_iPad_Notifications@2x.png deleted file mode 100644 index 085851a1..00000000 Binary files a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-DEVELOP.appiconset/icon_develop_iPad_Notifications@2x.png and /dev/null differ diff --git a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-DEVELOP.appiconset/icon_develop_iPad_Settings.png b/UhooiPicBook/Resources/Assets.xcassets/AppIcon-DEVELOP.appiconset/icon_develop_iPad_Settings.png deleted file mode 100644 index eb6967dd..00000000 Binary files a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-DEVELOP.appiconset/icon_develop_iPad_Settings.png and /dev/null differ diff --git a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-DEVELOP.appiconset/icon_develop_iPad_Settings@2x.png b/UhooiPicBook/Resources/Assets.xcassets/AppIcon-DEVELOP.appiconset/icon_develop_iPad_Settings@2x.png deleted file mode 100644 index bcabc866..00000000 Binary files a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-DEVELOP.appiconset/icon_develop_iPad_Settings@2x.png and /dev/null differ diff --git a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-DEVELOP.appiconset/icon_develop_iPad_Spotlight.png b/UhooiPicBook/Resources/Assets.xcassets/AppIcon-DEVELOP.appiconset/icon_develop_iPad_Spotlight.png deleted file mode 100644 index 085851a1..00000000 Binary files a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-DEVELOP.appiconset/icon_develop_iPad_Spotlight.png and /dev/null differ diff --git a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-DEVELOP.appiconset/icon_develop_iPad_Spotlight@2x.png b/UhooiPicBook/Resources/Assets.xcassets/AppIcon-DEVELOP.appiconset/icon_develop_iPad_Spotlight@2x.png deleted file mode 100644 index be5247a7..00000000 Binary files a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-DEVELOP.appiconset/icon_develop_iPad_Spotlight@2x.png and /dev/null differ diff --git a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-DEVELOP.appiconset/icon_develop_iPhone_App@2x.png b/UhooiPicBook/Resources/Assets.xcassets/AppIcon-DEVELOP.appiconset/icon_develop_iPhone_App@2x.png deleted file mode 100644 index 68c93bf5..00000000 Binary files a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-DEVELOP.appiconset/icon_develop_iPhone_App@2x.png and /dev/null differ diff --git a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-DEVELOP.appiconset/icon_develop_iPhone_App@3x.png b/UhooiPicBook/Resources/Assets.xcassets/AppIcon-DEVELOP.appiconset/icon_develop_iPhone_App@3x.png deleted file mode 100644 index 3c61214b..00000000 Binary files a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-DEVELOP.appiconset/icon_develop_iPhone_App@3x.png and /dev/null differ diff --git a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-DEVELOP.appiconset/icon_develop_iPhone_Notifications@2x.png b/UhooiPicBook/Resources/Assets.xcassets/AppIcon-DEVELOP.appiconset/icon_develop_iPhone_Notifications@2x.png deleted file mode 100644 index 085851a1..00000000 Binary files a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-DEVELOP.appiconset/icon_develop_iPhone_Notifications@2x.png and /dev/null differ diff --git a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-DEVELOP.appiconset/icon_develop_iPhone_Notifications@3x.png b/UhooiPicBook/Resources/Assets.xcassets/AppIcon-DEVELOP.appiconset/icon_develop_iPhone_Notifications@3x.png deleted file mode 100644 index 03c52073..00000000 Binary files a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-DEVELOP.appiconset/icon_develop_iPhone_Notifications@3x.png and /dev/null differ diff --git a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-DEVELOP.appiconset/icon_develop_iPhone_Settings@2x.png b/UhooiPicBook/Resources/Assets.xcassets/AppIcon-DEVELOP.appiconset/icon_develop_iPhone_Settings@2x.png deleted file mode 100644 index bcabc866..00000000 Binary files a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-DEVELOP.appiconset/icon_develop_iPhone_Settings@2x.png and /dev/null differ diff --git a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-DEVELOP.appiconset/icon_develop_iPhone_Settings@3x.png b/UhooiPicBook/Resources/Assets.xcassets/AppIcon-DEVELOP.appiconset/icon_develop_iPhone_Settings@3x.png deleted file mode 100644 index f9921597..00000000 Binary files a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-DEVELOP.appiconset/icon_develop_iPhone_Settings@3x.png and /dev/null differ diff --git a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-DEVELOP.appiconset/icon_develop_iPhone_Spotlight@2x.png b/UhooiPicBook/Resources/Assets.xcassets/AppIcon-DEVELOP.appiconset/icon_develop_iPhone_Spotlight@2x.png deleted file mode 100644 index be5247a7..00000000 Binary files a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-DEVELOP.appiconset/icon_develop_iPhone_Spotlight@2x.png and /dev/null differ diff --git a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-DEVELOP.appiconset/icon_develop_iPhone_Spotlight@3x.png b/UhooiPicBook/Resources/Assets.xcassets/AppIcon-DEVELOP.appiconset/icon_develop_iPhone_Spotlight@3x.png deleted file mode 100644 index 68c93bf5..00000000 Binary files a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-DEVELOP.appiconset/icon_develop_iPhone_Spotlight@3x.png and /dev/null differ diff --git a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-PRODUCTION.appiconset/Contents.json b/UhooiPicBook/Resources/Assets.xcassets/AppIcon-PRODUCTION.appiconset/Contents.json deleted file mode 100644 index 8459122c..00000000 --- a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-PRODUCTION.appiconset/Contents.json +++ /dev/null @@ -1,116 +0,0 @@ -{ - "images" : [ - { - "filename" : "uhooipicbook_iPhone_Notifications@2x.png", - "idiom" : "iphone", - "scale" : "2x", - "size" : "20x20" - }, - { - "filename" : "uhooipicbook_iPhone_Notifications@3x.png", - "idiom" : "iphone", - "scale" : "3x", - "size" : "20x20" - }, - { - "filename" : "uhooipicbook_iPhone_Settings@2x.png", - "idiom" : "iphone", - "scale" : "2x", - "size" : "29x29" - }, - { - "filename" : "uhooipicbook_iPhone_Settings@3x.png", - "idiom" : "iphone", - "scale" : "3x", - "size" : "29x29" - }, - { - "filename" : "uhooipicbook_iPhone_Spotlight@2x.png", - "idiom" : "iphone", - "scale" : "2x", - "size" : "40x40" - }, - { - "filename" : "uhooipicbook_iPhone_Spotlight@3x.png", - "idiom" : "iphone", - "scale" : "3x", - "size" : "40x40" - }, - { - "filename" : "uhooipicbook_iPhone_App@2x.png", - "idiom" : "iphone", - "scale" : "2x", - "size" : "60x60" - }, - { - "filename" : "uhooipicbook_iPhone_App@3x.png", - "idiom" : "iphone", - "scale" : "3x", - "size" : "60x60" - }, - { - "filename" : "uhooipicbook_iPad_Notifications.png", - "idiom" : "ipad", - "scale" : "1x", - "size" : "20x20" - }, - { - "filename" : "uhooipicbook_iPad_Notifications@2x.png", - "idiom" : "ipad", - "scale" : "2x", - "size" : "20x20" - }, - { - "filename" : "uhooipicbook_iPad_Settings.png", - "idiom" : "ipad", - "scale" : "1x", - "size" : "29x29" - }, - { - "filename" : "uhooipicbook_iPad_Settings@2x.png", - "idiom" : "ipad", - "scale" : "2x", - "size" : "29x29" - }, - { - "filename" : "uhooipicbook_iPad_Spotlight.png", - "idiom" : "ipad", - "scale" : "1x", - "size" : "40x40" - }, - { - "filename" : "uhooipicbook_iPad_Spotlight@2x.png", - "idiom" : "ipad", - "scale" : "2x", - "size" : "40x40" - }, - { - "filename" : "uhooipicbook_iPad_App.png", - "idiom" : "ipad", - "scale" : "1x", - "size" : "76x76" - }, - { - "filename" : "uhooipicbook_iPad_App@2x.png", - "idiom" : "ipad", - "scale" : "2x", - "size" : "76x76" - }, - { - "filename" : "uhooipicbook_iPadPro_App@2x.png", - "idiom" : "ipad", - "scale" : "2x", - "size" : "83.5x83.5" - }, - { - "filename" : "uhooipicbook_AppStore.png", - "idiom" : "ios-marketing", - "scale" : "1x", - "size" : "1024x1024" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-PRODUCTION.appiconset/uhooipicbook_iPadPro_App@2x.png b/UhooiPicBook/Resources/Assets.xcassets/AppIcon-PRODUCTION.appiconset/uhooipicbook_iPadPro_App@2x.png deleted file mode 100644 index bf56e1b2..00000000 Binary files a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-PRODUCTION.appiconset/uhooipicbook_iPadPro_App@2x.png and /dev/null differ diff --git a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-PRODUCTION.appiconset/uhooipicbook_iPad_App.png b/UhooiPicBook/Resources/Assets.xcassets/AppIcon-PRODUCTION.appiconset/uhooipicbook_iPad_App.png deleted file mode 100644 index 799a5358..00000000 Binary files a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-PRODUCTION.appiconset/uhooipicbook_iPad_App.png and /dev/null differ diff --git a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-PRODUCTION.appiconset/uhooipicbook_iPad_App@2x.png b/UhooiPicBook/Resources/Assets.xcassets/AppIcon-PRODUCTION.appiconset/uhooipicbook_iPad_App@2x.png deleted file mode 100644 index 91182c80..00000000 Binary files a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-PRODUCTION.appiconset/uhooipicbook_iPad_App@2x.png and /dev/null differ diff --git a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-PRODUCTION.appiconset/uhooipicbook_iPad_Notifications.png b/UhooiPicBook/Resources/Assets.xcassets/AppIcon-PRODUCTION.appiconset/uhooipicbook_iPad_Notifications.png deleted file mode 100644 index 2cdf0bf9..00000000 Binary files a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-PRODUCTION.appiconset/uhooipicbook_iPad_Notifications.png and /dev/null differ diff --git a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-PRODUCTION.appiconset/uhooipicbook_iPad_Notifications@2x.png b/UhooiPicBook/Resources/Assets.xcassets/AppIcon-PRODUCTION.appiconset/uhooipicbook_iPad_Notifications@2x.png deleted file mode 100644 index 37ec99bc..00000000 Binary files a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-PRODUCTION.appiconset/uhooipicbook_iPad_Notifications@2x.png and /dev/null differ diff --git a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-PRODUCTION.appiconset/uhooipicbook_iPad_Settings.png b/UhooiPicBook/Resources/Assets.xcassets/AppIcon-PRODUCTION.appiconset/uhooipicbook_iPad_Settings.png deleted file mode 100644 index debbacef..00000000 Binary files a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-PRODUCTION.appiconset/uhooipicbook_iPad_Settings.png and /dev/null differ diff --git a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-PRODUCTION.appiconset/uhooipicbook_iPad_Spotlight.png b/UhooiPicBook/Resources/Assets.xcassets/AppIcon-PRODUCTION.appiconset/uhooipicbook_iPad_Spotlight.png deleted file mode 100644 index 37ec99bc..00000000 Binary files a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-PRODUCTION.appiconset/uhooipicbook_iPad_Spotlight.png and /dev/null differ diff --git a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-PRODUCTION.appiconset/uhooipicbook_iPad_Spotlight@2x.png b/UhooiPicBook/Resources/Assets.xcassets/AppIcon-PRODUCTION.appiconset/uhooipicbook_iPad_Spotlight@2x.png deleted file mode 100644 index b1cae43e..00000000 Binary files a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-PRODUCTION.appiconset/uhooipicbook_iPad_Spotlight@2x.png and /dev/null differ diff --git a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-PRODUCTION.appiconset/uhooipicbook_iPhone_App@2x.png b/UhooiPicBook/Resources/Assets.xcassets/AppIcon-PRODUCTION.appiconset/uhooipicbook_iPhone_App@2x.png deleted file mode 100644 index c2639e27..00000000 Binary files a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-PRODUCTION.appiconset/uhooipicbook_iPhone_App@2x.png and /dev/null differ diff --git a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-PRODUCTION.appiconset/uhooipicbook_iPhone_App@3x.png b/UhooiPicBook/Resources/Assets.xcassets/AppIcon-PRODUCTION.appiconset/uhooipicbook_iPhone_App@3x.png deleted file mode 100644 index c3f4b21f..00000000 Binary files a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-PRODUCTION.appiconset/uhooipicbook_iPhone_App@3x.png and /dev/null differ diff --git a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-PRODUCTION.appiconset/uhooipicbook_iPhone_Notifications@2x.png b/UhooiPicBook/Resources/Assets.xcassets/AppIcon-PRODUCTION.appiconset/uhooipicbook_iPhone_Notifications@2x.png deleted file mode 100644 index 37ec99bc..00000000 Binary files a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-PRODUCTION.appiconset/uhooipicbook_iPhone_Notifications@2x.png and /dev/null differ diff --git a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-PRODUCTION.appiconset/uhooipicbook_iPhone_Notifications@3x.png b/UhooiPicBook/Resources/Assets.xcassets/AppIcon-PRODUCTION.appiconset/uhooipicbook_iPhone_Notifications@3x.png deleted file mode 100644 index ce45ad44..00000000 Binary files a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-PRODUCTION.appiconset/uhooipicbook_iPhone_Notifications@3x.png and /dev/null differ diff --git a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-PRODUCTION.appiconset/uhooipicbook_iPhone_Spotlight@2x.png b/UhooiPicBook/Resources/Assets.xcassets/AppIcon-PRODUCTION.appiconset/uhooipicbook_iPhone_Spotlight@2x.png deleted file mode 100644 index b1cae43e..00000000 Binary files a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-PRODUCTION.appiconset/uhooipicbook_iPhone_Spotlight@2x.png and /dev/null differ diff --git a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-PRODUCTION.appiconset/uhooipicbook_iPhone_Spotlight@3x.png b/UhooiPicBook/Resources/Assets.xcassets/AppIcon-PRODUCTION.appiconset/uhooipicbook_iPhone_Spotlight@3x.png deleted file mode 100644 index c2639e27..00000000 Binary files a/UhooiPicBook/Resources/Assets.xcassets/AppIcon-PRODUCTION.appiconset/uhooipicbook_iPhone_Spotlight@3x.png and /dev/null differ diff --git a/UhooiPicBook/Util/Debug.swift b/UhooiPicBook/Util/Debug.swift deleted file mode 100644 index 18016a6b..00000000 --- a/UhooiPicBook/Util/Debug.swift +++ /dev/null @@ -1,11 +0,0 @@ -// -// Debug.swift -// UhooiPicBook -// -// Created by uhooi on 2020/05/08. -// - -#if DEBUG -import SwiftPrettyPrint -typealias Debug = SwiftPrettyPrint.Pretty -#endif diff --git a/UhooiPicBookStickers/Stickers.xcassets/iMessage App Icon.stickersiconset/uhooipicbook_iPad_Settings@2x.png b/UhooiPicBookStickers/Stickers.xcassets/iMessage App Icon.stickersiconset/uhooipicbook_iPad_Settings@2x.png deleted file mode 100644 index d11ccd0c..00000000 Binary files a/UhooiPicBookStickers/Stickers.xcassets/iMessage App Icon.stickersiconset/uhooipicbook_iPad_Settings@2x.png and /dev/null differ diff --git a/UhooiPicBookStickers/Stickers.xcassets/iMessage App Icon.stickersiconset/uhooipicbook_iPhone_Settings@2x.png b/UhooiPicBookStickers/Stickers.xcassets/iMessage App Icon.stickersiconset/uhooipicbook_iPhone_Settings@2x.png deleted file mode 100644 index d11ccd0c..00000000 Binary files a/UhooiPicBookStickers/Stickers.xcassets/iMessage App Icon.stickersiconset/uhooipicbook_iPhone_Settings@2x.png and /dev/null differ diff --git a/UhooiPicBookStickers/Stickers.xcassets/iMessage App Icon.stickersiconset/uhooipicbook_iPhone_Settings@3x.png b/UhooiPicBookStickers/Stickers.xcassets/iMessage App Icon.stickersiconset/uhooipicbook_iPhone_Settings@3x.png deleted file mode 100644 index ee374be0..00000000 Binary files a/UhooiPicBookStickers/Stickers.xcassets/iMessage App Icon.stickersiconset/uhooipicbook_iPhone_Settings@3x.png and /dev/null differ diff --git a/UhooiPicBookTests/Modules/MonsterList/Interactors/MonsterListInteractorTests.swift b/UhooiPicBookTests/Modules/MonsterList/Interactors/MonsterListInteractorTests.swift deleted file mode 100644 index 901ae50e..00000000 --- a/UhooiPicBookTests/Modules/MonsterList/Interactors/MonsterListInteractorTests.swift +++ /dev/null @@ -1,98 +0,0 @@ -// -// MonsterListInteractorTests.swift -// UhooiPicBookTests -// -// Created by uhooi on 28/02/2020. -// Copyright © 2020 THE Uhooi. All rights reserved. -// - -import XCTest -@testable import UhooiPicBook - -final class MonsterListInteractorTests: XCTestCase { - - // MARK: Stored Instance Properties - - private var presenterMock: MonsterListInteractorOutputMock! - private var monstersRepositoryMock: MonstersRepositoryMock! - private var monstersTempRepositoryMock: MonstersTempRepositoryMock! - private var spotlightRepositoryMock: SpotlightRepositoryMock! - private var interactor: MonsterListInteractor! - - // MARK: TestCase Life-Cycle Methods - - override func setUpWithError() throws { - reset() - } - - override func tearDownWithError() throws { - // Put teardown code here. This method is called after the invocation of each test method in the class. - } - - // MARK: - Test Methods - - // MARK: MonsterListInteractorInput - - // MARK: fetchMonsters() - - func test_fetchMonsters_success() { - let monsterDTOs: [MonsterDTO] = [] - self.monstersRepositoryMock.loadMonstersHandler = { result in - result(.success(monsterDTOs)) - } - - self.interactor.fetchMonsters { result in - switch result { - case let .success(monsters): - XCTAssertEqual(monsters, monsterDTOs) - case let .failure(error): - XCTFail("Error: \(error)") - } - XCTAssertEqual(self.monstersRepositoryMock.loadMonstersCallCount, 1) - } - } - - func test_fetchMonsters_failure() { - enum TestError: Error { - case test - } - self.monstersRepositoryMock.loadMonstersHandler = { result in - result(.failure(TestError.test)) - } - - self.interactor.fetchMonsters { result in - switch result { - case let .success(monsters): - XCTFail("Monsters: \(monsters)") - case let .failure(error): - XCTAssertEqual(error as! TestError, TestError.test) - } - XCTAssertEqual(self.monstersRepositoryMock.loadMonstersCallCount, 1) - } - } - - // saveForSpotlight() - - func test_saveForSpotlight() { - let uhooiEntity = MonsterEntity(name: "uhooi", description: "uhooi's description\nuhooi", baseColorCode: "#FFFFFF", iconUrl: URL(string: "https://theuhooi.com/uhooi")!, dancingUrl: URL(string: "https://theuhooi.com/uhooi-dancing")!) - - self.interactor.saveForSpotlight(uhooiEntity) - - XCTAssertEqual(self.monstersTempRepositoryMock.saveMonsterCallCount, 1) - XCTAssertEqual(self.spotlightRepositoryMock.saveMonsterCallCount, 1) - } - - // MARK: - Other Private Methods - - private func reset() { - self.presenterMock = MonsterListInteractorOutputMock() - self.monstersRepositoryMock = MonstersRepositoryMock() - self.monstersTempRepositoryMock = MonstersTempRepositoryMock() - self.spotlightRepositoryMock = SpotlightRepositoryMock() - self.interactor = MonsterListInteractor(monstersRepository: self.monstersRepositoryMock, - monstersTempRepository: self.monstersTempRepositoryMock, - spotlightRepository: self.spotlightRepositoryMock) - self.interactor.presenter = self.presenterMock - } - -} diff --git a/UhooiPicBookTests/Modules/MonsterList/Presenters/MonsterListPresenterTests.swift b/UhooiPicBookTests/Modules/MonsterList/Presenters/MonsterListPresenterTests.swift deleted file mode 100644 index 32a58981..00000000 --- a/UhooiPicBookTests/Modules/MonsterList/Presenters/MonsterListPresenterTests.swift +++ /dev/null @@ -1,204 +0,0 @@ -// -// MonsterListPresenterTests.swift -// UhooiPicBookTests -// -// Created by uhooi on 28/02/2020. -// Copyright © 2020 THE Uhooi. All rights reserved. -// - -import XCTest -@testable import UhooiPicBook - -final class MonsterListPresenterTests: XCTestCase { - - // MARK: Stored Instance Properties - - private var viewMock: MonsterListUserInterfaceMock! - private var interactorMock: MonsterListInteractorInputMock! - private var routerMock: MonsterListRouterInputMock! - private var presenter: MonsterListPresenter! - - // MARK: TestCase Life-Cycle Methods - - override func setUpWithError() throws { - reset() - } - - override func tearDownWithError() throws { - // Put teardown code here. This method is called after the invocation of each test method in the class. - } - - // MARK: - Test Methods - - // MARK: MonsterListEventHandler - - // MARK: viewDidLoad() - - func test_viewDidLoad_success_zero() { - let monsterDTOs: [MonsterDTO] = [] - self.interactorMock.fetchMonstersHandler = { completion in - completion(.success(monsterDTOs)) - } - self.viewMock.showMonstersHandler = { monsters in - for index in 0 ..< monsterDTOs.count { - XCTAssertEqual(monsters[index].name, monsterDTOs[index].name) - XCTAssertEqual(monsters[index].description, monsterDTOs[index].description) - let iconUrl = URL(string: monsterDTOs[index].iconUrlString) - XCTAssertEqual(monsters[index].iconUrl, iconUrl) - } - } - - self.presenter.viewDidLoad() - - XCTAssertEqual(self.viewMock.startIndicatorCallCount, 1) - XCTAssertEqual(self.interactorMock.fetchMonstersCallCount, 1) - XCTAssertEqual(self.viewMock.showMonstersCallCount, 1) - XCTAssertEqual(self.viewMock.stopIndicatorCallCount, 1) - } - - func test_viewDidLoad_success_three() { - let uhooiDTO = MonsterDTO(name: "uhooi", description: "uhooi's description", baseColorCode: "#FFFFFF", iconUrlString: "https://theuhooi.com/uhooi", dancingUrlString: "https://theuhooi.com/uhooi-dancing", order: 1) - let ayausaDTO = MonsterDTO(name: "ayausa", description: "ayausa's description", baseColorCode: "#FFFFFF", iconUrlString: "https://theuhooi.com/ayausa", dancingUrlString: "https://theuhooi.com/ayausa-dancing", order: 2) - let chibirdDTO = MonsterDTO(name: "chibird", description: "chibird's description", baseColorCode: "#FFFFFF", iconUrlString: "https://theuhooi.com/chibird", dancingUrlString: "https://theuhooi.com/chibird-dancing", order: 3) - let monsterDTOs = [uhooiDTO, ayausaDTO, chibirdDTO] - self.interactorMock.fetchMonstersHandler = { completion in - completion(.success(monsterDTOs)) - } - self.viewMock.showMonstersHandler = { monsters in - for index in 0 ..< monsterDTOs.count { - XCTAssertEqual(monsters[index].name, monsterDTOs[index].name) - XCTAssertEqual(monsters[index].description, monsterDTOs[index].description) - let iconUrl = URL(string: monsterDTOs[index].iconUrlString) - XCTAssertEqual(monsters[index].iconUrl, iconUrl) - } - } - - self.presenter.viewDidLoad() - - XCTAssertEqual(self.viewMock.startIndicatorCallCount, 1) - XCTAssertEqual(self.interactorMock.fetchMonstersCallCount, 1) - XCTAssertEqual(self.viewMock.showMonstersCallCount, 1) - XCTAssertEqual(self.viewMock.stopIndicatorCallCount, 1) - } - - func test_viewDidLoad_newLine() { - typealias TestCase = (description: String, expected: String, line: UInt) - let testCases: [TestCase] = [ - ("", "" , #line), - ("¥¥n", "¥¥n" , #line), - ("\n", "\n" , #line), - ("\\n", "\n" , #line), - // ("\\\n", "\\n" ,#line), - ("\\n\\n", "\n\n" , #line), - ("test\\nuhooi", "test\nuhooi" , #line), - ] - - for (description, expected, line) in testCases { - reset() - let monsterDTO = MonsterDTO( - name: "monster's name", - description: description, - baseColorCode: "#FFFFFF", - iconUrlString: "https://theuhooi.com/monster", - dancingUrlString: "https://theuhooi.com/monster-dancing", - order: 1 - ) - self.interactorMock.fetchMonstersHandler = { completion in - completion(.success([monsterDTO])) - } - self.viewMock.showMonstersHandler = { monsters in - XCTAssertEqual(monsters[0].description, expected, line: line) - } - - self.presenter.viewDidLoad() - - XCTAssertEqual(self.viewMock.startIndicatorCallCount, 1) - XCTAssertEqual(self.interactorMock.fetchMonstersCallCount, 1) - XCTAssertEqual(self.viewMock.showMonstersCallCount, 1) - XCTAssertEqual(self.viewMock.stopIndicatorCallCount, 1) - } - } - - func test_viewDidLoad_failure() { - enum TestError: Error { - case test - } - self.interactorMock.fetchMonstersHandler = { completion in - completion(.failure(TestError.test)) - } - - self.presenter.viewDidLoad() - - XCTAssertEqual(self.viewMock.startIndicatorCallCount, 1) - XCTAssertEqual(self.interactorMock.fetchMonstersCallCount, 1) - XCTAssertEqual(self.viewMock.showMonstersCallCount, 0) - XCTAssertEqual(self.viewMock.stopIndicatorCallCount, 1) - } - - // MARK: didSelectMonster() - - func test_didSelectMonster() { - let uhooiEntity = MonsterEntity(name: "uhooi", description: "uhooi's description\nuhooi", baseColorCode: "#FFFFFF", iconUrl: URL(string: "https://theuhooi.com/uhooi")!, dancingUrl: URL(string: "https://theuhooi.com/uhooi-dancing")!) - - self.presenter.didSelectMonster(monster: uhooiEntity) - - XCTAssertEqual(self.interactorMock.saveForSpotlightCallCount, 1) - XCTAssertEqual(self.routerMock.showMonsterDetailCallCount, 1) - } - - // MARK: didTapContactUs() - - func test_didTapContactUs() { - self.presenter.didTapContactUs() - - XCTAssertEqual(self.routerMock.showContactUsCallCount, 1) - XCTAssertEqual(self.routerMock.showPrivacyPolicyCallCount, 0) - XCTAssertEqual(self.routerMock.showSettingsCallCount, 0) - XCTAssertEqual(self.routerMock.showAboutThisAppCallCount, 0) - } - - // MARK: didTapPrivacyPolicy() - - func test_didTapPrivacyPolicy() { - self.presenter.didTapPrivacyPolicy() - - XCTAssertEqual(self.routerMock.showContactUsCallCount, 0) - XCTAssertEqual(self.routerMock.showPrivacyPolicyCallCount, 1) - XCTAssertEqual(self.routerMock.showSettingsCallCount, 0) - XCTAssertEqual(self.routerMock.showAboutThisAppCallCount, 0) - } - - // MARK: didTapLicenses() - - func test_didTapLicenses() { - self.presenter.didTapLicenses() - - XCTAssertEqual(self.routerMock.showContactUsCallCount, 0) - XCTAssertEqual(self.routerMock.showPrivacyPolicyCallCount, 0) - XCTAssertEqual(self.routerMock.showSettingsCallCount, 1) - XCTAssertEqual(self.routerMock.showAboutThisAppCallCount, 0) - } - - // MARK: didTapAboutThisApp() - - func test_didTapAboutThisApp() { - self.presenter.didTapAboutThisApp() - - XCTAssertEqual(self.routerMock.showContactUsCallCount, 0) - XCTAssertEqual(self.routerMock.showPrivacyPolicyCallCount, 0) - XCTAssertEqual(self.routerMock.showSettingsCallCount, 0) - XCTAssertEqual(self.routerMock.showAboutThisAppCallCount, 1) - } - - // MARK: MonsterListInteractorOutput - - // MARK: - Other Private Methods - - private func reset() { - self.viewMock = MonsterListUserInterfaceMock() - self.interactorMock = MonsterListInteractorInputMock() - self.routerMock = MonsterListRouterInputMock() - self.presenter = MonsterListPresenter(view: self.viewMock, interactor: self.interactorMock, router: self.routerMock) - } - -} diff --git a/UhooiPicBookWidgets/Monster/MonsterConfigurableWidget.swift b/UhooiPicBookWidgets/Monster/MonsterConfigurableWidget.swift deleted file mode 100644 index 72deda84..00000000 --- a/UhooiPicBookWidgets/Monster/MonsterConfigurableWidget.swift +++ /dev/null @@ -1,69 +0,0 @@ -// -// MonsterConfigurableWidget.swift -// UhooiPicBookWidgets -// -// Created by Takehito Koshimizu on 2020/11/14. -// - -import WidgetKit -import SwiftUI - -private struct MonsterProvider { - typealias Entry = MonsterEntry - typealias Intent = SelectMonsterIntent - - private let imageManager: ImageCacheManagerProtocol - - init(imageManager: ImageCacheManagerProtocol) { - self.imageManager = imageManager - } -} - -struct MonsterConfigurableWidget: Widget { - var body: some WidgetConfiguration { - IntentConfiguration( - kind: "MonsterConfigurable", - intent: SelectMonsterIntent.self, - provider: MonsterProvider(imageManager: ImageCacheManager()) - ) { entry in - MonsterEntryView(entry: entry) - } - .configurationDisplayName("Configuration display name") - .description("Configurable description") - .supportedFamilies([.systemSmall, .systemMedium]) - } -} - -extension MonsterProvider: IntentTimelineProvider { - func placeholder(in context: Context) -> Entry { - .createDefault() - } - - func getSnapshot(for intent: Intent, in context: Context, completion: @escaping (Entry) -> Void) { - completion(.createDefault()) - } - - func getTimeline(for intent: Intent, in context: Context, completion: @escaping (Timeline) -> Void) { - convertDTOToEntry(dto: intent.monster?.convertToDTO()) { entry in - let entries = [entry ?? .createDefault()] - completion(Timeline(entries: entries, policy: .never)) - } - } - - private func convertDTOToEntry(dto: MonsterDTO?, completion: @escaping (Entry?) -> Void) { - if let dto = dto, let iconUrl = URL(string: dto.iconUrlString) { - self.imageManager.cacheImage(imageUrl: iconUrl) { result in - switch result { - case let .success(icon): - let name = dto.name - let description = dto.description.replacingOccurrences(of: "\\n", with: "\n") - completion(Entry(date: Date(), name: name, description: description, icon: icon)) - case .failure: - completion(nil) - } - } - } else { - completion(nil) - } - } -} diff --git a/UhooiPicBookWidgets/Monster/MonsterEntry.swift b/UhooiPicBookWidgets/Monster/MonsterEntry.swift deleted file mode 100644 index 9646f2a8..00000000 --- a/UhooiPicBookWidgets/Monster/MonsterEntry.swift +++ /dev/null @@ -1,25 +0,0 @@ -// -// MonsterEntry.swift -// UhooiPicBookWidgets -// -// Created by uhooi on 2020/12/14. -// - -import UIKit.UIImage -import WidgetKit - -struct MonsterEntry: TimelineEntry { - let date: Date - let name: String - let description: String - let icon: UIImage - - static func createDefault() -> Self { - .init( - date: Date(), - name: "uhooi", - description: "ゆかいな みどりの せいぶつ。\nわるそうに みえるが むがい。", - icon: UIImage(named: "Uhooi")! // swiftlint:disable:this force_unwrapping - ) - } -} diff --git a/UhooiPicBookWidgets/Monster/MonsterWidget.swift b/UhooiPicBookWidgets/Monster/MonsterWidget.swift deleted file mode 100644 index 20cf1f33..00000000 --- a/UhooiPicBookWidgets/Monster/MonsterWidget.swift +++ /dev/null @@ -1,100 +0,0 @@ -// -// MonsterWidget.swift -// UhooiPicBookWidgets -// -// Created by uhooi on 2020/11/09. -// - -import WidgetKit -import SwiftUI -import FirebaseCore - -private struct MonsterProvider { - typealias Entry = MonsterEntry - - private let monstersRepository: MonstersRepository - private let imageCacheManager: ImageCacheManagerProtocol - - init(monstersRepository: MonstersRepository, imageCacheManager: ImageCacheManagerProtocol) { - self.monstersRepository = monstersRepository - self.imageCacheManager = imageCacheManager - } -} - -struct MonsterWidget: Widget { - var body: some WidgetConfiguration { - StaticConfiguration( - kind: "Monster", - provider: MonsterProvider( - monstersRepository: MonstersFirebaseClient(), - imageCacheManager: ImageCacheManager() - ) - ) { entry in - MonsterEntryView(entry: entry) - } - .configurationDisplayName("Configuration display name") - .description("Description") - .supportedFamilies([.systemSmall, .systemMedium]) - } - - init() { - FirebaseApp.configure() - } -} - -extension MonsterProvider: TimelineProvider { - func placeholder(in context: Context) -> Entry { - .createDefault() - } - - func getSnapshot(in context: Context, completion: @escaping (Entry) -> Void) { - completion(.createDefault()) - } - - func getTimeline(in context: Context, completion: @escaping (Timeline) -> Void) { - var entries: [Entry] = [] - - // swiftlint:disable:next closure_body_length - self.monstersRepository.loadMonsters { result in - switch result { - case let .success(monsters): - let currentDate = Date() - var hourOffset = 0 - for monster in monsters.sorted(by: { $0.order < $1.order }) { - let name = monster.name - let description = monster.description.replacingOccurrences(of: "\\n", with: "\n") - let iconUrlString = monster.iconUrlString - - guard let iconUrl = URL(string: iconUrlString) else { - continue - } - - let group = DispatchGroup() - group.enter() - - self.imageCacheManager.cacheImage(imageUrl: iconUrl) { result in - switch result { - case let .success(icon): - guard let entryDate = Calendar.current.date(byAdding: .hour, value: hourOffset, to: currentDate) else { - fatalError("Fail to unwrap `entryDate`. hourOffset: \(hourOffset), currentDate: \(currentDate)") - } - let entry = Entry(date: entryDate, name: name, description: description, icon: icon) - entries.append(entry) - hourOffset += 1 - case .failure: - break - } - - group.leave() - } - - group.wait() - } - case .failure: - break - } - - completion(Timeline(entries: entries, policy: .atEnd)) - } - } -} diff --git a/ci_scripts/ci_pre_xcodebuild.sh b/ci_scripts/ci_pre_xcodebuild.sh new file mode 100755 index 00000000..dbb0329a --- /dev/null +++ b/ci_scripts/ci_pre_xcodebuild.sh @@ -0,0 +1,5 @@ +#!/bin/bash +cd ${CI_WORKSPACE} +make build-cli-tools +make download-firebase-sdk +make generate-licenses diff --git a/lic-plist.yml b/lic-plist.yml deleted file mode 100644 index 31be436d..00000000 --- a/lic-plist.yml +++ /dev/null @@ -1,8 +0,0 @@ -github: - - owner: firebase - name: firebase-ios-sdk - version: 8.6.0 - -rename: - firebase-ios-sdk: Firebase - diff --git a/project.yml b/project.yml deleted file mode 100644 index 1e9af834..00000000 --- a/project.yml +++ /dev/null @@ -1,310 +0,0 @@ -name: UhooiPicBook - -options: - bundleIdPrefix: com.theuhooi - deploymentTarget: - iOS: 14.0 - developmentLanguage: ja - xcodeVersion: "13.0" - -settings: - base: - MARKETING_VERSION: 1.5.0 - CURRENT_PROJECT_VERSION: 16 - DEVELOPMENT_TEAM: 47E56DYP3N - OTHER_LDFLAGS: $(inherited) $(OTHER_LDFLAGS) -ObjC - configs: - debug: - DEBUG_INFORMATION_FORMAT: "dwarf-with-dsym" - -packages: - Rswift: - url: https://github.com/mac-cain13/R.swift.Library - version: 5.4.0 - Gedatsu: - url: https://github.com/bannzai/Gedatsu - version: 1.2.0 - SwiftPrettyPrint: - url: https://github.com/YusukeHosonuma/SwiftPrettyPrint - version: 1.2.0 - -targets: - UhooiPicBook: - type: application - platform: iOS - sources: - - UhooiPicBook - - Shared - - path: "UhooiPicBook/Generated/MockResults.swift" - optional: true - type: file - - path: "UhooiPicBook/Generated/R.generated.swift" - optional: true - type: file - - path: "Frameworks/Firebase/FirebaseFirestore/Resources/gRPCCertificates-Cpp.bundle" - type: file - settings: - base: - INFOPLIST_FILE: UhooiPicBook/Resources/Info.plist - CODE_SIGN_ENTITLEMENTS: UhooiPicBook/Resources/UhooiPicBook.entitlements - DEVELOPMENT_LANGUAGE: jp - PRODUCT_BUNDLE_IDENTIFIER: ${BUNDLE_IDENTIFIER} - ASSETCATALOG_COMPILER_APPICON_NAME: AppIcon-${ENVIRONMENT} - configs: - debug: - OTHER_SWIFT_FLAGS: $(inherited) -Xfrontend -warn-long-expression-type-checking=500 -Xfrontend -warn-long-function-bodies=500 - dependencies: - - target: UhooiPicBookStickers - embed: true - codeSign: false - buildPhase: - copyFiles: - destination: plugins - - target: UhooiPicBookWidgets - - target: UhooiPicBookWidgetsConfigurableIntent - - package: Rswift - - package: Gedatsu - - package: SwiftPrettyPrint - - framework: "Frameworks/Firebase/FirebaseAnalytics/FirebaseAnalytics.xcframework" - - framework: "Frameworks/Firebase/FirebaseAnalytics/FirebaseCore.xcframework" - - framework: "Frameworks/Firebase/FirebaseAnalytics/FirebaseCoreDiagnostics.xcframework" - - framework: "Frameworks/Firebase/FirebaseAnalytics/FirebaseInstallations.xcframework" - - framework: "Frameworks/Firebase/FirebaseAnalytics/GoogleAppMeasurement.xcframework" - - framework: "Frameworks/Firebase/FirebaseAnalytics/GoogleDataTransport.xcframework" - - framework: "Frameworks/Firebase/FirebaseAnalytics/GoogleUtilities.xcframework" - - framework: "Frameworks/Firebase/FirebaseAnalytics/PromisesObjC.xcframework" - - framework: "Frameworks/Firebase/FirebaseAnalytics/nanopb.xcframework" - - framework: "Frameworks/Firebase/FirebaseAppDistribution/FirebaseAppDistribution.xcframework" - - framework: "Frameworks/Firebase/FirebaseCrashlytics/FirebaseCrashlytics.xcframework" - - framework: "Frameworks/Firebase/FirebaseFirestore/BoringSSL-GRPC.xcframework" - - framework: "Frameworks/Firebase/FirebaseFirestore/FirebaseFirestore.xcframework" - - framework: "Frameworks/Firebase/FirebaseFirestore/abseil.xcframework" - - framework: "Frameworks/Firebase/FirebaseFirestore/gRPC-C++.xcframework" - - framework: "Frameworks/Firebase/FirebaseFirestore/gRPC-Core.xcframework" - - framework: "Frameworks/Firebase/FirebaseFirestore/leveldb-library.xcframework" - - framework: "Frameworks/Firebase/FirebaseMessaging/FirebaseMessaging.xcframework" - - framework: "Frameworks/Firebase/FirebasePerformance/FirebaseABTesting.xcframework" - - framework: "Frameworks/Firebase/FirebasePerformance/FirebasePerformance.xcframework" - - framework: "Frameworks/Firebase/FirebasePerformance/FirebaseRemoteConfig.xcframework" - preBuildScripts: - - path: ./Scripts/XcodeGen/rswift.sh - name: Generate Resources with R.swift - inputFiles: - - $TEMP_DIR/rswift-lastrun - outputFiles: - - $SRCROOT/$TARGET_NAME/Generated/R.generated.swift - - path: ./Scripts/XcodeGen/mockolo.sh - name: Generate Mocks with Mockolo - outputFiles: - - $SRCROOT/$TARGET_NAME/Generated/MockResults.swift - postCompileScripts: - - path: ./Scripts/XcodeGen/swiftlint.sh - name: Run SwiftLint - - path: ./Scripts/XcodeGen/iblinter.sh - name: Run IBLinter - - path: ./Scripts/XcodeGen/spellchecker.sh - name: Run SpellChecker - postBuildScripts: - - script: ./Frameworks/Firebase/FirebaseCrashlytics/run - name: Run Firebase Crashlytics - inputFiles: - - $(SRCROOT)/$(BUILT_PRODUCTS_DIR)/$(INFOPLIST_PATH) - - UhooiPicBookTests: - type: bundle.unit-test - platform: iOS - sources: - - UhooiPicBookTests - settings: - base: - INFOPLIST_FILE: UhooiPicBookTests/Info.plist - dependencies: - - target: UhooiPicBook - - UhooiPicBookUITests: - type: bundle.ui-testing - platform: iOS - sources: - - UhooiPicBookUITests - settings: - base: - INFOPLIST_FILE: UhooiPicBookUITests/Info.plist - dependencies: - - target: UhooiPicBook - - UhooiPicBookStickers: - type: app-extension.messages-sticker-pack - platform: iOS - deploymentTarget: 11.0 - sources: - - UhooiPicBookStickers - settings: - base: - ASSETCATALOG_COMPILER_APPICON_NAME: "iMessage App Icon" - CLANG_ENABLE_OBJC_WEAK: YES - CODE_SIGN_IDENTITY: "iPhone Developer" - CODE_SIGN_STYLE: Automatic - GCC_PREPROCESSOR_DEFINITIONS: - - "DEBUG=1" - - "$(inherited)" - INFOPLIST_FILE: UhooiPicBookStickers/Info.plist - LD_RUNPATH_SEARCH_PATHS: "" - MTL_ENABLE_DEBUG_INFO: INCLUDE_SOURCE - MTL_FAST_MATH: YES - PRODUCT_BUNDLE_IDENTIFIER: ${BUNDLE_IDENTIFIER}.Stickers - PRODUCT_NAME: "UhooiPicBookStickers" - SKIP_INSTALL: YES - - UhooiPicBookWidgets: - type: app-extension - platform: iOS - deploymentTarget: 14.0 - settings: - base: - ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME: AccentColor - ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME: WidgetBackground - CODE_SIGN_IDENTITY: "iPhone Developer" - CODE_SIGN_STYLE: Automatic - GCC_PREPROCESSOR_DEFINITIONS: - - "DEBUG=1" - - "$(inherited)" - INFOPLIST_FILE: UhooiPicBookWidgets/Info.plist - LD_RUNPATH_SEARCH_PATHS: - - "$(inherited)" - - "@executable_path/Frameworks" - - "@executable_path/../../Frameworks" - OTHER_LDFLAGS: $(inherited) $(OTHER_LDFLAGS) -ObjC - PRODUCT_BUNDLE_IDENTIFIER: ${BUNDLE_IDENTIFIER}.Widgets - PRODUCT_NAME: "UhooiPicBookWidgets" - SKIP_INSTALL: YES - sources: - - UhooiPicBookWidgets - - Shared - - path: "Frameworks/Firebase/FirebaseFirestore/Resources/gRPCCertificates-Cpp.bundle" - type: file - dependencies: - - sdk: SwiftUI.framework - - sdk: WidgetKit.framework - - framework: "Frameworks/Firebase/FirebaseAnalytics/FirebaseAnalytics.xcframework" - - framework: "Frameworks/Firebase/FirebaseAnalytics/FirebaseCore.xcframework" - - framework: "Frameworks/Firebase/FirebaseAnalytics/FirebaseCoreDiagnostics.xcframework" - - framework: "Frameworks/Firebase/FirebaseAnalytics/FirebaseInstallations.xcframework" - - framework: "Frameworks/Firebase/FirebaseAnalytics/GoogleAppMeasurement.xcframework" - - framework: "Frameworks/Firebase/FirebaseAnalytics/GoogleDataTransport.xcframework" - - framework: "Frameworks/Firebase/FirebaseAnalytics/GoogleUtilities.xcframework" - - framework: "Frameworks/Firebase/FirebaseAnalytics/PromisesObjC.xcframework" - - framework: "Frameworks/Firebase/FirebaseAnalytics/nanopb.xcframework" - - framework: "Frameworks/Firebase/FirebaseAppDistribution/FirebaseAppDistribution.xcframework" - - framework: "Frameworks/Firebase/FirebaseCrashlytics/FirebaseCrashlytics.xcframework" - - framework: "Frameworks/Firebase/FirebaseFirestore/BoringSSL-GRPC.xcframework" - - framework: "Frameworks/Firebase/FirebaseFirestore/FirebaseFirestore.xcframework" - - framework: "Frameworks/Firebase/FirebaseFirestore/abseil.xcframework" - - framework: "Frameworks/Firebase/FirebaseFirestore/gRPC-C++.xcframework" - - framework: "Frameworks/Firebase/FirebaseFirestore/gRPC-Core.xcframework" - - framework: "Frameworks/Firebase/FirebaseFirestore/leveldb-library.xcframework" - - framework: "Frameworks/Firebase/FirebaseMessaging/FirebaseMessaging.xcframework" - - framework: "Frameworks/Firebase/FirebasePerformance/FirebaseABTesting.xcframework" - - framework: "Frameworks/Firebase/FirebasePerformance/FirebasePerformance.xcframework" - - framework: "Frameworks/Firebase/FirebasePerformance/FirebaseRemoteConfig.xcframework" - postBuildScripts: - - script: ./Frameworks/Firebase/FirebaseCrashlytics/run - name: Run Firebase Crashlytics - inputFiles: - - $(SRCROOT)/$(BUILT_PRODUCTS_DIR)/$(INFOPLIST_PATH) - - UhooiPicBookWidgetsConfigurableIntent: - type: app-extension - platform: iOS - deploymentTarget: 14.0 - settings: - base: - CODE_SIGN_IDENTITY: "iPhone Developer" - CODE_SIGN_STYLE: Automatic - GCC_PREPROCESSOR_DEFINITIONS: - - "DEBUG=1" - - "$(inherited)" - INFOPLIST_FILE: UhooiPicBookWidgetsConfigurableIntent/Info.plist - LD_RUNPATH_SEARCH_PATHS: - - "$(inherited)" - - "@executable_path/Frameworks" - - "@executable_path/../../Frameworks" - OTHER_LDFLAGS: $(inherited) $(OTHER_LDFLAGS) -ObjC - PRODUCT_BUNDLE_IDENTIFIER: ${BUNDLE_IDENTIFIER}.WidgetsConfigurableIntent - PRODUCT_NAME: "UhooiPicBookWidgetsConfigurableIntent" - SKIP_INSTALL: YES - sources: - - UhooiPicBookWidgetsConfigurableIntent - - Shared - - path: "Frameworks/Firebase/FirebaseFirestore/Resources/gRPCCertificates-Cpp.bundle" - type: file - dependencies: - - framework: "Frameworks/Firebase/FirebaseAnalytics/FirebaseAnalytics.xcframework" - - framework: "Frameworks/Firebase/FirebaseAnalytics/FirebaseCore.xcframework" - - framework: "Frameworks/Firebase/FirebaseAnalytics/FirebaseCoreDiagnostics.xcframework" - - framework: "Frameworks/Firebase/FirebaseAnalytics/FirebaseInstallations.xcframework" - - framework: "Frameworks/Firebase/FirebaseAnalytics/GoogleAppMeasurement.xcframework" - - framework: "Frameworks/Firebase/FirebaseAnalytics/GoogleDataTransport.xcframework" - - framework: "Frameworks/Firebase/FirebaseAnalytics/GoogleUtilities.xcframework" - - framework: "Frameworks/Firebase/FirebaseAnalytics/PromisesObjC.xcframework" - - framework: "Frameworks/Firebase/FirebaseAnalytics/nanopb.xcframework" - - framework: "Frameworks/Firebase/FirebaseAppDistribution/FirebaseAppDistribution.xcframework" - - framework: "Frameworks/Firebase/FirebaseFirestore/BoringSSL-GRPC.xcframework" - - framework: "Frameworks/Firebase/FirebaseFirestore/FirebaseFirestore.xcframework" - - framework: "Frameworks/Firebase/FirebaseFirestore/abseil.xcframework" - - framework: "Frameworks/Firebase/FirebaseFirestore/gRPC-C++.xcframework" - - framework: "Frameworks/Firebase/FirebaseFirestore/gRPC-Core.xcframework" - - framework: "Frameworks/Firebase/FirebaseFirestore/leveldb-library.xcframework" - - framework: "Frameworks/Firebase/FirebaseMessaging/FirebaseMessaging.xcframework" - - framework: "Frameworks/Firebase/FirebasePerformance/FirebaseABTesting.xcframework" - - framework: "Frameworks/Firebase/FirebasePerformance/FirebasePerformance.xcframework" - - framework: "Frameworks/Firebase/FirebasePerformance/FirebaseRemoteConfig.xcframework" - -schemes: - UhooiPicBook: - build: - targets: - UhooiPicBook: all - postActions: - - script: rm -rf "${TARGET_BUILD_DIR}/${PRODUCT_NAME}.app/Frameworks/abseil.framework" && - rm -rf "${TARGET_BUILD_DIR}/${PRODUCT_NAME}.app/Frameworks/BoringSSL-GRPC.framework" && - rm -rf "${TARGET_BUILD_DIR}/${PRODUCT_NAME}.app/Frameworks/FirebaseABTesting.framework" && - rm -rf "${TARGET_BUILD_DIR}/${PRODUCT_NAME}.app/Frameworks/FirebaseAnalytics.framework" && - rm -rf "${TARGET_BUILD_DIR}/${PRODUCT_NAME}.app/Frameworks/FirebaseAppDistribution.framework" && - rm -rf "${TARGET_BUILD_DIR}/${PRODUCT_NAME}.app/Frameworks/FirebaseCore.framework" && - rm -rf "${TARGET_BUILD_DIR}/${PRODUCT_NAME}.app/Frameworks/FirebaseCoreDiagnostics.framework" && - rm -rf "${TARGET_BUILD_DIR}/${PRODUCT_NAME}.app/Frameworks/FirebaseCrashlytics.framework" && - rm -rf "${TARGET_BUILD_DIR}/${PRODUCT_NAME}.app/Frameworks/FirebaseFirestore.framework" && - rm -rf "${TARGET_BUILD_DIR}/${PRODUCT_NAME}.app/Frameworks/FirebaseInstallations.framework" && - rm -rf "${TARGET_BUILD_DIR}/${PRODUCT_NAME}.app/Frameworks/FirebaseMessaging.framework" && - rm -rf "${TARGET_BUILD_DIR}/${PRODUCT_NAME}.app/Frameworks/FirebasePerformance.framework" && - rm -rf "${TARGET_BUILD_DIR}/${PRODUCT_NAME}.app/Frameworks/FirebaseRemoteConfig.framework" && - rm -rf "${TARGET_BUILD_DIR}/${PRODUCT_NAME}.app/Frameworks/GoogleAppMeasurement.framework" && - rm -rf "${TARGET_BUILD_DIR}/${PRODUCT_NAME}.app/Frameworks/GoogleDataTransport.framework" && - rm -rf "${TARGET_BUILD_DIR}/${PRODUCT_NAME}.app/Frameworks/GoogleUtilities.framework" && - rm -rf "${TARGET_BUILD_DIR}/${PRODUCT_NAME}.app/Frameworks/gRPC-C++.framework" && - rm -rf "${TARGET_BUILD_DIR}/${PRODUCT_NAME}.app/Frameworks/gRPC-Core.framework" && - rm -rf "${TARGET_BUILD_DIR}/${PRODUCT_NAME}.app/Frameworks/leveldb-library.framework" && - rm -rf "${TARGET_BUILD_DIR}/${PRODUCT_NAME}.app/Frameworks/nanopb.framework" && - rm -rf "${TARGET_BUILD_DIR}/${PRODUCT_NAME}.app/Frameworks/PromisesObjC.framework" - name: Remove Firebase frameworks - settingsTarget: UhooiPicBook - run: - config: Debug - test: - config: Debug - gatherCoverageData: true - coverageTargets: - - UhooiPicBook - targets: - - name: UhooiPicBookTests - parallelizable: true - randomExecutionOrder: true - - name: UhooiPicBookUITests - parallelizable: true - randomExecutionOrder: true - profile: - config: Release - analyze: - config: Debug - archive: - config: Release