Release v1.4.1 (#427)

* feat: use bundler to install Ruby Gems instead of installing them system-wide using root

* chore: install bundler without sudo

* Improve tab bar icon vertical alignment

* feat: update tabBar UI

* chore: update version to 1.4.1 (122)

* chore: fix accessibility large content label text missing issue

* chore: update version to 1.4.1 (123)

* chore: update navigation bar button item assets

* fix: compose tabBar button layout raise crash on iPad issue

* chore: update version to 1.4.1 (124)

* chore: suppress warnings

* feat: add navigation pan pop gesture. resolve #407 #419

* chore: update version to 1.4.1 (125)

* fix: profile bio line break get trimmed issue. resolve #311

* chore: update version to 1.4.1 (126)

Co-authored-by: Marcus Kida <marcus.kida@bearologics.com>
Co-authored-by: vollkorntomate <thomas.voelkl@outlook.de>
This commit is contained in:
CMK 2022-05-09 11:28:35 +08:00 committed by GitHub
parent ed30085f87
commit e4c38c70e2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
68 changed files with 1779 additions and 202 deletions

View File

@ -1,9 +1,13 @@
#!/bin/bash
sudo gem install cocoapods-keys
# Install Ruby Bundler
gem install bundler:2.3.11
# Install Ruby Gems
bundle install
# stub keys. DO NOT use in production
pod keys set notification_endpoint "<endpoint>"
pod keys set notification_endpoint_debug "<endpoint>"
bundle exec pod keys set notification_endpoint "<endpoint>"
bundle exec pod keys set notification_endpoint_debug "<endpoint>"
pod install
bundle exec pod install

View File

@ -15,8 +15,8 @@
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>1.4.0</string>
<string>1.4.1</string>
<key>CFBundleVersion</key>
<string>121</string>
<string>126</string>
</dict>
</plist>

View File

@ -12,12 +12,13 @@ Intell the latest version of Xcode from the App Store or Apple Developer Downloa
This guide may not suit your machine and actually setup procedure may change in the future. Please file the issue or Pull Request if there are any problems.
## CocoaPods
The app use [CocoaPods]() and [CocoaPods-Keys](https://github.com/orta/cocoapods-keys). The M1 Mac needs virtual ruby env to workaround compatibility issues.
The app use [CocoaPods]() and [CocoaPods-Keys](https://github.com/orta/cocoapods-keys). Ruby Gems are managed through Bundler. The M1 Mac needs virtual ruby env to workaround compatibility issues.
#### Intel Mac
```zsh
sudo gem install cocoapods cocoapods-keys
gem install bundler
bundle install
```
#### M1 Mac
@ -40,18 +41,19 @@ rbenv global 3.0.3
ruby --version
# > ruby 3.0.3p157 (2021-11-24 revision 3fb7d2cadc) [arm64-darwin21]
sudo gem install cocoapods cocoapods-keys
gem install bundler
bundle install
```
## Bootstrap
```zsh
# make a clean build
sudo gem install cocoapods-clean
pod clean
bundle install
bundle exec pod clean
# make install
pod install --repo-update
bundle exec pod install --repo-update
# open workspace
open Mastodon.xcworkspace

6
Gemfile Normal file
View File

@ -0,0 +1,6 @@
source "https://rubygems.org"
gem "cocoapods"
gem "cocoapods-clean"
gem "cocoapods-keys"

109
Gemfile.lock Normal file
View File

@ -0,0 +1,109 @@
GEM
remote: https://rubygems.org/
specs:
CFPropertyList (3.0.5)
rexml
RubyInline (3.12.5)
ZenTest (~> 4.3)
ZenTest (4.12.1)
activesupport (6.1.5.1)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 1.6, < 2)
minitest (>= 5.1)
tzinfo (~> 2.0)
zeitwerk (~> 2.3)
addressable (2.8.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.1.0)
cocoapods (1.11.3)
addressable (~> 2.8)
claide (>= 1.0.2, < 2.0)
cocoapods-core (= 1.11.3)
cocoapods-deintegrate (>= 1.0.3, < 2.0)
cocoapods-downloader (>= 1.4.0, < 2.0)
cocoapods-plugins (>= 1.0.0, < 2.0)
cocoapods-search (>= 1.0.0, < 2.0)
cocoapods-trunk (>= 1.4.0, < 2.0)
cocoapods-try (>= 1.1.0, < 2.0)
colored2 (~> 3.1)
escape (~> 0.0.4)
fourflusher (>= 2.3.0, < 3.0)
gh_inspector (~> 1.0)
molinillo (~> 0.8.0)
nap (~> 1.0)
ruby-macho (>= 1.0, < 3.0)
xcodeproj (>= 1.21.0, < 2.0)
cocoapods-clean (0.0.1)
cocoapods-core (1.11.3)
activesupport (>= 5.0, < 7)
addressable (~> 2.8)
algoliasearch (~> 1.0)
concurrent-ruby (~> 1.1)
fuzzy_match (~> 2.0.4)
nap (~> 1.0)
netrc (~> 0.11)
public_suffix (~> 4.0)
typhoeus (~> 1.0)
cocoapods-deintegrate (1.0.5)
cocoapods-downloader (1.6.3)
cocoapods-keys (2.2.1)
dotenv
osx_keychain
cocoapods-plugins (1.0.0)
nap
cocoapods-search (1.0.1)
cocoapods-trunk (1.6.0)
nap (>= 0.8, < 2.0)
netrc (~> 0.11)
cocoapods-try (1.2.0)
colored2 (3.1.2)
concurrent-ruby (1.1.10)
dotenv (2.7.6)
escape (0.0.4)
ethon (0.15.0)
ffi (>= 1.15.0)
ffi (1.15.5)
fourflusher (2.3.1)
fuzzy_match (2.0.4)
gh_inspector (1.1.3)
httpclient (2.8.3)
i18n (1.10.0)
concurrent-ruby (~> 1.0)
json (2.6.1)
minitest (5.15.0)
molinillo (0.8.0)
nanaimo (0.3.0)
nap (1.1.0)
netrc (0.11.0)
osx_keychain (1.0.2)
RubyInline (~> 3)
public_suffix (4.0.7)
rexml (3.2.5)
ruby-macho (2.5.1)
typhoeus (1.4.0)
ethon (>= 0.9.0)
tzinfo (2.0.4)
concurrent-ruby (~> 1.0)
xcodeproj (1.21.0)
CFPropertyList (>= 2.3.3, < 4.0)
atomos (~> 0.1.3)
claide (>= 1.0.2, < 2.0)
colored2 (~> 3.1)
nanaimo (~> 0.3.0)
rexml (~> 3.2.4)
zeitwerk (2.5.4)
PLATFORMS
ruby
DEPENDENCIES
cocoapods
cocoapods-clean
cocoapods-keys
BUNDLED WITH
2.3.11

View File

@ -537,7 +537,6 @@
DBCBED1726132DB500B49291 /* UserTimelineViewModel+Diffable.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBCBED1626132DB500B49291 /* UserTimelineViewModel+Diffable.swift */; };
DBCBED1D26132E1A00B49291 /* StatusFetchedResultsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBCBED1C26132E1A00B49291 /* StatusFetchedResultsController.swift */; };
DBCC3B30261440A50045B23D /* UITabBarController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBCC3B2F261440A50045B23D /* UITabBarController.swift */; };
DBCC3B36261440BA0045B23D /* UINavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBCC3B35261440BA0045B23D /* UINavigationController.swift */; };
DBCC3B8F26148F7B0045B23D /* CachedProfileViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBCC3B8E26148F7B0045B23D /* CachedProfileViewModel.swift */; };
DBCC3B9526157E6E0045B23D /* APIService+Relationship.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBCC3B9426157E6E0045B23D /* APIService+Relationship.swift */; };
DBCCC71E25F73297007E1AB6 /* APIService+Reblog.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBCCC71D25F73297007E1AB6 /* APIService+Reblog.swift */; };
@ -1302,7 +1301,6 @@
DBCBED1626132DB500B49291 /* UserTimelineViewModel+Diffable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UserTimelineViewModel+Diffable.swift"; sourceTree = "<group>"; };
DBCBED1C26132E1A00B49291 /* StatusFetchedResultsController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusFetchedResultsController.swift; sourceTree = "<group>"; };
DBCC3B2F261440A50045B23D /* UITabBarController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UITabBarController.swift; sourceTree = "<group>"; };
DBCC3B35261440BA0045B23D /* UINavigationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UINavigationController.swift; sourceTree = "<group>"; };
DBCC3B8E26148F7B0045B23D /* CachedProfileViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CachedProfileViewModel.swift; sourceTree = "<group>"; };
DBCC3B9426157E6E0045B23D /* APIService+Relationship.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "APIService+Relationship.swift"; sourceTree = "<group>"; };
DBCCC71D25F73297007E1AB6 /* APIService+Reblog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "APIService+Reblog.swift"; sourceTree = "<group>"; };
@ -2792,7 +2790,6 @@
2D84350425FF858100EECE90 /* UIScrollView.swift */,
DB9E0D6E25EE008500CFDD76 /* UIInterpolatingMotionEffect.swift */,
DBCC3B2F261440A50045B23D /* UITabBarController.swift */,
DBCC3B35261440BA0045B23D /* UINavigationController.swift */,
DB73BF4827140BA300781945 /* UICollectionViewDiffableDataSource.swift */,
DB73BF4A27140C0800781945 /* UITableViewDiffableDataSource.swift */,
);
@ -4029,7 +4026,6 @@
DB9D7C21269824B80054B3DF /* APIService+Filter.swift in Sources */,
2D38F1E525CD46C100561493 /* HomeTimelineViewModel.swift in Sources */,
DB0FCB842796B2A2006C02E2 /* FavoriteViewController+DataSourceProvider.swift in Sources */,
DBCC3B36261440BA0045B23D /* UINavigationController.swift in Sources */,
DB0FCB68279507EF006C02E2 /* DataSourceFacade+Meta.swift in Sources */,
DB63F75C279956D000455B82 /* Persistence+Tag.swift in Sources */,
2D84350525FF858100EECE90 /* UIScrollView.swift in Sources */,
@ -4711,7 +4707,7 @@
CODE_SIGN_ENTITLEMENTS = Mastodon/Mastodon.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 121;
CURRENT_PROJECT_VERSION = 126;
DEVELOPMENT_ASSET_PATHS = "Mastodon/Resources/Preview\\ Assets.xcassets";
DEVELOPMENT_TEAM = 5Z4GVSS33P;
INFOPLIST_FILE = Mastodon/Info.plist;
@ -4741,7 +4737,7 @@
CODE_SIGN_ENTITLEMENTS = Mastodon/Mastodon.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 121;
CURRENT_PROJECT_VERSION = 126;
DEVELOPMENT_ASSET_PATHS = "Mastodon/Resources/Preview\\ Assets.xcassets";
DEVELOPMENT_TEAM = 5Z4GVSS33P;
INFOPLIST_FILE = Mastodon/Info.plist;
@ -4849,11 +4845,11 @@
APPLICATION_EXTENSION_API_ONLY = YES;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 121;
CURRENT_PROJECT_VERSION = 126;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = 5Z4GVSS33P;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 121;
DYLIB_CURRENT_VERSION = 126;
DYLIB_INSTALL_NAME_BASE = "@rpath";
INFOPLIST_FILE = AppShared/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
@ -4880,11 +4876,11 @@
APPLICATION_EXTENSION_API_ONLY = YES;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 121;
CURRENT_PROJECT_VERSION = 126;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = 5Z4GVSS33P;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 121;
DYLIB_CURRENT_VERSION = 126;
DYLIB_INSTALL_NAME_BASE = "@rpath";
INFOPLIST_FILE = AppShared/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
@ -4908,7 +4904,7 @@
buildSettings = {
CODE_SIGN_ENTITLEMENTS = MastodonIntent/MastodonIntent.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 121;
CURRENT_PROJECT_VERSION = 126;
DEVELOPMENT_TEAM = 5Z4GVSS33P;
INFOPLIST_FILE = MastodonIntent/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
@ -4932,7 +4928,7 @@
buildSettings = {
CODE_SIGN_ENTITLEMENTS = MastodonIntent/MastodonIntent.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 121;
CURRENT_PROJECT_VERSION = 126;
DEVELOPMENT_TEAM = 5Z4GVSS33P;
INFOPLIST_FILE = MastodonIntent/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
@ -4956,7 +4952,7 @@
buildSettings = {
CODE_SIGN_ENTITLEMENTS = ShareActionExtension/ShareActionExtension.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 121;
CURRENT_PROJECT_VERSION = 126;
DEVELOPMENT_TEAM = 5Z4GVSS33P;
INFOPLIST_FILE = ShareActionExtension/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
@ -4980,7 +4976,7 @@
buildSettings = {
CODE_SIGN_ENTITLEMENTS = ShareActionExtension/ShareActionExtension.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 121;
CURRENT_PROJECT_VERSION = 126;
DEVELOPMENT_TEAM = 5Z4GVSS33P;
INFOPLIST_FILE = ShareActionExtension/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
@ -5067,7 +5063,7 @@
CODE_SIGN_ENTITLEMENTS = Mastodon/Mastodon.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 121;
CURRENT_PROJECT_VERSION = 126;
DEVELOPMENT_ASSET_PATHS = "Mastodon/Resources/Preview\\ Assets.xcassets";
DEVELOPMENT_TEAM = 5Z4GVSS33P;
INFOPLIST_FILE = Mastodon/Info.plist;
@ -5134,11 +5130,11 @@
APPLICATION_EXTENSION_API_ONLY = YES;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 121;
CURRENT_PROJECT_VERSION = 126;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = 5Z4GVSS33P;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 121;
DYLIB_CURRENT_VERSION = 126;
DYLIB_INSTALL_NAME_BASE = "@rpath";
INFOPLIST_FILE = AppShared/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
@ -5162,7 +5158,7 @@
buildSettings = {
CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 121;
CURRENT_PROJECT_VERSION = 126;
DEVELOPMENT_TEAM = 5Z4GVSS33P;
INFOPLIST_FILE = NotificationService/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
@ -5185,7 +5181,7 @@
buildSettings = {
CODE_SIGN_ENTITLEMENTS = ShareActionExtension/ShareActionExtension.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 121;
CURRENT_PROJECT_VERSION = 126;
DEVELOPMENT_TEAM = 5Z4GVSS33P;
INFOPLIST_FILE = ShareActionExtension/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
@ -5209,7 +5205,7 @@
buildSettings = {
CODE_SIGN_ENTITLEMENTS = MastodonIntent/MastodonIntent.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 121;
CURRENT_PROJECT_VERSION = 126;
DEVELOPMENT_TEAM = 5Z4GVSS33P;
INFOPLIST_FILE = MastodonIntent/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
@ -5233,7 +5229,7 @@
buildSettings = {
CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 121;
CURRENT_PROJECT_VERSION = 126;
DEVELOPMENT_TEAM = 5Z4GVSS33P;
INFOPLIST_FILE = NotificationService/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
@ -5256,7 +5252,7 @@
buildSettings = {
CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 121;
CURRENT_PROJECT_VERSION = 126;
DEVELOPMENT_TEAM = 5Z4GVSS33P;
INFOPLIST_FILE = NotificationService/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (

View File

@ -129,7 +129,7 @@
<key>ShareActionExtension.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>22</integer>
<integer>26</integer>
</dict>
</dict>
<key>SuppressBuildableAutocreation</key>

View File

@ -309,7 +309,7 @@ extension SceneCoordinator {
if scene.isOnboarding {
return OnboardingNavigationController(rootViewController: viewController)
} else {
return UINavigationController(rootViewController: viewController)
return AdaptiveStatusBarStyleNavigationController(rootViewController: viewController)
}
}()
modalNavigationController.modalPresentationCapturesStatusBarAppearance = true
@ -368,10 +368,10 @@ extension SceneCoordinator {
splitViewController?.contentSplitViewController.currentSupplementaryTab = tab
splitViewController?.compactMainTabBarViewController.selectedIndex = tab.rawValue
splitViewController?.compactMainTabBarViewController.currentTab.value = tab
splitViewController?.compactMainTabBarViewController.currentTab = tab
tabBarController.selectedIndex = tab.rawValue
tabBarController.currentTab.value = tab
tabBarController.currentTab = tab
}
}

View File

@ -29,7 +29,7 @@ extension PickServerSection {
weak dependency,
weak pickServerCellDelegate
] tableView, indexPath, item -> UITableViewCell? in
guard let dependency = dependency else { return nil }
guard let _ = dependency else { return nil }
switch item {
case .header:
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: OnboardingHeadlineTableViewCell.self), for: indexPath) as! OnboardingHeadlineTableViewCell

View File

@ -51,7 +51,7 @@ extension SettingsSection {
}
cell.delegate = settingsAppearanceTableViewCellDelegate
return cell
case .appearancePreference(let record, let appearanceType):
case .appearancePreference(let record, _):
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: SettingsToggleTableViewCell.self), for: indexPath) as! SettingsToggleTableViewCell
cell.delegate = settingsToggleCellDelegate
managedObjectContext.performAndWait {

View File

@ -7,13 +7,12 @@
import MastodonSDK
extension Mastodon.Entity.Tag: Hashable {
public func hash(into hasher: inout Hasher) {
hasher.combine(name)
}
public static func == (lhs: Mastodon.Entity.Tag, rhs: Mastodon.Entity.Tag) -> Bool {
return lhs.name == rhs.name
}
}
//extension Mastodon.Entity.Tag: Hashable {
// public func hash(into hasher: inout Hasher) {
// hasher.combine(name)
// }
//
// public static func == (lhs: Mastodon.Entity.Tag, rhs: Mastodon.Entity.Tag) -> Bool {
// return lhs.name == rhs.name
// }
//}

View File

@ -1,16 +0,0 @@
//
// UINavigationController.swift
// Mastodon
//
// Created by MainasuK Cirno on 2021-3-31.
//
import UIKit
// This not works!
// SeeAlso: `AdaptiveStatusBarStyleNavigationController`
extension UINavigationController {
open override var childForStatusBarStyle: UIViewController? {
return visibleViewController
}
}

View File

@ -30,7 +30,7 @@
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>1.4.0</string>
<string>1.4.1</string>
<key>CFBundleURLTypes</key>
<array>
<dict>
@ -43,7 +43,7 @@
</dict>
</array>
<key>CFBundleVersion</key>
<string>121</string>
<string>126</string>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>LSApplicationQueriesSchemes</key>

View File

@ -99,7 +99,7 @@ extension DataSourceFacade {
try await managedObjectContext.performChanges {
guard let authenticationBox = _authenticationBox else { return }
guard let me = authenticationBox.authenticationRecord.object(in: managedObjectContext)?.user else { return }
guard let _ = authenticationBox.authenticationRecord.object(in: managedObjectContext)?.user else { return }
let request = SearchHistory.sortedFetchRequest
request.predicate = SearchHistory.predicate(
domain: authenticationBox.domain,

View File

@ -486,7 +486,7 @@ extension NotificationTableViewCellDelegate where Self: DataSourceProvider {
provider: self,
user: user
)
case .notification(let notification):
case .notification:
assertionFailure("TODO")
default:
assertionFailure("TODO")

View File

@ -494,7 +494,7 @@ extension StatusTableViewCellDelegate where Self: DataSourceProvider {
provider: self,
user: user
)
case .notification(let notification):
case .notification:
assertionFailure("TODO")
default:
assertionFailure("TODO")

View File

@ -138,7 +138,7 @@ extension TableViewControllerNavigateableCore where Self: DataSourceProvider {
target: .status,
status: record
)
case .notification(let record):
case .notification:
assertionFailure()
default:
assertionFailure()

View File

@ -93,7 +93,7 @@ extension UITableViewDelegate where Self: DataSourceProvider & MediaPreviewableV
guard let image = mediaView.thumbnail(),
let assetURLString = mediaView.configuration?.assetURL,
let assetURL = URL(string: assetURLString),
let resourceType = mediaView.configuration?.resourceType
let _ = mediaView.configuration?.resourceType
else {
// not provide preview unless thumbnail ready
return nil

View File

@ -118,7 +118,7 @@ extension AccountListViewController {
// the presentingViewController may deinit.
// Hold it and check the window to prevent PanModel crash
guard let presentingViewController = presentingViewController else { return }
guard let _ = presentingViewController else { return }
guard self.view.window != nil else { return }
self.hasLoaded = true

View File

@ -77,7 +77,7 @@ extension AutoCompleteViewModel.State {
override func didEnter(from previousState: GKState?) {
super.didEnter(from: previousState)
guard let viewModel = viewModel, let stateMachine = stateMachine else { return }
guard let viewModel = viewModel, let _ = stateMachine else { return }
let searchText = viewModel.inputText.value
let searchType = AutoCompleteViewModel.SearchType(inputText: searchText) ?? .default

View File

@ -68,7 +68,7 @@ extension DiscoveryNewsViewModel.State {
override func didEnter(from previousState: GKState?) {
super.didEnter(from: previousState)
guard let viewModel = viewModel, let stateMachine = stateMachine else { return }
guard let _ = viewModel, let stateMachine = stateMachine else { return }
stateMachine.enter(Loading.self)
}

View File

@ -28,7 +28,7 @@ final class HashtagTimelineViewController: UIViewController, NeedsDependency, Me
let composeBarButtonItem: UIBarButtonItem = {
let barButtonItem = UIBarButtonItem()
barButtonItem.image = UIImage(systemName: "square.and.pencil")?.withRenderingMode(.alwaysTemplate)
barButtonItem.image = Asset.ObjectsAndTools.squareAndPencil.image.withRenderingMode(.alwaysTemplate)
return barButtonItem
}()

View File

@ -186,7 +186,7 @@ extension HomeTimelineViewController {
}
func match(item: StatusItem) -> Bool {
let authenticationBox = AppContext.shared.authenticationService.activeMastodonAuthenticationBox.value
// let authenticationBox = AppContext.shared.authenticationService.activeMastodonAuthenticationBox.value
switch item {
case .feed(let record):
guard let feed = record.object(in: AppContext.shared.managedObjectContext) else { return false }

View File

@ -51,19 +51,11 @@ final class HomeTimelineViewController: UIViewController, NeedsDependency, Media
let settingBarButtonItem: UIBarButtonItem = {
let barButtonItem = UIBarButtonItem()
barButtonItem.tintColor = ThemeService.tintColor
barButtonItem.image = UIImage(systemName: "gear")?.withRenderingMode(.alwaysTemplate)
barButtonItem.image = Asset.ObjectsAndTools.gear.image.withRenderingMode(.alwaysTemplate)
barButtonItem.accessibilityLabel = L10n.Common.Controls.Actions.settings
return barButtonItem
}()
let composeBarButtonItem: UIBarButtonItem = {
let barButtonItem = UIBarButtonItem()
barButtonItem.tintColor = ThemeService.tintColor
barButtonItem.image = UIImage(systemName: "square.and.pencil")?.withRenderingMode(.alwaysTemplate)
barButtonItem.accessibilityLabel = L10n.Common.Controls.Actions.compose
return barButtonItem
}()
let tableView: UITableView = {
let tableView = ControlContainableTableView()
tableView.register(StatusTableViewCell.self, forCellReuseIdentifier: String(describing: StatusTableViewCell.self))
@ -109,14 +101,14 @@ extension HomeTimelineViewController {
guard let self = self else { return }
#if DEBUG
// display debug menu
self.navigationItem.leftBarButtonItem = {
self.navigationItem.rightBarButtonItem = {
let barButtonItem = UIBarButtonItem()
barButtonItem.image = UIImage(systemName: "ellipsis.circle")
barButtonItem.menu = self.debugMenu
return barButtonItem
}()
#else
self.navigationItem.leftBarButtonItem = displaySettingBarButtonItem ? self.settingBarButtonItem : nil
self.navigationItem.rightBarButtonItem = displaySettingBarButtonItem ? self.settingBarButtonItem : nil
#endif
}
.store(in: &disposeBag)
@ -133,16 +125,6 @@ extension HomeTimelineViewController {
titleView.button.menu = self.debugMenu
#endif
viewModel.$displayComposeBarButtonItem
.receive(on: DispatchQueue.main)
.sink { [weak self] displayComposeBarButtonItem in
guard let self = self else { return }
self.navigationItem.rightBarButtonItem = displayComposeBarButtonItem ? self.composeBarButtonItem : nil
}
.store(in: &disposeBag)
composeBarButtonItem.target = self
composeBarButtonItem.action = #selector(HomeTimelineViewController.composeBarButtonItemPressed(_:))
navigationItem.titleView = titleView
titleView.delegate = self
@ -411,18 +393,7 @@ extension HomeTimelineViewController {
let settingsViewModel = SettingsViewModel(context: context, setting: setting)
coordinator.present(scene: .settings(viewModel: settingsViewModel), from: self, transition: .modal(animated: true, completion: nil))
}
@objc private func composeBarButtonItemPressed(_ sender: UIBarButtonItem) {
os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s", ((#file as NSString).lastPathComponent), #line, #function)
guard let authenticationBox = context.authenticationService.activeMastodonAuthenticationBox.value else { return }
let composeViewModel = ComposeViewModel(
context: context,
composeKind: .post,
authenticationBox: authenticationBox
)
coordinator.present(scene: .compose(viewModel: composeViewModel), from: self, transition: .modal(animated: true, completion: nil))
}
@objc private func refreshControlValueChanged(_ sender: UIRefreshControl) {
guard viewModel.loadLatestStateMachine.enter(HomeTimelineViewModel.LoadLatestState.Loading.self) else {
sender.endRefreshing()

View File

@ -33,7 +33,6 @@ final class HomeTimelineViewModel: NSObject {
@Published var lastAutomaticFetchTimestamp: Date? = nil
@Published var scrollPositionRecord: ScrollPositionRecord? = nil
@Published var displaySettingBarButtonItem = true
@Published var displayComposeBarButtonItem = true
weak var tableView: UITableView?
weak var timelineMiddleLoaderTableViewCellDelegate: TimelineMiddleLoaderTableViewCellDelegate?

View File

@ -90,7 +90,10 @@ extension ProfileHeaderViewModel {
extension ProfileHeaderViewModel {
static func normalize(note: String?) -> String? {
guard let note = note?.trimmingCharacters(in: .whitespacesAndNewlines),!note.isEmpty else {
let _note = note?.replacingOccurrences(of: "<br>|<br />", with: "\u{2028}", options: .regularExpression, range: nil)
.replacingOccurrences(of: "</p>", with: "</p>\u{2029}", range: nil)
.trimmingCharacters(in: .whitespacesAndNewlines)
guard let note = _note, !note.isEmpty else {
return nil
}

View File

@ -42,19 +42,34 @@ final class ProfileViewController: UIViewController, NeedsDependency, MediaPrevi
}()
private(set) lazy var settingBarButtonItem: UIBarButtonItem = {
let barButtonItem = UIBarButtonItem(image: UIImage(systemName: "gear"), style: .plain, target: self, action: #selector(ProfileViewController.settingBarButtonItemPressed(_:)))
let barButtonItem = UIBarButtonItem(
image: Asset.ObjectsAndTools.gear.image.withRenderingMode(.alwaysTemplate),
style: .plain,
target: self,
action: #selector(ProfileViewController.settingBarButtonItemPressed(_:))
)
barButtonItem.tintColor = .white
return barButtonItem
}()
private(set) lazy var shareBarButtonItem: UIBarButtonItem = {
let barButtonItem = UIBarButtonItem(image: UIImage(systemName: "square.and.arrow.up"), style: .plain, target: self, action: #selector(ProfileViewController.shareBarButtonItemPressed(_:)))
let barButtonItem = UIBarButtonItem(
image: Asset.Arrow.squareAndArrowUp.image.withRenderingMode(.alwaysTemplate),
style: .plain,
target: self,
action: #selector(ProfileViewController.shareBarButtonItemPressed(_:))
)
barButtonItem.tintColor = .white
return barButtonItem
}()
private(set) lazy var favoriteBarButtonItem: UIBarButtonItem = {
let barButtonItem = UIBarButtonItem(image: UIImage(systemName: "star"), style: .plain, target: self, action: #selector(ProfileViewController.favoriteBarButtonItemPressed(_:)))
let barButtonItem = UIBarButtonItem(
image: Asset.ObjectsAndTools.star.image.withRenderingMode(.alwaysTemplate),
style: .plain,
target: self,
action: #selector(ProfileViewController.favoriteBarButtonItemPressed(_:))
)
barButtonItem.tintColor = .white
return barButtonItem
}()
@ -619,7 +634,7 @@ extension ProfileViewController {
return nil
}
let name = user.displayNameWithFallback
let record = ManagedObjectRecord<MastodonUser>(objectID: user.objectID)
let _ = ManagedObjectRecord<MastodonUser>(objectID: user.objectID)
let menu = MastodonMenu.setupMenu(
actions: [
.muteUser(.init(name: name, isMuting: self.viewModel.isMuting.value)),
@ -634,7 +649,7 @@ extension ProfileViewController {
.sink { [weak self] completion in
guard let self = self else { return }
switch completion {
case .failure(let error):
case .failure:
self.moreMenuBarButtonItem.menu = nil
case .finished:
break
@ -938,6 +953,7 @@ extension ProfileViewController: ProfileHeaderViewDelegate {
viewModel.isUpdating.value = true
Task {
do {
// TODO: handle error
_ = try await viewModel.updateProfileInfo(
headerProfileInfo: profileHeaderViewModel.editProfileInfo,
aboutProfileInfo: profileAboutViewModel.editProfileInfo

View File

@ -38,7 +38,6 @@ final class ContentSplitViewController: UIViewController, NeedsDependency {
private(set) lazy var mainTabBarController: MainTabBarController = {
let mainTabBarController = MainTabBarController(context: context, coordinator: coordinator)
if let homeTimelineViewController = mainTabBarController.viewController(of: HomeTimelineViewController.self) {
homeTimelineViewController.viewModel.displayComposeBarButtonItem = false
homeTimelineViewController.viewModel.displaySettingBarButtonItem = false
}
return mainTabBarController
@ -83,7 +82,8 @@ extension ContentSplitViewController {
.sink(receiveValue: { [weak self] tab in
guard let self = self else { return }
self.mainTabBarController.selectedIndex = tab.rawValue
self.mainTabBarController.currentTab.value = tab
self.mainTabBarController.currentTab = tab
self.sidebarViewController.viewModel.currentTab = tab
})
.store(in: &disposeBag)
}

View File

@ -22,14 +22,29 @@ class MainTabBarController: UITabBarController {
weak var context: AppContext!
weak var coordinator: SceneCoordinator!
let composeButttonShadowBackgroundContainer = ShadowBackgroundContainer()
let composeButton: UIButton = {
let button = UIButton()
button.setImage(Asset.ObjectsAndTools.squareAndPencil.image.withRenderingMode(.alwaysTemplate), for: .normal)
button.setBackgroundImage(UIImage.placeholder(color: Asset.Colors.Label.primary.color), for: .normal)
button.setBackgroundImage(UIImage.placeholder(color: Asset.Colors.Label.primary.color.withAlphaComponent(0.8)), for: .highlighted)
button.tintColor = Asset.Colors.Label.primaryReverse.color
button.contentEdgeInsets = UIEdgeInsets(top: 6, left: 12, bottom: 6, right: 12)
button.layer.masksToBounds = true
button.layer.cornerCurve = .continuous
button.layer.cornerRadius = 8
return button
}()
static let avatarButtonSize = CGSize(width: 25, height: 25)
let avatarButton = CircleAvatarButton()
var currentTab = CurrentValueSubject<Tab, Never>(.home)
@Published var currentTab: Tab = .home
enum Tab: Int, CaseIterable {
case home
case search
case compose
case notification
case me
@ -41,6 +56,7 @@ class MainTabBarController: UITabBarController {
switch self {
case .home: return L10n.Common.Controls.Tabs.home
case .search: return L10n.Common.Controls.Tabs.search
case .compose: return L10n.Common.Controls.Actions.compose
case .notification: return L10n.Common.Controls.Tabs.notification
case .me: return L10n.Common.Controls.Tabs.profile
}
@ -48,28 +64,41 @@ class MainTabBarController: UITabBarController {
var image: UIImage {
switch self {
case .home: return UIImage(systemName: "house.fill")!
case .search: return UIImage(systemName: "magnifyingglass")!
case .notification: return UIImage(systemName: "bell.fill")!
case .home: return Asset.ObjectsAndTools.house.image.withRenderingMode(.alwaysTemplate)
case .search: return Asset.ObjectsAndTools.magnifyingglass.image.withRenderingMode(.alwaysTemplate)
case .compose: return Asset.ObjectsAndTools.squareAndPencil.image.withRenderingMode(.alwaysTemplate)
case .notification: return Asset.ObjectsAndTools.bell.image.withRenderingMode(.alwaysTemplate)
case .me: return UIImage(systemName: "person")!
}
}
var selectedImage: UIImage {
switch self {
case .home: return Asset.ObjectsAndTools.houseFill.image.withRenderingMode(.alwaysTemplate)
case .search: return Asset.ObjectsAndTools.magnifyingglassFill.image.withRenderingMode(.alwaysTemplate)
case .compose: return Asset.ObjectsAndTools.squareAndPencil.image.withRenderingMode(.alwaysTemplate)
case .notification: return Asset.ObjectsAndTools.bellFill.image.withRenderingMode(.alwaysTemplate)
case .me: return UIImage(systemName: "person.fill")!
}
}
var largeImage: UIImage {
switch self {
case .home: return UIImage(systemName: "house.fill", withConfiguration: UIImage.SymbolConfiguration(pointSize: 80))!
case .search: return UIImage(systemName: "magnifyingglass", withConfiguration: UIImage.SymbolConfiguration(pointSize: 80))!
case .notification: return UIImage(systemName: "bell.fill", withConfiguration: UIImage.SymbolConfiguration(pointSize: 80))!
case .me: return UIImage(systemName: "person.fill", withConfiguration: UIImage.SymbolConfiguration(pointSize: 80))!
case .home: return Asset.ObjectsAndTools.house.image.withRenderingMode(.alwaysTemplate).resized(size: CGSize(width: 80, height: 80))
case .search: return Asset.ObjectsAndTools.magnifyingglass.image.withRenderingMode(.alwaysTemplate).resized(size: CGSize(width: 80, height: 80))
case .compose: return Asset.ObjectsAndTools.squareAndPencil.image.withRenderingMode(.alwaysTemplate).resized(size: CGSize(width: 80, height: 80))
case .notification: return Asset.ObjectsAndTools.bell.image.withRenderingMode(.alwaysTemplate).resized(size: CGSize(width: 80, height: 80))
case .me: return UIImage(systemName: "person", withConfiguration: UIImage.SymbolConfiguration(pointSize: 80))!
}
}
var sidebarImage: UIImage {
switch self {
case .home: return UIImage(systemName: "house")!
case .search: return UIImage(systemName: "magnifyingglass")!
case .notification: return UIImage(systemName: "bell")!
case .me: return UIImage(systemName: "person.fill")!
case .home: return Asset.ObjectsAndTools.house.image.withRenderingMode(.alwaysTemplate)
case .search: return Asset.ObjectsAndTools.magnifyingglass.image.withRenderingMode(.alwaysTemplate)
case .compose: return Asset.ObjectsAndTools.squareAndPencil.image.withRenderingMode(.alwaysTemplate)
case .notification: return Asset.ObjectsAndTools.bell.image.withRenderingMode(.alwaysTemplate)
case .me: return UIImage(systemName: "person")!
}
}
@ -86,6 +115,8 @@ class MainTabBarController: UITabBarController {
_viewController.context = context
_viewController.coordinator = coordinator
viewController = _viewController
case .compose:
viewController = UIViewController()
case .notification:
let _viewController = NotificationViewController()
_viewController.context = context
@ -143,24 +174,30 @@ extension MainTabBarController {
}
.store(in: &disposeBag)
// seealso: `ThemeService.apply(theme:)`
let tabs = Tab.allCases
let viewControllers: [UIViewController] = tabs.map { tab in
let viewController = tab.viewController(context: context, coordinator: coordinator)
viewController.tabBarItem.tag = tab.tag
viewController.tabBarItem.title = tab.title
viewController.tabBarItem.image = tab.image
viewController.tabBarItem.title = tab.title // needs for acessiblity large content label
viewController.tabBarItem.image = tab.image.imageWithoutBaseline()
viewController.tabBarItem.selectedImage = tab.selectedImage.imageWithoutBaseline()
viewController.tabBarItem.largeContentSizeImage = tab.largeImage.imageWithoutBaseline()
viewController.tabBarItem.accessibilityLabel = tab.title
viewController.tabBarItem.largeContentSizeImage = tab.largeImage
viewController.tabBarItem.imageInsets = UIEdgeInsets(top: 6, left: 0, bottom: -6, right: 0)
switch tab {
case .compose:
viewController.tabBarItem.isEnabled = false
default:
break
}
return viewController
}
_viewControllers = viewControllers
setViewControllers(viewControllers, animated: false)
selectedIndex = 0
UITabBarItem.appearance().setTitleTextAttributes([.foregroundColor : UIColor.clear], for: .normal)
UITabBarItem.appearance().setTitleTextAttributes([.foregroundColor : UIColor.clear], for: .highlighted)
UITabBarItem.appearance().setTitleTextAttributes([.foregroundColor : UIColor.clear], for: .selected)
context.apiService.error
.receive(on: DispatchQueue.main)
@ -208,13 +245,15 @@ extension MainTabBarController {
}
.store(in: &disposeBag)
// handle push notification. toggle entry when finish fetch latest notification
Publishers.CombineLatest(
// handle push notification.
// toggle entry when finish fetch latest notification
Publishers.CombineLatest3(
context.authenticationService.activeMastodonAuthentication,
context.notificationService.unreadNotificationCountDidUpdate
context.notificationService.unreadNotificationCountDidUpdate,
$currentTab
)
.receive(on: DispatchQueue.main)
.sink { [weak self] authentication, _ in
.sink { [weak self] authentication, _, currentTab in
guard let self = self else { return }
guard let notificationViewController = self.notificationViewController else { return }
@ -223,12 +262,19 @@ extension MainTabBarController {
return count > 0
} ?? false
let image = hasUnreadPushNotification ? UIImage(systemName: "bell.badge.fill")! : UIImage(systemName: "bell.fill")!
notificationViewController.tabBarItem.image = image
notificationViewController.navigationController?.tabBarItem.image = image
let image: UIImage = {
if currentTab == .notification {
return hasUnreadPushNotification ? Asset.ObjectsAndTools.bellBadgeFill.image.withRenderingMode(.alwaysTemplate) : Asset.ObjectsAndTools.bellFill.image.withRenderingMode(.alwaysTemplate)
} else {
return hasUnreadPushNotification ? Asset.ObjectsAndTools.bellBadge.image.withRenderingMode(.alwaysTemplate) : Asset.ObjectsAndTools.bell.image.withRenderingMode(.alwaysTemplate)
}
}()
notificationViewController.tabBarItem.image = image.imageWithoutBaseline()
notificationViewController.navigationController?.tabBarItem.image = image.imageWithoutBaseline()
}
.store(in: &disposeBag)
layoutComposeButton()
layoutAvatarButton()
$avatarURL
@ -280,7 +326,7 @@ extension MainTabBarController {
}
.store(in: &disposeBag)
currentTab
$currentTab
.receive(on: DispatchQueue.main)
.sink { [weak self] tab in
guard let self = self else { return }
@ -290,6 +336,8 @@ extension MainTabBarController {
updateTabBarDisplay()
composeButton.addTarget(self, action: #selector(MainTabBarController.composeButtonDidPressed(_:)), for: .touchUpInside)
#if DEBUG
// Debug Register viewController
// Task { @MainActor in
@ -307,23 +355,25 @@ extension MainTabBarController {
super.traitCollectionDidChange(previousTraitCollection)
updateTabBarDisplay()
updateComposeButtonAppearance()
updateAvatarButtonAppearance()
}
}
extension MainTabBarController {
private func updateTabBarDisplay() {
switch traitCollection.horizontalSizeClass {
case .compact:
tabBar.isHidden = false
default:
tabBar.isHidden = true
}
@objc private func composeButtonDidPressed(_ sender: UIButton) {
logger.log(level: .debug, "\((#file as NSString).lastPathComponent, privacy: .public)[\(#line, privacy: .public)], \(#function, privacy: .public)")
guard let authenticationBox = context.authenticationService.activeMastodonAuthenticationBox.value else { return }
let composeViewModel = ComposeViewModel(
context: context,
composeKind: .post,
authenticationBox: authenticationBox
)
coordinator.present(scene: .compose(viewModel: composeViewModel), from: nil, transition: .modal(animated: true, completion: nil))
}
}
extension MainTabBarController {
@objc private func tabBarLongPressGestureRecognizerHandler(_ sender: UILongPressGestureRecognizer) {
guard sender.state == .began else { return }
@ -351,6 +401,59 @@ extension MainTabBarController {
}
extension MainTabBarController {
private func updateTabBarDisplay() {
switch traitCollection.horizontalSizeClass {
case .compact:
tabBar.isHidden = false
composeButttonShadowBackgroundContainer.isHidden = false
default:
tabBar.isHidden = true
composeButttonShadowBackgroundContainer.isHidden = true
}
}
private func layoutComposeButton() {
guard composeButton.superview == nil else { return }
let _composeTabItem = self.tabBar.items?.first { item in item.tag == Tab.compose.tag }
guard let composeTabItem = _composeTabItem else { return }
guard let view = composeTabItem.value(forKey: "view") as? UIView else {
return
}
let _anchorImageView = view.subviews.first { subview in subview is UIImageView } as? UIImageView
guard let anchorImageView = _anchorImageView else {
assertionFailure()
return
}
anchorImageView.alpha = 0
composeButttonShadowBackgroundContainer.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(composeButttonShadowBackgroundContainer) // add to tabBar will crash on iPad when size class changing
NSLayoutConstraint.activate([
composeButttonShadowBackgroundContainer.centerXAnchor.constraint(equalTo: anchorImageView.centerXAnchor),
composeButttonShadowBackgroundContainer.centerYAnchor.constraint(equalTo: anchorImageView.centerYAnchor),
])
composeButttonShadowBackgroundContainer.cornerRadius = composeButton.layer.cornerRadius
composeButton.translatesAutoresizingMaskIntoConstraints = false
composeButttonShadowBackgroundContainer.addSubview(composeButton)
NSLayoutConstraint.activate([
composeButton.topAnchor.constraint(equalTo: composeButttonShadowBackgroundContainer.topAnchor),
composeButton.leadingAnchor.constraint(equalTo: composeButttonShadowBackgroundContainer.leadingAnchor),
composeButton.trailingAnchor.constraint(equalTo: composeButttonShadowBackgroundContainer.trailingAnchor),
composeButton.bottomAnchor.constraint(equalTo: composeButttonShadowBackgroundContainer.bottomAnchor),
])
composeButton.setContentHuggingPriority(.required - 1, for: .horizontal)
composeButton.setContentHuggingPriority(.required - 1, for: .vertical)
}
private func updateComposeButtonAppearance() {
composeButton.setBackgroundImage(UIImage.placeholder(color: Asset.Colors.Label.primary.color), for: .normal)
composeButton.setBackgroundImage(UIImage.placeholder(color: Asset.Colors.Label.primary.color.withAlphaComponent(0.8)), for: .highlighted)
}
private func layoutAvatarButton() {
guard avatarButton.superview == nil else { return }
@ -370,8 +473,8 @@ extension MainTabBarController {
self.avatarButton.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(self.avatarButton)
NSLayoutConstraint.activate([
self.avatarButton.centerXAnchor.constraint(equalTo: view.centerXAnchor),
self.avatarButton.centerYAnchor.constraint(equalTo: anchorImageView.centerYAnchor, constant: 1.5), // 1.5pt offset
self.avatarButton.centerXAnchor.constraint(equalTo: anchorImageView.centerXAnchor),
self.avatarButton.centerYAnchor.constraint(equalTo: anchorImageView.centerYAnchor),
self.avatarButton.widthAnchor.constraint(equalToConstant: MainTabBarController.avatarButtonSize.width).priority(.required - 1),
self.avatarButton.heightAnchor.constraint(equalToConstant: MainTabBarController.avatarButtonSize.height).priority(.required - 1),
])
@ -381,9 +484,10 @@ extension MainTabBarController {
}
private func updateAvatarButtonAppearance() {
avatarButton.borderColor = currentTab.value == .me ? .label : .systemFill
avatarButton.borderColor = currentTab == .me ? .label : .systemFill
avatarButton.setNeedsLayout()
}
}
extension MainTabBarController {
@ -403,11 +507,12 @@ extension MainTabBarController: UITabBarControllerDelegate {
func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s: select %s", ((#file as NSString).lastPathComponent), #line, #function, viewController.debugDescription)
defer {
if let tab = Tab(rawValue: tabBarController.selectedIndex) {
currentTab.value = tab
if let tab = Tab(rawValue: viewController.tabBarItem.tag) {
currentTab = tab
}
}
guard currentTab.value.rawValue == tabBarController.selectedIndex,
// assert index is as same as the tab rawValue
guard currentTab.rawValue == tabBarController.selectedIndex,
let navigationController = viewController as? UINavigationController,
navigationController.viewControllers.count == 1,
let scrollViewContainer = navigationController.topViewController as? ScrollViewContainer else {
@ -478,7 +583,13 @@ extension MainTabBarController {
var switchToTabKeyCommands: [UIKeyCommand] {
var commands: [UIKeyCommand] = []
for (i, tab) in Tab.allCases.enumerated() {
let tabs: [Tab] = [
.home,
.search,
.notification,
.me
]
for (i, tab) in tabs.enumerated() {
let title = L10n.Common.Controls.Keyboard.Common.switchToTab(tab.title)
let input = String(i + 1)
let command = UIKeyCommand(
@ -584,7 +695,7 @@ extension MainTabBarController {
let previousTab = Tab(rawValue: selectedIndex)
selectedIndex = index
if let tab = Tab(rawValue: index) {
currentTab.value = tab
currentTab = tab
}
if let previousTab = previousTab {

View File

@ -208,7 +208,7 @@ extension RootSplitViewController: UISplitViewControllerDelegate {
switch proposedTopColumn {
case .compact:
RootSplitViewController.transform(from: contentSplitViewController.mainTabBarController, to: compactMainTabBarViewController)
compactMainTabBarViewController.currentTab.value = contentSplitViewController.currentSupplementaryTab
compactMainTabBarViewController.currentTab = contentSplitViewController.currentSupplementaryTab
default:
assertionFailure()
@ -231,11 +231,11 @@ extension RootSplitViewController: UISplitViewControllerDelegate {
RootSplitViewController.transform(from: compactMainTabBarViewController, to: contentSplitViewController.mainTabBarController)
let tab = compactMainTabBarViewController.currentTab.value
let tab = compactMainTabBarViewController.currentTab
if tab == .search {
contentSplitViewController.currentSupplementaryTab = .home
} else {
contentSplitViewController.currentSupplementaryTab = compactMainTabBarViewController.currentTab.value
contentSplitViewController.currentSupplementaryTab = compactMainTabBarViewController.currentTab
}
return proposedDisplayMode

View File

@ -154,10 +154,9 @@ extension SidebarViewController {
coordinator.animate { context in
self.collectionView.collectionViewLayout.invalidateLayout()
} completion: { [weak self] context in
// guard let self = self else { return }
} completion: { context in
// do nothing
}
}
}

View File

@ -22,7 +22,8 @@ final class SidebarViewModel {
let context: AppContext
@Published private var isSidebarDataSourceReady = false
@Published private var isAvatarButtonDataReady = false
@Published var currentTab: MainTabBarController.Tab = .home
// output
var diffableDataSource: UICollectionViewDiffableDataSource<Section, Item>?
var secondaryDiffableDataSource: UICollectionViewDiffableDataSource<Section, Item>?
@ -86,35 +87,55 @@ extension SidebarViewModel {
}
}()
cell.item = SidebarListContentView.Item(
isActive: false,
title: item.title,
image: item.sidebarImage,
image: item.image,
activeImage: item.selectedImage,
imageURL: imageURL
)
cell.setNeedsUpdateConfiguration()
cell.isAccessibilityElement = true
cell.accessibilityLabel = item.title
self.$currentTab
.receive(on: DispatchQueue.main)
.sink { [weak cell] currentTab in
guard let cell = cell else { return }
cell.item?.isActive = currentTab == item
cell.setNeedsUpdateConfiguration()
}
.store(in: &cell.disposeBag)
switch item {
case .notification:
Publishers.CombineLatest(
Publishers.CombineLatest3(
self.context.authenticationService.activeMastodonAuthentication,
self.context.notificationService.unreadNotificationCountDidUpdate
self.context.notificationService.unreadNotificationCountDidUpdate,
self.$currentTab
)
.receive(on: DispatchQueue.main)
.sink { [weak cell] authentication, _ in
.sink { [weak cell] authentication, _, currentTab in
guard let cell = cell else { return }
let hasUnreadPushNotification: Bool = authentication.flatMap { authentication in
let count = UserDefaults.shared.getNotificationCountWithAccessToken(accessToken: authentication.userAccessToken)
return count > 0
} ?? false
let image = hasUnreadPushNotification ? UIImage(systemName: "bell.badge")! : UIImage(systemName: "bell")!
cell._contentView?.imageView.image = image
let image: UIImage = {
if currentTab == .notification {
return hasUnreadPushNotification ? Asset.ObjectsAndTools.bellBadgeFill.image.withRenderingMode(.alwaysTemplate) : Asset.ObjectsAndTools.bellFill.image.withRenderingMode(.alwaysTemplate)
} else {
return hasUnreadPushNotification ? Asset.ObjectsAndTools.bellBadge.image.withRenderingMode(.alwaysTemplate) : Asset.ObjectsAndTools.bell.image.withRenderingMode(.alwaysTemplate)
}
}()
cell.item?.image = image
cell.item?.activeImage = image
cell.setNeedsUpdateConfiguration()
}
.store(in: &cell.disposeBag)
case .me:
guard let authentication = self.context.authenticationService.activeMastodonAuthentication.value else { break }
let currentUserDisplayName = authentication.user.displayNameWithFallback ?? "no user"
let currentUserDisplayName = authentication.user.displayNameWithFallback
cell.accessibilityHint = L10n.Scene.AccountList.tabBarHint(currentUserDisplayName)
default:
break
@ -122,7 +143,7 @@ extension SidebarViewModel {
}
let cellRegistration = UICollectionView.CellRegistration<SidebarListCollectionViewCell, SidebarListContentView.Item> { [weak self] cell, indexPath, item in
guard let self = self else { return }
guard let _ = self else { return }
cell.item = item
cell.setNeedsUpdateConfiguration()
cell.isAccessibilityElement = true
@ -140,15 +161,19 @@ extension SidebarViewModel {
return collectionView.dequeueConfiguredReusableCell(using: tabCellRegistration, for: indexPath, item: tab)
case .setting:
let item = SidebarListContentView.Item(
isActive: false,
title: L10n.Common.Controls.Actions.settings,
image: UIImage(systemName: "gear")!,
image: Asset.ObjectsAndTools.gear.image.withRenderingMode(.alwaysTemplate),
activeImage: Asset.ObjectsAndTools.gear.image.withRenderingMode(.alwaysTemplate),
imageURL: nil
)
return collectionView.dequeueConfiguredReusableCell(using: cellRegistration, for: indexPath, item: item)
case .compose:
let item = SidebarListContentView.Item(
isActive: false,
title: L10n.Common.Controls.Actions.compose,
image: UIImage(systemName: "square.and.pencil")!,
image: Asset.ObjectsAndTools.squareAndPencil.image.withRenderingMode(.alwaysTemplate),
activeImage: Asset.ObjectsAndTools.squareAndPencil.image.withRenderingMode(.alwaysTemplate),
imageURL: nil
)
return collectionView.dequeueConfiguredReusableCell(using: cellRegistration, for: indexPath, item: item)
@ -192,15 +217,15 @@ extension SidebarViewModel {
}
let item = SidebarListContentView.Item(
isActive: false,
title: L10n.Common.Controls.Actions.compose,
image: UIImage(systemName: "square.and.pencil")!,
image: Asset.ObjectsAndTools.squareAndPencil.image.withRenderingMode(.alwaysTemplate),
activeImage: Asset.ObjectsAndTools.squareAndPencil.image.withRenderingMode(.alwaysTemplate),
imageURL: nil
)
return collectionView.dequeueConfiguredReusableCell(using: cellRegistration, for: indexPath, item: item)
}
// _secondaryDiffableDataSource.supplementaryViewProvider = { collectionView, elementKind, indexPath in
// return nil
// }
secondaryDiffableDataSource = _secondaryDiffableDataSource
var secondarySnapshot = NSDiffableDataSourceSnapshot<Section, Item>()

View File

@ -93,12 +93,14 @@ extension SidebarListContentView {
// configure model
imageView.isHidden = item.imageURL != nil
avatarButton.isHidden = item.imageURL == nil
imageView.image = item.image.withRenderingMode(.alwaysTemplate)
imageView.image = item.isActive ? item.activeImage.withRenderingMode(.alwaysTemplate) : item.image.withRenderingMode(.alwaysTemplate)
avatarButton.avatarImageView.setImage(
url: item.imageURL,
placeholder: avatarButton.avatarImageView.image ?? .placeholder(color: .systemFill), // reuse to avoid blink
scaleToSize: nil
)
avatarButton.borderWidth = item.isActive ? 2 : 0
avatarButton.setNeedsLayout()
}
}
@ -107,25 +109,32 @@ extension SidebarListContentView {
// state
var isSelected: Bool = false
var isHighlighted: Bool = false
var isActive: Bool
// model
let title: String
let image: UIImage
var image: UIImage
var activeImage: UIImage
let imageURL: URL?
static func == (lhs: SidebarListContentView.Item, rhs: SidebarListContentView.Item) -> Bool {
return lhs.isSelected == rhs.isSelected
&& lhs.isHighlighted == rhs.isHighlighted
&& lhs.isActive == rhs.isActive
&& lhs.title == rhs.title
&& lhs.image == rhs.image
&& lhs.activeImage == rhs.activeImage
&& lhs.imageURL == rhs.imageURL
}
func hash(into hasher: inout Hasher) {
hasher.combine(isSelected)
hasher.combine(isHighlighted)
hasher.combine(isActive)
hasher.combine(title)
hasher.combine(image)
hasher.combine(activeImage)
imageURL.flatMap { hasher.combine($0) }
}
}

View File

@ -448,7 +448,7 @@ extension SettingsViewController: SettingsAppearanceTableViewCellDelegate {
guard let dataSource = viewModel.dataSource else { return }
guard let indexPath = tableView.indexPath(for: cell) else { return }
let item = dataSource.itemIdentifier(for: indexPath)
guard case let .appearance(record) = item else { return }
guard case .appearance = item else { return }
Task { @MainActor in
switch appearanceMode {

View File

@ -10,7 +10,41 @@ import UIKit
// Make status bar style adaptive for child view controller
// SeeAlso: `modalPresentationCapturesStatusBarAppearance`
class AdaptiveStatusBarStyleNavigationController: UINavigationController {
private lazy var fullWidthBackGestureRecognizer = UIPanGestureRecognizer()
override var childForStatusBarStyle: UIViewController? {
visibleViewController
}
}
// ref: https://stackoverflow.com/a/60598558/3797903
extension AdaptiveStatusBarStyleNavigationController {
override func viewDidLoad() {
super.viewDidLoad()
setupFullWidthBackGesture()
}
private func setupFullWidthBackGesture() {
// The trick here is to wire up our full-width `fullWidthBackGestureRecognizer` to execute the same handler as
// the system `interactivePopGestureRecognizer`. That's done by assigning the same "targets" (effectively
// object and selector) of the system one to our gesture recognizer.
guard let interactivePopGestureRecognizer = interactivePopGestureRecognizer,
let targets = interactivePopGestureRecognizer.value(forKey: "targets")
else { return }
fullWidthBackGestureRecognizer.setValue(targets, forKey: "targets")
fullWidthBackGestureRecognizer.delegate = self
view.addGestureRecognizer(fullWidthBackGestureRecognizer)
}
}
// MARK: - UIGestureRecognizerDelegate
extension AdaptiveStatusBarStyleNavigationController: UIGestureRecognizerDelegate {
func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
let isSystemSwipeToBackEnabled = interactivePopGestureRecognizer?.isEnabled == true
let isThereStackedViewControllers = viewControllers.count > 1
return isSystemSwipeToBackEnabled && isThereStackedViewControllers
}
}

View File

@ -255,6 +255,8 @@ extension MediaHostToMediaPreviewViewControllerAnimatedTransitioning {
rect.size.height -= offset
return rect
}()
// FIXME:
let maskLayerToFinalPath = maskLayerToFinalRect.flatMap { UIBezierPath(rect: $0) }?.cgPath
if let maskLayerToPath = maskLayerToPath {

View File

@ -34,7 +34,7 @@ extension APIService {
let value = response.value.ancestors + response.value.descendants
for entity in value {
Persistence.Status.createOrMerge(
_ = Persistence.Status.createOrMerge(
in: managedObjectContext,
context: Persistence.Status.PersistContext(
domain: domain,

View File

@ -95,7 +95,7 @@ extension InstanceService {
self.logger.log(level: .debug, "\((#file as NSString).lastPathComponent, privacy: .public)[\(#line, privacy: .public)], \(#function, privacy: .public): [Instance] update instance for domain: \(domain)")
}
} receiveValue: { [weak self] response in
guard let self = self else { return }
guard let _ = self else { return }
// do nothing
}
.store(in: &disposeBag)

View File

@ -17,9 +17,9 @@
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>1.4.0</string>
<string>1.4.1</string>
<key>CFBundleVersion</key>
<string>121</string>
<string>126</string>
<key>NSExtension</key>
<dict>
<key>NSExtensionAttributes</key>

View File

@ -0,0 +1,15 @@
{
"images" : [
{
"filename" : "Share iOS.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true
}
}

View File

@ -0,0 +1,110 @@
%PDF-1.7
1 0 obj
<< >>
endobj
2 0 obj
<< /Length 3 0 R >>
stream
/DeviceRGB CS
/DeviceRGB cs
q
1.000000 0.000000 -0.000000 1.000000 5.004150 3.928345 cm
0.000000 0.000000 0.000000 scn
16.750000 11.071655 m
17.129696 11.071655 17.443491 10.789501 17.493153 10.423426 c
17.500000 10.321655 l
17.500000 3.320786 l
17.500000 1.587753 16.143545 0.171539 14.434423 0.075930 c
14.250000 0.070786 l
3.250000 0.070786 l
1.516969 0.070786 0.100754 1.427240 0.005145 3.136362 c
0.000000 3.320786 l
0.000000 10.321655 l
0.000000 10.735868 0.335786 11.071655 0.750000 11.071655 c
1.129696 11.071655 1.443491 10.789501 1.493153 10.423426 c
1.500000 10.321655 l
1.500000 3.320786 l
1.500000 2.402613 2.207110 1.649591 3.106473 1.576586 c
3.250000 1.570786 l
14.250000 1.570786 l
15.168174 1.570786 15.921191 2.277895 15.994198 3.177258 c
16.000000 3.320786 l
16.000000 10.321655 l
16.000000 10.735868 16.335787 11.071655 16.750000 11.071655 c
h
3.215397 14.855352 m
8.211636 19.851965 l
8.477744 20.118093 8.894129 20.142456 9.187749 19.924934 c
9.271878 19.852423 l
14.276731 14.855809 l
14.569866 14.563158 14.570257 14.088284 14.277605 13.795150 c
14.011558 13.528664 13.594913 13.504115 13.301123 13.721727 c
13.216944 13.794276 l
9.493999 17.510654 l
9.494885 5.816710 l
9.494885 5.437014 9.212732 5.123218 8.846657 5.073555 c
8.744885 5.066710 l
8.365190 5.066710 8.051395 5.348864 8.001733 5.714939 c
7.994885 5.816710 l
7.993999 17.513655 l
4.276096 13.794732 l
4.009840 13.528456 3.593178 13.504234 3.299558 13.722077 c
3.215437 13.794693 l
2.949160 14.060949 2.924938 14.477612 3.142782 14.771232 c
3.215397 14.855352 l
8.211636 19.851965 l
3.215397 14.855352 l
h
f
n
Q
endstream
endobj
3 0 obj
1600
endobj
4 0 obj
<< /Annots []
/Type /Page
/MediaBox [ 0.000000 0.000000 28.000000 28.000000 ]
/Resources 1 0 R
/Contents 2 0 R
/Parent 5 0 R
>>
endobj
5 0 obj
<< /Kids [ 4 0 R ]
/Count 1
/Type /Pages
>>
endobj
6 0 obj
<< /Pages 5 0 R
/Type /Catalog
>>
endobj
xref
0 7
0000000000 65535 f
0000000010 00000 n
0000000034 00000 n
0000001690 00000 n
0000001713 00000 n
0000001886 00000 n
0000001960 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 6 0 R
/Size 7
>>
startxref
2019
%%EOF

View File

@ -0,0 +1,15 @@
{
"images" : [
{
"filename" : "bell.badge.fill.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true
}
}

View File

@ -0,0 +1,94 @@
%PDF-1.7
1 0 obj
<< >>
endobj
2 0 obj
<< /Length 3 0 R >>
stream
/DeviceRGB CS
/DeviceRGB cs
q
1.000000 0.000000 -0.000000 1.000000 4.000000 3.251190 cm
0.000000 0.000000 0.000000 scn
17.228973 14.106000 m
17.604315 14.106000 17.967243 14.159944 18.310644 14.260609 c
18.330521 14.022223 18.340664 13.781026 18.340664 13.537420 c
18.340664 9.025727 l
19.917404 5.460056 l
19.978443 5.322020 20.010000 5.172432 20.010000 5.021130 c
20.010000 4.429121 19.537165 3.949203 18.953897 3.949203 c
1.056364 3.949203 l
0.907638 3.949203 0.760588 3.981087 0.624843 4.042767 c
0.092485 4.284660 -0.145878 4.918783 0.092444 5.459118 c
1.665367 9.025314 l
1.665486 13.551995 l
1.670396 13.833986 l
1.824999 18.382032 5.507209 22.000000 10.003014 22.000000 c
11.607554 22.000000 13.106230 21.539965 14.378001 20.742750 c
13.732699 20.037863 13.338069 19.093309 13.338069 18.055204 c
13.338069 15.874119 15.080086 14.106000 17.228973 14.106000 c
h
13.291688 2.819208 m
13.026393 1.219061 11.654965 0.000000 10.003014 0.000000 c
8.351062 0.000000 6.979633 1.219061 6.714338 2.819208 c
13.291688 2.819208 l
h
17.228973 15.234344 m
18.763893 15.234344 20.008190 16.497286 20.008190 18.055204 c
20.008190 19.613121 18.763893 20.876064 17.228973 20.876064 c
15.694054 20.876064 14.449756 19.613121 14.449756 18.055204 c
14.449756 16.497286 15.694054 15.234344 17.228973 15.234344 c
h
f
n
Q
endstream
endobj
3 0 obj
1305
endobj
4 0 obj
<< /Annots []
/Type /Page
/MediaBox [ 0.000000 0.000000 28.000000 28.000000 ]
/Resources 1 0 R
/Contents 2 0 R
/Parent 5 0 R
>>
endobj
5 0 obj
<< /Kids [ 4 0 R ]
/Count 1
/Type /Pages
>>
endobj
6 0 obj
<< /Pages 5 0 R
/Type /Catalog
>>
endobj
xref
0 7
0000000000 65535 f
0000000010 00000 n
0000000034 00000 n
0000001395 00000 n
0000001418 00000 n
0000001591 00000 n
0000001665 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 6 0 R
/Size 7
>>
startxref
1724
%%EOF

View File

@ -0,0 +1,15 @@
{
"images" : [
{
"filename" : "bell.badge.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true
}
}

View File

@ -0,0 +1,112 @@
%PDF-1.7
1 0 obj
<< >>
endobj
2 0 obj
<< /Length 3 0 R >>
stream
/DeviceRGB CS
/DeviceRGB cs
q
1.000000 0.000000 -0.000000 1.000000 4.000000 3.000000 cm
0.000000 0.000000 0.000000 scn
9.991263 22.000000 m
11.600367 22.000000 13.104079 21.540958 14.379686 20.742632 c
13.999659 20.330532 13.705750 19.835861 13.527027 19.288073 c
12.501425 19.935305 11.289410 20.308149 9.991263 20.308149 c
6.295337 20.308149 3.312736 17.291861 3.312205 13.540749 c
3.312205 8.567127 l
1.816118 5.077236 l
18.175934 5.077236 l
16.670322 8.566052 l
16.670446 13.526248 l
16.666271 13.780252 l
16.662128 13.902481 16.654818 14.023849 16.644423 14.144276 c
16.834492 14.115398 17.029049 14.100430 17.227058 14.100430 c
17.602913 14.100430 17.966335 14.154360 18.310204 14.254990 c
18.322084 14.112284 18.330519 13.968523 18.335421 13.823792 c
18.340088 13.540749 l
18.340088 8.919773 l
19.876272 5.360107 l
19.953144 5.181980 19.992825 4.989672 19.992825 4.795261 c
19.992825 4.016609 19.369843 3.385387 18.601355 3.385387 c
13.330793 3.383699 l
13.330793 1.514933 11.835634 -0.000002 9.991263 -0.000002 c
8.212763 -0.000002 6.758977 1.408655 6.657403 3.184881 c
6.651230 3.386263 l
1.391824 3.385387 l
1.201094 3.385387 1.012400 3.425116 0.837460 3.502110 c
0.132594 3.812326 -0.190615 4.642769 0.115552 5.356956 c
1.642440 8.918699 l
1.642440 13.540869 l
1.643104 18.227058 5.373904 22.000000 9.991263 22.000000 c
h
11.660524 3.386263 m
8.321499 3.383699 l
8.321499 2.449318 9.069077 1.691849 9.991263 1.691849 c
10.859203 1.691849 11.572474 2.362822 11.653385 3.220762 c
11.660524 3.386263 l
h
14.488358 18.551571 m
14.594155 19.146286 14.884010 19.676186 15.296021 20.078548 c
15.796463 20.567268 16.477119 20.867832 17.227058 20.867832 c
18.764036 20.867832 20.010000 19.605387 20.010000 18.048080 c
20.010000 16.815081 19.228939 15.766922 18.140787 15.383841 c
17.854582 15.283082 17.547131 15.228331 17.227058 15.228331 c
16.950932 15.228331 16.684196 15.269077 16.432392 15.344961 c
15.282606 15.691461 14.444118 16.770555 14.444118 18.048080 c
14.444118 18.219936 14.459294 18.388199 14.488358 18.551571 c
h
f
n
Q
endstream
endobj
3 0 obj
2038
endobj
4 0 obj
<< /Annots []
/Type /Page
/MediaBox [ 0.000000 0.000000 28.000000 28.000000 ]
/Resources 1 0 R
/Contents 2 0 R
/Parent 5 0 R
>>
endobj
5 0 obj
<< /Kids [ 4 0 R ]
/Count 1
/Type /Pages
>>
endobj
6 0 obj
<< /Pages 5 0 R
/Type /Catalog
>>
endobj
xref
0 7
0000000000 65535 f
0000000010 00000 n
0000000034 00000 n
0000002128 00000 n
0000002151 00000 n
0000002324 00000 n
0000002398 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 6 0 R
/Size 7
>>
startxref
2457
%%EOF

View File

@ -0,0 +1,15 @@
{
"images" : [
{
"filename" : "bell.fill.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true
}
}

View File

@ -0,0 +1,88 @@
%PDF-1.7
1 0 obj
<< >>
endobj
2 0 obj
<< /Length 3 0 R >>
stream
/DeviceRGB CS
/DeviceRGB cs
q
1.000000 0.000000 -0.000000 1.000000 3.994385 2.997498 cm
0.000000 0.000000 0.000000 scn
13.471207 3.000130 m
13.228097 1.303843 11.769090 0.000013 10.005556 0.000013 c
8.242023 0.000013 6.783014 1.303843 6.539904 3.000130 c
13.471207 3.000130 l
h
10.005556 22.002502 m
14.615297 22.002502 18.368101 18.333513 18.503042 13.756456 c
18.503042 13.501259 l
18.506800 13.501259 l
18.506556 9.389503 l
19.920570 5.745182 l
19.958755 5.646759 19.984545 5.544180 19.997494 5.439810 c
20.007233 5.282207 l
20.007233 4.619465 19.503553 4.074364 18.858105 4.008816 c
18.727232 4.002207 l
1.280344 4.002207 l
1.121637 4.002207 0.964313 4.031721 0.816398 4.089247 c
0.198722 4.329462 -0.126749 4.996468 0.046107 5.621784 c
0.087384 5.746153 l
1.503556 9.390502 l
1.504312 13.501259 l
1.504312 18.196365 5.310449 22.002502 10.005556 22.002502 c
h
f
n
Q
endstream
endobj
3 0 obj
870
endobj
4 0 obj
<< /Annots []
/Type /Page
/MediaBox [ 0.000000 0.000000 28.000000 28.000000 ]
/Resources 1 0 R
/Contents 2 0 R
/Parent 5 0 R
>>
endobj
5 0 obj
<< /Kids [ 4 0 R ]
/Count 1
/Type /Pages
>>
endobj
6 0 obj
<< /Pages 5 0 R
/Type /Catalog
>>
endobj
xref
0 7
0000000000 65535 f
0000000010 00000 n
0000000034 00000 n
0000000960 00000 n
0000000982 00000 n
0000001155 00000 n
0000001229 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 6 0 R
/Size 7
>>
startxref
1288
%%EOF

View File

@ -0,0 +1,15 @@
{
"images" : [
{
"filename" : "bell.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true
}
}

View File

@ -0,0 +1,106 @@
%PDF-1.7
1 0 obj
<< >>
endobj
2 0 obj
<< /Length 3 0 R >>
stream
/DeviceRGB CS
/DeviceRGB cs
q
1.000000 0.000000 -0.000000 1.000000 3.994385 2.997498 cm
0.000000 0.000000 0.000000 scn
10.005556 22.002502 m
14.615297 22.002502 18.368101 18.333513 18.503042 13.756456 c
18.506800 13.501259 l
18.506556 8.889502 l
19.920570 5.245478 l
19.958755 5.147055 19.984545 5.044476 19.997494 4.940105 c
20.007233 4.782503 l
20.007233 4.119761 19.503553 3.574659 18.858105 3.509111 c
18.727232 3.502502 l
13.506981 3.501438 l
13.506981 1.567654 11.939340 0.000013 10.005556 0.000013 c
8.136232 0.000013 6.609047 1.464890 6.509312 3.309326 c
6.504000 3.503502 l
1.280344 3.502502 l
1.121637 3.502502 0.964313 3.532017 0.816398 3.589542 c
0.198722 3.829758 -0.126749 4.496763 0.046107 5.122080 c
0.087384 5.246449 l
1.503556 8.890503 l
1.504312 13.501259 l
1.504312 18.196365 5.310449 22.002502 10.005556 22.002502 c
h
12.001492 3.352070 m
12.006001 3.503502 l
8.004131 3.501438 l
8.004131 2.396082 8.900200 1.500013 10.005556 1.500013 c
11.060669 1.500013 11.925088 2.316473 12.001492 3.352070 c
h
10.005556 20.502502 m
6.219432 20.502502 3.135237 17.497185 3.008372 13.741951 c
3.004312 13.501259 l
3.004312 8.749136 l
3.004312 8.687140 2.996625 8.625507 2.981514 8.565626 c
2.953312 8.477293 l
1.601556 5.003502 l
18.405556 5.003502 l
17.057579 8.477861 l
17.035206 8.535532 17.020094 8.595635 17.012506 8.656790 c
17.006800 8.749136 l
17.006800 13.501259 l
17.006800 17.367939 13.872236 20.502502 10.005556 20.502502 c
h
f
n
Q
endstream
endobj
3 0 obj
1451
endobj
4 0 obj
<< /Annots []
/Type /Page
/MediaBox [ 0.000000 0.000000 28.000000 28.000000 ]
/Resources 1 0 R
/Contents 2 0 R
/Parent 5 0 R
>>
endobj
5 0 obj
<< /Kids [ 4 0 R ]
/Count 1
/Type /Pages
>>
endobj
6 0 obj
<< /Pages 5 0 R
/Type /Catalog
>>
endobj
xref
0 7
0000000000 65535 f
0000000010 00000 n
0000000034 00000 n
0000001541 00000 n
0000001564 00000 n
0000001737 00000 n
0000001811 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 6 0 R
/Size 7
>>
startxref
1870
%%EOF

View File

@ -0,0 +1,15 @@
{
"images" : [
{
"filename" : "gear.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true
}
}

View File

@ -0,0 +1,155 @@
%PDF-1.7
1 0 obj
<< >>
endobj
2 0 obj
<< /Length 3 0 R >>
stream
/DeviceRGB CS
/DeviceRGB cs
q
1.000000 0.000000 -0.000000 1.000000 4.639893 4.163849 cm
0.000000 0.000000 0.000000 scn
9.372525 19.586090 m
10.106503 19.577631 10.837610 19.492828 11.554037 19.333052 c
11.866778 19.263306 12.100667 19.002579 12.136167 18.684128 c
12.306372 17.157282 l
12.383412 16.456230 12.975316 15.925249 13.680974 15.924509 c
13.870646 15.924213 14.058271 15.963713 14.233541 16.041258 c
15.634164 16.656530 l
15.925470 16.784498 16.265816 16.714733 16.483282 16.482475 c
17.495462 15.401449 18.249289 14.104940 18.688040 12.690507 c
18.782648 12.385511 18.673761 12.054057 18.416712 11.864587 c
17.175230 10.949497 l
16.821091 10.689301 16.611935 10.276085 16.611935 9.836634 c
16.611935 9.397182 16.821091 8.983968 17.176010 8.723198 c
18.418562 7.807791 l
18.675699 7.618353 18.784660 7.286852 18.690054 6.981801 c
18.251465 5.567602 17.498068 4.271195 16.486473 3.189995 c
16.269207 2.957779 15.929114 2.887827 15.637836 3.015442 c
14.231503 3.631588 l
13.829185 3.807648 13.367112 3.781857 12.986887 3.562117 c
12.606662 3.342377 12.353621 2.954891 12.305302 2.518358 c
12.136227 0.991678 l
12.101363 0.676876 11.872503 0.417910 11.564378 0.344601 c
10.115929 -0.000013 8.606833 -0.000013 7.158383 0.344601 c
6.850258 0.417910 6.621398 0.676876 6.586535 0.991678 c
6.417712 2.516102 l
6.368124 2.951803 6.114693 3.338112 5.734776 3.557108 c
5.354860 3.776103 4.893555 3.801792 4.492552 3.626715 c
3.085926 3.010441 l
2.794572 2.882792 2.454386 2.952816 2.237134 3.185158 c
1.224976 4.267610 0.471545 5.565555 0.033552 6.981297 c
-0.060786 7.286231 0.048213 7.617466 0.305198 7.806790 c
1.548530 8.722771 l
1.902669 8.982967 2.111826 9.396182 2.111826 9.835633 c
2.111826 10.275084 1.902669 10.688300 1.548066 10.948837 c
0.305513 11.863244 l
0.048147 12.052642 -0.060952 12.384308 0.033719 12.689507 c
0.472470 14.103941 1.226297 15.400448 2.238477 16.481474 c
2.455943 16.713732 2.796290 16.783497 3.087596 16.655531 c
4.487972 16.040365 l
4.890913 15.863533 5.354152 15.890244 5.736122 16.113400 c
6.116442 16.334003 6.369638 16.721867 6.418519 17.158447 c
6.588595 18.684128 l
6.624113 19.002741 6.858214 19.263550 7.171155 19.333147 c
7.888429 19.492670 8.620303 19.577436 9.372525 19.586090 c
h
9.372712 18.086191 m
8.918673 18.080845 8.465910 18.041662 8.018175 17.969074 c
7.909245 16.991905 l
7.807416 16.082413 7.280385 15.275068 6.490771 14.817059 c
5.696323 14.352917 4.727715 14.297064 3.884934 14.666923 c
2.986644 15.061529 l
2.414711 14.367364 1.959492 13.584736 1.638873 12.744408 c
2.436671 12.157299 l
3.175481 11.614474 3.611826 10.752420 3.611826 9.835633 c
3.611826 8.918846 3.175481 8.056792 2.437450 7.514541 c
1.638397 6.925866 l
1.958737 6.084057 2.414029 5.299965 2.986352 4.604462 c
3.891485 5.001020 l
4.729578 5.366932 5.691594 5.313361 6.483880 4.856663 c
7.276166 4.399964 7.804679 3.594347 7.908344 2.683468 c
8.017305 1.699598 l
8.906950 1.548321 9.815811 1.548321 10.705456 1.699598 c
10.814412 2.683426 l
10.915205 3.594033 11.443104 4.402411 12.236333 4.860834 c
13.029562 5.319258 13.993543 5.373064 14.833156 5.005638 c
15.737573 4.609392 l
16.309378 5.303812 16.764484 6.086632 17.085032 6.927112 c
16.287088 7.514968 l
15.548278 8.057793 15.111936 8.919847 15.111936 9.836634 c
15.111936 10.753421 15.548280 11.615475 16.286161 12.157617 c
17.083044 12.744996 l
16.762415 13.585482 16.307142 14.368252 15.735116 15.062530 c
14.838643 14.668724 l
14.473309 14.507083 14.078127 14.423886 13.679017 14.424510 c
12.209332 14.426050 10.975889 15.532539 10.815476 16.992264 c
10.706551 17.969393 l
10.261019 18.041893 9.812987 18.080971 9.372712 18.086191 c
h
9.360047 13.586140 m
11.431115 13.586140 13.110047 11.907207 13.110047 9.836140 c
13.110047 7.765072 11.431115 6.086140 9.360047 6.086140 c
7.288980 6.086140 5.610047 7.765072 5.610047 9.836140 c
5.610047 11.907207 7.288980 13.586140 9.360047 13.586140 c
h
9.360047 12.086140 m
8.117407 12.086140 7.110047 11.078780 7.110047 9.836140 c
7.110047 8.593499 8.117407 7.586140 9.360047 7.586140 c
10.602688 7.586140 11.610047 8.593499 11.610047 9.836140 c
11.610047 11.078780 10.602688 12.086140 9.360047 12.086140 c
h
f
n
Q
endstream
endobj
3 0 obj
4141
endobj
4 0 obj
<< /Annots []
/Type /Page
/MediaBox [ 0.000000 0.000000 28.000000 28.000000 ]
/Resources 1 0 R
/Contents 2 0 R
/Parent 5 0 R
>>
endobj
5 0 obj
<< /Kids [ 4 0 R ]
/Count 1
/Type /Pages
>>
endobj
6 0 obj
<< /Pages 5 0 R
/Type /Catalog
>>
endobj
xref
0 7
0000000000 65535 f
0000000010 00000 n
0000000034 00000 n
0000004231 00000 n
0000004254 00000 n
0000004427 00000 n
0000004501 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 6 0 R
/Size 7
>>
startxref
4560
%%EOF

View File

@ -0,0 +1,15 @@
{
"images" : [
{
"filename" : "Home-fill.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true
}
}

View File

@ -0,0 +1,85 @@
%PDF-1.7
1 0 obj
<< >>
endobj
2 0 obj
<< /Length 3 0 R >>
stream
/DeviceRGB CS
/DeviceRGB cs
q
1.000000 0.000000 -0.000000 1.000000 4.000000 2.835022 cm
0.000000 0.000000 0.000000 scn
8.592125 21.667089 m
9.414732 22.326954 10.585270 22.326952 11.407875 21.667089 c
19.157869 15.450343 l
19.690231 15.023304 19.999994 14.377716 19.999994 13.695241 c
19.999994 2.414970 l
19.999994 1.172331 18.992638 0.164970 17.749996 0.164970 c
15.250000 0.164970 l
14.007360 0.164970 13.000000 1.172327 13.000000 2.414968 c
13.000000 8.914963 l
13.000000 9.329177 12.664214 9.664963 12.250000 9.664963 c
7.750000 9.664963 l
7.335785 9.664963 7.000000 9.329177 7.000000 8.914964 c
7.000000 2.414970 l
7.000000 1.172331 5.992641 0.164970 4.750000 0.164970 c
2.250000 0.164970 l
1.007360 0.164970 0.000000 1.172327 0.000000 2.414968 c
0.000000 13.695240 l
0.000000 14.377715 0.309763 15.023304 0.842125 15.450343 c
8.592125 21.667089 l
h
f
n
Q
endstream
endobj
3 0 obj
862
endobj
4 0 obj
<< /Annots []
/Type /Page
/MediaBox [ 0.000000 0.000000 28.000000 28.000000 ]
/Resources 1 0 R
/Contents 2 0 R
/Parent 5 0 R
>>
endobj
5 0 obj
<< /Kids [ 4 0 R ]
/Count 1
/Type /Pages
>>
endobj
6 0 obj
<< /Pages 5 0 R
/Type /Catalog
>>
endobj
xref
0 7
0000000000 65535 f
0000000010 00000 n
0000000034 00000 n
0000000952 00000 n
0000000974 00000 n
0000001147 00000 n
0000001221 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 6 0 R
/Size 7
>>
startxref
1280
%%EOF

View File

@ -0,0 +1,15 @@
{
"images" : [
{
"filename" : "Home.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true
}
}

View File

@ -0,0 +1,105 @@
%PDF-1.7
1 0 obj
<< >>
endobj
2 0 obj
<< /Length 3 0 R >>
stream
/DeviceRGB CS
/DeviceRGB cs
q
1.000000 0.000000 -0.000000 1.000000 4.000000 2.834961 cm
0.000000 0.000000 0.000000 scn
8.591907 21.668686 m
9.414594 22.328781 10.585405 22.328781 11.408092 21.668686 c
19.158089 15.450356 l
19.690319 15.023312 19.999994 14.377806 19.999994 13.695429 c
19.999994 2.415045 l
19.999994 1.172405 18.992638 0.165045 17.749996 0.165045 c
14.750000 0.165045 l
13.507360 0.165045 12.500000 1.172403 12.500000 2.415045 c
12.500000 8.415037 l
12.500000 8.829250 12.164213 9.165037 11.750000 9.165037 c
8.250000 9.165037 l
7.835786 9.165037 7.500000 8.829250 7.500000 8.415037 c
7.500000 2.415045 l
7.500000 1.172403 6.492640 0.165045 5.250000 0.165045 c
2.250000 0.165045 l
1.007360 0.165045 0.000000 1.172401 0.000000 2.415043 c
0.000000 13.695428 l
0.000000 14.377805 0.309674 15.023312 0.841907 15.450356 c
8.591907 21.668686 l
h
10.469363 20.498734 m
10.195135 20.718765 9.804865 20.718765 9.530635 20.498734 c
1.780635 14.280403 l
1.603225 14.138056 1.500000 13.922887 1.500000 13.695428 c
1.500000 2.415043 l
1.500000 2.000832 1.835786 1.665045 2.250000 1.665045 c
5.250000 1.665045 l
5.664214 1.665045 6.000000 2.000832 6.000000 2.415045 c
6.000000 8.415037 l
6.000000 9.657678 7.007360 10.665037 8.250000 10.665037 c
11.750000 10.665037 l
12.992640 10.665037 14.000000 9.657678 14.000000 8.415037 c
14.000000 2.415045 l
14.000000 2.000832 14.335787 1.665045 14.750000 1.665045 c
17.749996 1.665045 l
18.164207 1.665045 18.499994 2.000830 18.499994 2.415045 c
18.499994 13.695429 l
18.499994 13.922888 18.396770 14.138056 18.219358 14.280403 c
10.469363 20.498734 l
h
f
n
Q
endstream
endobj
3 0 obj
1604
endobj
4 0 obj
<< /Annots []
/Type /Page
/MediaBox [ 0.000000 0.000000 28.000000 28.000000 ]
/Resources 1 0 R
/Contents 2 0 R
/Parent 5 0 R
>>
endobj
5 0 obj
<< /Kids [ 4 0 R ]
/Count 1
/Type /Pages
>>
endobj
6 0 obj
<< /Pages 5 0 R
/Type /Catalog
>>
endobj
xref
0 7
0000000000 65535 f
0000000010 00000 n
0000000034 00000 n
0000001694 00000 n
0000001717 00000 n
0000001890 00000 n
0000001964 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 6 0 R
/Size 7
>>
startxref
2023
%%EOF

View File

@ -0,0 +1,15 @@
{
"images" : [
{
"filename" : "Search-Fill.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true
}
}

View File

@ -0,0 +1,83 @@
%PDF-1.7
1 0 obj
<< >>
endobj
2 0 obj
<< /Length 3 0 R >>
stream
/DeviceRGB CS
/DeviceRGB cs
q
1.000000 0.000000 -0.000000 1.000000 2.000000 1.855835 cm
0.000000 0.000000 0.000000 scn
9.500000 24.144165 m
14.746705 24.144165 19.000000 19.890869 19.000000 14.644165 c
19.000000 12.562231 18.330292 10.636717 17.194551 9.071299 c
23.560659 2.704824 l
24.146446 2.119038 24.146446 1.169292 23.560659 0.583506 c
23.011484 0.034330 22.142424 0.000008 21.553263 0.480536 c
21.439341 0.583506 l
15.072866 6.949614 l
13.507448 5.813873 11.581934 5.144165 9.500000 5.144165 c
4.253295 5.144165 0.000000 9.397460 0.000000 14.644165 c
0.000000 19.890869 4.253295 24.144165 9.500000 24.144165 c
h
9.500000 21.144165 m
5.910149 21.144165 3.000000 18.234016 3.000000 14.644165 c
3.000000 11.054314 5.910149 8.144165 9.500000 8.144165 c
13.089851 8.144165 16.000000 11.054314 16.000000 14.644165 c
16.000000 18.234016 13.089851 21.144165 9.500000 21.144165 c
h
f
n
Q
endstream
endobj
3 0 obj
887
endobj
4 0 obj
<< /Annots []
/Type /Page
/MediaBox [ 0.000000 0.000000 28.000000 28.000000 ]
/Resources 1 0 R
/Contents 2 0 R
/Parent 5 0 R
>>
endobj
5 0 obj
<< /Kids [ 4 0 R ]
/Count 1
/Type /Pages
>>
endobj
6 0 obj
<< /Pages 5 0 R
/Type /Catalog
>>
endobj
xref
0 7
0000000000 65535 f
0000000010 00000 n
0000000034 00000 n
0000000977 00000 n
0000000999 00000 n
0000001172 00000 n
0000001246 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 6 0 R
/Size 7
>>
startxref
1305
%%EOF

View File

@ -0,0 +1,15 @@
{
"images" : [
{
"filename" : "Search.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true
}
}

View File

@ -0,0 +1,83 @@
%PDF-1.7
1 0 obj
<< >>
endobj
2 0 obj
<< /Length 3 0 R >>
stream
/DeviceRGB CS
/DeviceRGB cs
q
1.000000 0.000000 -0.000000 1.000000 2.750000 2.679199 cm
0.000000 0.000000 0.000000 scn
8.750000 22.570801 m
13.582491 22.570801 17.500000 18.653292 17.500000 13.820801 c
17.500000 11.674633 16.727327 9.708933 15.444990 8.186705 c
22.280331 1.351131 l
22.573223 1.058239 22.573223 0.583363 22.280331 0.290470 c
22.014065 0.024204 21.597401 -0.000004 21.303789 0.217852 c
21.219669 0.290470 l
14.384096 7.125811 l
12.861868 5.843473 10.896168 5.070801 8.750000 5.070801 c
3.917509 5.070801 0.000000 8.988310 0.000000 13.820801 c
0.000000 18.653292 3.917509 22.570801 8.750000 22.570801 c
h
8.750000 21.070801 m
4.745935 21.070801 1.500000 17.824865 1.500000 13.820801 c
1.500000 9.816736 4.745935 6.570801 8.750000 6.570801 c
12.754065 6.570801 16.000000 9.816736 16.000000 13.820801 c
16.000000 17.824865 12.754065 21.070801 8.750000 21.070801 c
h
f
n
Q
endstream
endobj
3 0 obj
885
endobj
4 0 obj
<< /Annots []
/Type /Page
/MediaBox [ 0.000000 0.000000 28.000000 28.000000 ]
/Resources 1 0 R
/Contents 2 0 R
/Parent 5 0 R
>>
endobj
5 0 obj
<< /Kids [ 4 0 R ]
/Count 1
/Type /Pages
>>
endobj
6 0 obj
<< /Pages 5 0 R
/Type /Catalog
>>
endobj
xref
0 7
0000000000 65535 f
0000000010 00000 n
0000000034 00000 n
0000000975 00000 n
0000000997 00000 n
0000001170 00000 n
0000001244 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 6 0 R
/Size 7
>>
startxref
1303
%%EOF

View File

@ -0,0 +1,15 @@
{
"images" : [
{
"filename" : "square.and.pencil.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true
}
}

View File

@ -0,0 +1,93 @@
%PDF-1.7
1 0 obj
<< >>
endobj
2 0 obj
<< /Length 3 0 R >>
stream
/DeviceRGB CS
/DeviceRGB cs
q
1.000000 0.000000 -0.000000 1.000000 3.000000 2.926788 cm
0.000000 0.000000 0.000000 scn
18.780287 17.792883 m
19.073179 18.085777 19.073177 18.560650 18.780285 18.853542 c
18.487391 19.146435 18.012516 19.146435 17.719624 18.853540 c
7.719669 8.853540 l
7.250000 7.323212 l
8.780332 7.792883 l
18.780287 17.792883 l
h
3.249999 18.073212 m
1.455072 18.073212 0.000000 16.618137 0.000000 14.823212 c
0.000000 3.323212 l
0.000000 1.528286 1.455075 0.073212 3.250000 0.073212 c
14.750000 0.073212 l
16.544926 0.073212 18.000000 1.528286 18.000000 3.323212 c
18.000000 11.323212 l
18.000000 11.737425 17.664213 12.073212 17.250000 12.073212 c
16.835787 12.073212 16.500000 11.737425 16.500000 11.323212 c
16.500000 3.323212 l
16.500000 2.356712 15.716498 1.573212 14.750000 1.573212 c
3.250000 1.573212 l
2.283502 1.573212 1.500000 2.356712 1.500000 3.323212 c
1.500000 14.823212 l
1.500000 15.789711 2.283501 16.573212 3.249999 16.573212 c
11.249994 16.573212 l
11.664207 16.573212 11.999994 16.908998 11.999994 17.323212 c
11.999994 17.737425 11.664207 18.073212 11.249994 18.073212 c
3.249999 18.073212 l
h
f
n
Q
endstream
endobj
3 0 obj
1142
endobj
4 0 obj
<< /Annots []
/Type /Page
/MediaBox [ 0.000000 0.000000 24.000000 24.000000 ]
/Resources 1 0 R
/Contents 2 0 R
/Parent 5 0 R
>>
endobj
5 0 obj
<< /Kids [ 4 0 R ]
/Count 1
/Type /Pages
>>
endobj
6 0 obj
<< /Pages 5 0 R
/Type /Catalog
>>
endobj
xref
0 7
0000000000 65535 f
0000000010 00000 n
0000000034 00000 n
0000001232 00000 n
0000001255 00000 n
0000001428 00000 n
0000001502 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 6 0 R
/Size 7
>>
startxref
1561
%%EOF

View File

@ -24,6 +24,7 @@ public enum Asset {
public enum Arrow {
public static let `repeat` = ImageAsset(name: "Arrow/repeat")
public static let repeatSmall = ImageAsset(name: "Arrow/repeat.small")
public static let squareAndArrowUp = ImageAsset(name: "Arrow/square.and.arrow.up")
}
public enum Asset {
public static let email = ImageAsset(name: "Asset/email")
@ -99,6 +100,16 @@ public enum Asset {
public static let faceSmilingAdaptive = ImageAsset(name: "Human/face.smiling.adaptive")
}
public enum ObjectsAndTools {
public static let bellBadgeFill = ImageAsset(name: "ObjectsAndTools/bell.badge.fill")
public static let bellBadge = ImageAsset(name: "ObjectsAndTools/bell.badge")
public static let bellFill = ImageAsset(name: "ObjectsAndTools/bell.fill")
public static let bell = ImageAsset(name: "ObjectsAndTools/bell")
public static let gear = ImageAsset(name: "ObjectsAndTools/gear")
public static let houseFill = ImageAsset(name: "ObjectsAndTools/house.fill")
public static let house = ImageAsset(name: "ObjectsAndTools/house")
public static let magnifyingglassFill = ImageAsset(name: "ObjectsAndTools/magnifyingglass.fill")
public static let magnifyingglass = ImageAsset(name: "ObjectsAndTools/magnifyingglass")
public static let squareAndPencil = ImageAsset(name: "ObjectsAndTools/square.and.pencil")
public static let starFill = ImageAsset(name: "ObjectsAndTools/star.fill")
public static let star = ImageAsset(name: "ObjectsAndTools/star")
}

View File

@ -0,0 +1,18 @@
//
// UIImage.swift
//
//
// Created by MainasuK on 2022-5-6.
//
import UIKit
extension UIImage {
public func resized(size: CGSize) -> UIImage {
return UIGraphicsImageRenderer(size: size).image { context in
self.draw(in: CGRect(origin: .zero, size: size))
}
}
}

View File

@ -15,8 +15,8 @@
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>1.4.0</string>
<string>1.4.1</string>
<key>CFBundleVersion</key>
<string>121</string>
<string>126</string>
</dict>
</plist>

View File

@ -15,8 +15,8 @@
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>1.4.0</string>
<string>1.4.1</string>
<key>CFBundleVersion</key>
<string>121</string>
<string>126</string>
</dict>
</plist>

View File

@ -17,9 +17,9 @@
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>1.4.0</string>
<string>1.4.1</string>
<key>CFBundleVersion</key>
<string>121</string>
<string>126</string>
<key>NSExtension</key>
<dict>
<key>NSExtensionPointIdentifier</key>

View File

@ -17,9 +17,9 @@
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>1.4.0</string>
<string>1.4.1</string>
<key>CFBundleVersion</key>
<string>121</string>
<string>126</string>
<key>NSExtension</key>
<dict>
<key>NSExtensionAttributes</key>

View File

@ -21,7 +21,7 @@ echo "${PODS_ROOT}/SwiftGen/bin/swiftgen"
if [[ -f "${PODS_ROOT}/SwiftGen/bin/swiftgen" ]] then
"${PODS_ROOT}/SwiftGen/bin/swiftgen"
else
echo "Run 'pod install' or update your CocoaPods installation."
echo "Run 'bundle exec pod install' or update your CocoaPods installation."
fi
#task 4 clean temp file