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 @@
-
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用キャラクター図鑑です。
+
+
+
+## 目次
+
+- [スクリーンショット](#スクリーンショット)
+- [開発](#開発)
+- [貢献](#貢献)
+- [スタッツ](#スタッツ)
+
+## スクリーンショット
+
+スクリーンショット
+
+### ライト
+
+|モンスター一覧|モンスター詳細|画像ポップアップ|
+|:--:|:--:|:--:|
+||||
+
+|モンスター一覧で開いたメニュー|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)
+
+
+## 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