├── .github └── FUNDING.yml ├── .gitignore ├── .swiftlint.yml ├── Dolphin.ipa ├── Dolphin.xcodeproj ├── project.pbxproj └── xcshareddata │ └── xcschemes │ ├── Dolphin.xcscheme │ ├── DolphinTests.xcscheme │ └── DolphinUITests.xcscheme ├── Dolphin ├── Application │ ├── AppDelegate.swift │ └── Application.swift ├── Common │ ├── BarButtonItem.swift │ ├── Button.swift │ ├── ImageView.swift │ ├── Label.swift │ ├── NavigationController.swift │ ├── PickerView.swift │ ├── ScrollView.swift │ ├── SearchBar.swift │ ├── SegmentedControl.swift │ ├── SlideImageView.swift │ ├── SplitViewController.swift │ ├── StackView.swift │ ├── Switch.swift │ ├── Table View Cells │ │ ├── DefaultTableViewCell.swift │ │ ├── DefaultTableViewCellViewModel.swift │ │ ├── TableViewCell.swift │ │ └── TableViewCellViewModel.swift │ ├── TableView.swift │ ├── TableViewController.swift │ ├── TextField.swift │ ├── Toolbar.swift │ ├── View.swift │ ├── ViewController.swift │ └── ViewModelType.swift ├── Configs │ └── Configs.swift ├── DependencyInjection │ ├── DIContainer.swift │ └── DependencyAssemblers │ │ └── AppAssembly.swift ├── Entity │ ├── BaseEntity.swift │ ├── CommonEntity.swift │ ├── DolphinUser.swift │ ├── Message.swift │ ├── TokenEnhancer.swift │ ├── TreeEntity.swift │ └── User.swift ├── Extensions │ ├── CATransform3D │ │ ├── CATransform3D+Dolphin.swift │ │ └── Degree.swift │ ├── Foundation │ │ └── Foundation+Dolphin.swift │ ├── RxSwift │ │ ├── KafkaRefresh+Rx.swift │ │ ├── Kingfisher+Rx.swift │ │ ├── Observable+Logging.swift │ │ └── Observable+Operation.swift │ ├── UIColor │ │ └── UIColor+Dolphin.swift │ ├── UIFont │ │ └── UIFont+Dolphin.swift │ ├── UIImage │ │ └── UIImage+Dolphin.swift │ └── UIView │ │ ├── UIView+Borders.swift │ │ └── UIView+Dolphin.swift ├── Info.plist ├── Managers │ ├── AuthManager.swift │ ├── LibsManager.swift │ ├── LogManager.swift │ ├── Reachability.swift │ ├── ThemeManager.swift │ └── WhatsNewManager.swift ├── Modules │ ├── Home │ │ ├── Cells │ │ │ ├── HomeCell.swift │ │ │ ├── HomeCell.xib │ │ │ └── HomeCellViewModel.swift │ │ ├── HomeSection.swift │ │ ├── HomeViewController.swift │ │ └── HomeViewModel.swift │ ├── Language │ │ ├── LanguageCell.swift │ │ ├── LanguageCell.xib │ │ ├── LanguageCellViewModel.swift │ │ ├── LanguageViewController.swift │ │ └── LanguageViewModel.swift │ ├── Login │ │ ├── Animation │ │ │ ├── CritterAnimatable.swift │ │ │ ├── CritterAssets.swift │ │ │ ├── CritterView.swift │ │ │ └── Parts │ │ │ │ ├── Body.swift │ │ │ │ ├── Head.swift │ │ │ │ ├── LeftArm.swift │ │ │ │ ├── LeftEar.swift │ │ │ │ ├── LeftEarMask.swift │ │ │ │ ├── LeftEye.swift │ │ │ │ ├── Mouth.swift │ │ │ │ ├── Muzzle.swift │ │ │ │ ├── Nose.swift │ │ │ │ ├── RightArm.swift │ │ │ │ ├── RightEar.swift │ │ │ │ ├── RightEarMask.swift │ │ │ │ └── RightEye.swift │ │ ├── LoginViewController.swift │ │ └── LoginViewModel.swift │ ├── Main │ │ ├── Base.lproj │ │ │ ├── LaunchScreen.storyboard │ │ │ └── Main.storyboard │ │ ├── HomeTabBarViewController.swift │ │ ├── HomeTabBarViewModel.swift │ │ ├── InitialSplitViewController.swift │ │ ├── MainViewController.swift │ │ └── Workbench │ │ │ ├── WorkbenchViewController.swift │ │ │ └── WorkbenchViewModel.swift │ ├── Message │ │ ├── Cells │ │ │ ├── MessageCell.swift │ │ │ ├── MessageCell.xib │ │ │ └── MessageCellViewModel.swift │ │ ├── MessageViewController.swift │ │ └── MessageViewModel.swift │ ├── Theme │ │ ├── ThemeCell.swift │ │ ├── ThemeCell.xib │ │ ├── ThemeCellViewModel.swift │ │ ├── ThemeViewController.swift │ │ └── ThemeViewModel.swift │ ├── User │ │ ├── Cells │ │ │ ├── UserCell.swift │ │ │ ├── UserCell.xib │ │ │ ├── UserCellViewModel.swift │ │ │ ├── UserSwitchCell.swift │ │ │ ├── UserSwitchCell.xib │ │ │ └── UserSwitchCellViewModel.swift │ │ ├── UserSection.swift │ │ ├── UserViewController.swift │ │ ├── UserViewModel.swift │ │ └── View │ │ │ └── UserHeaderView.swift │ └── Workbench │ │ ├── WorkbenchViewController.swift │ │ └── WorkbenchViewModel.swift ├── Resources │ ├── 2048.jpeg │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── dolphin 1024px.png │ │ │ ├── dolphin 120px 1.png │ │ │ ├── dolphin 120px.png │ │ │ ├── dolphin 152px.png │ │ │ ├── dolphin 167px.png │ │ │ ├── dolphin 180px.png │ │ │ ├── dolphin 20px.png │ │ │ ├── dolphin 29px.png │ │ │ ├── dolphin 40px 1.png │ │ │ ├── dolphin 40px 2.png │ │ │ ├── dolphin 40px.png │ │ │ ├── dolphin 58px 1.png │ │ │ ├── dolphin 58px.png │ │ │ ├── dolphin 60px.png │ │ │ ├── dolphin 76px.png │ │ │ ├── dolphin 80px 1.png │ │ │ ├── dolphin 80px.png │ │ │ └── dolphin 87px.png │ │ ├── Contents.json │ │ ├── image_no_result.imageset │ │ │ ├── Contents.json │ │ │ └── image_no_result.pdf │ │ └── launch_image.imageset │ │ │ ├── Contents.json │ │ │ └── launch_image.pdf │ ├── Icons.xcassets │ │ ├── Contents.json │ │ ├── icon_button_star.imageset │ │ │ ├── Contents.json │ │ │ └── icon_button_star.pdf │ │ ├── icon_button_tom.imageset │ │ │ ├── Contents.json │ │ │ └── tom.pdf │ │ ├── icon_button_unstar.imageset │ │ │ ├── Contents.json │ │ │ └── icon_button_unstar.pdf │ │ ├── icon_button_user_plus.imageset │ │ │ ├── Contents.json │ │ │ └── icon_button_user_plus.pdf │ │ ├── icon_button_user_x.imageset │ │ │ ├── Contents.json │ │ │ └── icon_button_user_x.pdf │ │ ├── icon_cell_acknowledgements.imageset │ │ │ ├── Contents.json │ │ │ └── icon_cell_acknowledgements.pdf │ │ ├── icon_cell_badge_collaborator.imageset │ │ │ ├── Contents.json │ │ │ └── icon_cell_badge_collaborator.pdf │ │ ├── icon_cell_badge_search.imageset │ │ │ ├── Contents.json │ │ │ └── icon_cell_badge_search.pdf │ │ ├── icon_cell_badge_star.imageset │ │ │ ├── Contents.json │ │ │ └── icon_cell_badge_star.pdf │ │ ├── icon_cell_badge_tag.imageset │ │ │ ├── Contents.json │ │ │ └── icon_cell_badge_tag.pdf │ │ ├── icon_cell_badge_user.imageset │ │ │ ├── Contents.json │ │ │ └── icon_cell_badge_user.pdf │ │ ├── icon_cell_check.imageset │ │ │ ├── Contents.json │ │ │ └── icon_cell_check.pdf │ │ ├── icon_cell_cloc.imageset │ │ │ ├── Contents.json │ │ │ └── icon_cell_cloc.pdf │ │ ├── icon_cell_company.imageset │ │ │ ├── Contents.json │ │ │ └── icon_cell_company.pdf │ │ ├── icon_cell_contact_no_image.imageset │ │ │ ├── Contents.json │ │ │ └── icon_cell_contact_no_image.pdf │ │ ├── icon_cell_created.imageset │ │ │ ├── Contents.json │ │ │ └── icon_cell_created.pdf │ │ ├── icon_cell_dir.imageset │ │ │ ├── Contents.json │ │ │ └── icon_cell_dir.pdf │ │ ├── icon_cell_disclosure.imageset │ │ │ ├── Contents.json │ │ │ └── icon_cell_disclosure.pdf │ │ ├── icon_cell_events.imageset │ │ │ ├── Contents.json │ │ │ └── icon_cell_events.pdf │ │ ├── icon_cell_file.imageset │ │ │ ├── Contents.json │ │ │ └── icon_cell_file.pdf │ │ ├── icon_cell_frown.imageset │ │ │ ├── Contents.json │ │ │ └── icon_cell_frown.pdf │ │ ├── icon_cell_issues.imageset │ │ │ ├── Contents.json │ │ │ └── icon_cell_issues.pdf │ │ ├── icon_cell_language.imageset │ │ │ ├── Contents.json │ │ │ └── icon_cell_language.pdf │ │ ├── icon_cell_link.imageset │ │ │ ├── Contents.json │ │ │ └── icon_cell_link.pdf │ │ ├── icon_cell_logout.imageset │ │ │ ├── Contents.json │ │ │ └── icon_cell_logout.pdf │ │ ├── icon_cell_night_mode.imageset │ │ │ ├── Contents.json │ │ │ └── icon_cell_night_mode.pdf │ │ ├── icon_cell_profile_summary.imageset │ │ │ ├── Contents.json │ │ │ └── icon_cell_profile_summary.pdf │ │ ├── icon_cell_readme.imageset │ │ │ ├── Contents.json │ │ │ └── icon_cell_readme.pdf │ │ ├── icon_cell_releases.imageset │ │ │ ├── Contents.json │ │ │ └── icon_cell_releases.pdf │ │ ├── icon_cell_remove.imageset │ │ │ ├── Contents.json │ │ │ └── icon_cell_remove.pdf │ │ ├── icon_cell_size.imageset │ │ │ ├── Contents.json │ │ │ └── icon_cell_size.pdf │ │ ├── icon_cell_smile.imageset │ │ │ ├── Contents.json │ │ │ └── icon_cell_smile.pdf │ │ ├── icon_cell_source.imageset │ │ │ ├── Contents.json │ │ │ └── icon_cell_source.pdf │ │ ├── icon_cell_star.imageset │ │ │ ├── Contents.json │ │ │ └── icon_cell_star.pdf │ │ ├── icon_cell_stars_history.imageset │ │ │ ├── Contents.json │ │ │ └── icon_cell_stars_history.pdf │ │ ├── icon_cell_submodule.imageset │ │ │ ├── Contents.json │ │ │ └── icon_cell_submodule.pdf │ │ ├── icon_cell_theme.imageset │ │ │ ├── Contents.json │ │ │ └── icon_cell_theme.pdf │ │ ├── icon_cell_updated.imageset │ │ │ ├── Contents.json │ │ │ └── icon_cell_updated.pdf │ │ ├── icon_cell_whats_new.imageset │ │ │ ├── Contents.json │ │ │ └── icon_cell_whats_new.pdf │ │ ├── icon_login_arm.imageset │ │ │ ├── Contents.json │ │ │ └── arm.pdf │ │ ├── icon_login_body.imageset │ │ │ ├── Contents.json │ │ │ └── body.pdf │ │ ├── icon_login_ear.imageset │ │ │ ├── Contents.json │ │ │ └── ear.pdf │ │ ├── icon_login_eye.imageset │ │ │ ├── Contents.json │ │ │ └── eye.pdf │ │ ├── icon_login_eye_doe.imageset │ │ │ ├── Contents.json │ │ │ └── eye-doe.pdf │ │ ├── icon_login_head.imageset │ │ │ ├── Contents.json │ │ │ └── face.pdf │ │ ├── icon_login_mouth_circle.imageset │ │ │ ├── Contents.json │ │ │ └── mouth-circle.pdf │ │ ├── icon_login_mouth_closed.imageset │ │ │ ├── Contents.json │ │ │ └── mouth-closed.pdf │ │ ├── icon_login_mouth_full.imageset │ │ │ ├── Contents.json │ │ │ └── mouth-open.pdf │ │ ├── icon_login_mouth_half.imageset │ │ │ ├── Contents.json │ │ │ └── mouth-half.pdf │ │ ├── icon_login_mouth_muzzle.imageset │ │ │ ├── Contents.json │ │ │ └── muzzle.pdf │ │ ├── icon_login_mouth_nose.imageset │ │ │ ├── Contents.json │ │ │ └── nose.pdf │ │ ├── icon_login_mouth_smile.imageset │ │ │ ├── Contents.json │ │ │ └── mouth-smile.pdf │ │ ├── icon_login_password_hide.imageset │ │ │ ├── Contents.json │ │ │ └── password-hide.pdf │ │ ├── icon_login_password_show.imageset │ │ │ ├── Contents.json │ │ │ └── password-show.pdf │ │ ├── icon_login_qq.imageset │ │ │ ├── Contents.json │ │ │ └── QQ.pdf │ │ ├── icon_login_wechat.imageset │ │ │ ├── Contents.json │ │ │ └── WeChat.pdf │ │ ├── icon_navigation_back.imageset │ │ │ ├── Contents.json │ │ │ └── icon_navigation_back.pdf │ │ ├── icon_navigation_close.imageset │ │ │ ├── Contents.json │ │ │ └── icon_navigation_close.pdf │ │ ├── icon_navigation_forward.imageset │ │ │ ├── Contents.json │ │ │ └── icon_navigation_forward.pdf │ │ ├── icon_navigation_history.imageset │ │ │ ├── Contents.json │ │ │ └── icon_navigation_history.pdf │ │ ├── icon_navigation_language.imageset │ │ │ ├── Contents.json │ │ │ └── icon_navigation_language.pdf │ │ ├── icon_navigation_refresh.imageset │ │ │ ├── Contents.json │ │ │ └── icon_navigation_refresh.pdf │ │ ├── icon_navigation_stop.imageset │ │ │ ├── Contents.json │ │ │ └── icon_navigation_stop.pdf │ │ ├── icon_navigation_theme.imageset │ │ │ ├── Contents.json │ │ │ └── icon_navigation_theme.pdf │ │ ├── icon_navigation_web.imageset │ │ │ ├── Contents.json │ │ │ └── icon_navigation_web.pdf │ │ ├── icon_oa_button.imageset │ │ │ ├── Contents.json │ │ │ └── icon_oa_button.pdf │ │ ├── icon_oa_button1.imageset │ │ │ ├── Contents.json │ │ │ └── leave.svg │ │ ├── icon_oa_button2.imageset │ │ │ ├── Contents.json │ │ │ └── overtime.svg │ │ ├── icon_oa_button3.imageset │ │ │ ├── Contents.json │ │ │ └── travel.svg │ │ ├── icon_oa_button4.imageset │ │ │ ├── Contents.json │ │ │ └── resignation.svg │ │ ├── icon_oa_slideImage1.imageset │ │ │ ├── 1.svg │ │ │ └── Contents.json │ │ ├── icon_oa_slideImage2.imageset │ │ │ ├── 2.svg │ │ │ └── Contents.json │ │ ├── icon_oa_slideImage3.imageset │ │ │ ├── 3.svg │ │ │ └── Contents.json │ │ ├── icon_oa_slideImage4.imageset │ │ │ ├── 4.svg │ │ │ └── Contents.json │ │ ├── icon_oa_slideImage5.imageset │ │ │ ├── 5.svg │ │ │ └── Contents.json │ │ ├── icon_oa_slideImage6.imageset │ │ │ ├── 6.svg │ │ │ └── Contents.json │ │ ├── icon_oa_slideImage7.imageset │ │ │ ├── 7.svg │ │ │ └── Contents.json │ │ ├── icon_tabbar_activity.imageset │ │ │ ├── Contents.json │ │ │ └── icon_tabbar_activity.pdf │ │ ├── icon_tabbar_home.imageset │ │ │ ├── Contents.json │ │ │ └── home.pdf │ │ ├── icon_tabbar_login.imageset │ │ │ ├── Contents.json │ │ │ └── icon_tabbar_login.pdf │ │ ├── icon_tabbar_news.imageset │ │ │ ├── Contents.json │ │ │ └── icon_tabbar_news.pdf │ │ ├── icon_tabbar_profile.imageset │ │ │ ├── Contents.json │ │ │ └── icon_tabbar_profile.pdf │ │ ├── icon_tabbar_search.imageset │ │ │ ├── Contents.json │ │ │ └── icon_tabbar_search.pdf │ │ ├── icon_tabbar_settings.imageset │ │ │ ├── Contents.json │ │ │ └── icon_tabbar_settings.pdf │ │ ├── icon_tabbar_workbench.imageset │ │ │ ├── Contents.json │ │ │ └── workbench.pdf │ │ ├── icon_toast_error.imageset │ │ │ ├── Contents.json │ │ │ └── icon_toast_error.pdf │ │ ├── icon_toast_success.imageset │ │ │ ├── Contents.json │ │ │ └── icon_toast_success.pdf │ │ ├── icon_toast_warning.imageset │ │ │ ├── Contents.json │ │ │ └── icon_toast_warning.pdf │ │ ├── icon_user_tom.imageset │ │ │ ├── Contents.json │ │ │ └── tom@2x.pdf │ │ ├── icon_whatsnew_color.imageset │ │ │ ├── Contents.json │ │ │ └── color.pdf │ │ ├── icon_whatsnew_ioc.imageset │ │ │ ├── Contents.json │ │ │ └── ioc.pdf │ │ ├── icon_whatsnew_ios.imageset │ │ │ ├── Contents.json │ │ │ └── ios.pdf │ │ └── icon_whatsnew_mvvm.imageset │ │ │ ├── Contents.json │ │ │ └── mvvm.pdf │ ├── en.lproj │ │ └── Localizable.strings │ ├── hy.lproj │ │ └── Localizable.strings │ ├── it.lproj │ │ └── Localizable.strings │ ├── main.gif │ ├── ru.lproj │ │ └── Localizable.strings │ ├── voice.mp3 │ ├── zh-Hans.lproj │ │ └── Localizable.strings │ └── zh-Hant.lproj │ │ └── Localizable.strings └── Utils │ ├── CommonUtil │ ├── ArrayUtil.swift │ ├── PermissionUtil.swift │ └── StrUtil.swift │ ├── Networking │ ├── Api │ │ └── ResultResponse.swift │ ├── ApiTarget.swift │ ├── Exception │ │ └── ResponseException.swift │ ├── HttpRequest.swift │ └── Networking.swift │ └── RxActivityIndicator │ └── ActivityIndicator.swift ├── DolphinTests ├── DolphinTests.swift ├── Info.plist ├── Models │ └── UserTests.swift └── Modules │ └── User │ └── UserViewModelTests.swift ├── DolphinUITests ├── DolphinUITests.swift ├── Info.plist └── SnapshotHelper.swift ├── Gemfile ├── Gemfile.lock ├── LICENSE ├── Podfile ├── Podfile.lock └── README.md /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | custom: ['https://godolphinx.org/sponsors/index.html'] -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # 排除构建生成目录 2 | build/ 3 | DerivedData/ 4 | 5 | # 排除生成的构建文件 6 | *.pbxuser 7 | !default.pbxuser 8 | *.mode1v3 9 | !default.mode1v3 10 | *.mode2v3 11 | !default.mode2v3 12 | *.perspectivev3 13 | !default.perspectivev3 14 | xcuserdata/ 15 | 16 | # 排除其他 17 | *.moved-aside 18 | *.xcuserstate 19 | 20 | # 排除Obj-C/Swift文件 21 | *.hmap 22 | *.dSYM.zip 23 | *.dSYM 24 | 25 | # 排除游乐场文件 26 | timeline.xctimeline 27 | playground.xcworkspace 28 | 29 | # 排除SwiftPackageManager工具生成目录 30 | Packages/ 31 | .build/ 32 | 33 | # 排除CocoaPods工具生成目录 34 | Pods/ 35 | *.xcworkspace 36 | 37 | # 排除Carthage工具生成目录 38 | Carthage/Checkouts 39 | Carthage/Build 40 | Cartfile.resolved 41 | 42 | # 排除fastlane自动构建工具生成目录 43 | fastlane/report.xml 44 | fastlane/Preview.html 45 | fastlane/screenshots/**/*.png 46 | fastlane/screenshots/screenshots.html 47 | fastlane/test_output 48 | 49 | # AppCode 50 | .idea/ 51 | 52 | # R.swift 53 | *.generated.swift 54 | 55 | ### macOS ### 56 | # General 57 | .DS_Store 58 | .AppleDouble 59 | .LSOverride 60 | 61 | # 缩略图 62 | Icon 63 | 64 | # Thumbnails 65 | ._* 66 | 67 | # 可能出现在卷根目录中的文件 68 | .DocumentRevisions-V100 69 | .fseventsd 70 | .Spotlight-V100 71 | .TemporaryItems 72 | .Trashes 73 | .VolumeIcon.icns 74 | .com.apple.timemachine.donotpresent 75 | 76 | # 可能在远程AFP共享上创建的目录 77 | .AppleDB 78 | .AppleDesktop 79 | Network Trash Folder 80 | Temporary Items 81 | .apdisk 82 | 83 | -------------------------------------------------------------------------------- /.swiftlint.yml: -------------------------------------------------------------------------------- 1 | # swiftlint规范检查配置 2 | # 配置参考文档: 3 | # https://realm.github.io/SwiftLint/rule-directory.html 4 | # https://github.com/realm/SwiftLint/blob/main/README_CN.md 5 | # @author: wangxiang4 6 | # @create: 2022/12/3 7 | 8 | # 执行时排除掉的规则 9 | disabled_rules: 10 | - missing_docs 11 | - unused_closure_parameter 12 | - cyclomatic_complexity 13 | - inclusive_language 14 | - trailing_whitespace 15 | - comment_spacing 16 | - unused_capture_list 17 | - identifier_name 18 | - force_cast 19 | 20 | # 一些规则仅仅是可选的 21 | opt_in_rules: 22 | # 可以通过执行如下指令来查找所有可用的规则: 23 | # swiftlint rules 24 | 25 | # 执行 linting 时包含的路径。如果出现这个 `--path` 会被忽略 26 | included: 27 | - Dolphin 28 | - DolphinTests 29 | - DolphinUITests 30 | 31 | # 执行 linting 时忽略的路径。优先级比 `included` 更高 32 | excluded: 33 | - Pods 34 | - Dolphin/Resources/R.generated.swift 35 | 36 | # 可配置的规则可以通过这个配置文件来自定义 37 | # 二进制规则可以设置他们的严格程度 38 | force_cast: warning # 隐式 39 | force_try: 40 | severity: warning # 显式 41 | 42 | # 同时有警告和错误等级的规则,可以只设置它的警告等级 43 | # 隐式 44 | line_length: 300 45 | 46 | function_body_length: 47 | - 300 # warning 48 | - 400 # error 49 | 50 | function_parameter_count: 51 | - 10 # warning 52 | - 15 # error 53 | 54 | large_tuple: 55 | - 6 # warning 56 | - 12 # error 57 | 58 | # 可以通过一个数组同时进行隐式设置 59 | type_body_length: 60 | - 300 # warning 61 | - 400 # error 62 | 63 | # 或者也可以同时进行显式设置 64 | file_length: 65 | warning: 1000 66 | error: 2000 67 | 68 | # 命名规则可以设置最小长度和最大程度的警告/错误 69 | # 此外它们也可以设置排除在外的名字 70 | type_name: 71 | min_length: 4 # 只是警告 72 | max_length: # 警告和错误 73 | warning: 40 74 | error: 50 75 | excluded: # 排除某个名字 76 | - T 77 | - E 78 | 79 | # 命名规则可以设置最小长度和最大程度的警告/错误 80 | # 此外它们也可以设置排除在外的名字 81 | identifier_name: 82 | min_length: # 只是警告 83 | error: 3 # 警告和错误 84 | excluded: # 排除某个名字 85 | - vc 86 | - id 87 | - in 88 | - kf 89 | - x 90 | - y 91 | -------------------------------------------------------------------------------- /Dolphin.ipa: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin.ipa -------------------------------------------------------------------------------- /Dolphin/Application/Application.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 初始启动界面 3 | // Created by wangxiang4 on 2022/11/27. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import SwiftUI 8 | 9 | final class Application: NSObject { 10 | 11 | // 首个ui窗口对象:提供绘画支持给屏幕 12 | var window: UIWindow? 13 | 14 | // 初始化首次场景 15 | func presentInitialScreen(in window: UIWindow?) { 16 | guard let window = window else { return } 17 | self.window = window 18 | 19 | if !StrUtil.isTrimEmpty((DIContainer.shared.resolve() as AuthManager).tokenEnhancer?.access_token) { 20 | // 呈现首页标签栏场景 21 | DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { [weak self] in 22 | let homeTabBarVC: HomeTabBarViewController = HomeTabBarViewController(viewModel: HomeTabBarViewModel()) 23 | let initialSplitVC: InitialSplitViewController = InitialSplitViewController(viewModel: nil) 24 | let navigationC = NavigationController(rootViewController: initialSplitVC) 25 | let splitVC = SplitViewController() 26 | splitVC.viewControllers = [homeTabBarVC, navigationC] 27 | UIView.transition(with: window, duration: 3.5, options: .transitionCurlUp, animations: { 28 | window.rootViewController = splitVC 29 | }, completion: nil) 30 | } 31 | return 32 | } 33 | 34 | // 呈现登录场景 35 | DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { [weak self] in 36 | UIView.transition(with: window, duration: 3.5, options: .transitionCurlDown, animations: { 37 | window.rootViewController = LoginViewController(viewModel: LoginViewModel()) 38 | }, completion: nil) 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Dolphin/Common/BarButtonItem.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 导航后退按钮视图rx-ui数据绑定,初始化默认配置 3 | // Created by wangxiang4 on 2022/11/27. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import SwiftUI 8 | 9 | class BarButtonItem: UIBarButtonItem { 10 | 11 | override init() { 12 | super.init() 13 | makeUI() 14 | } 15 | 16 | required public init?(coder aDecoder: NSCoder) { 17 | super.init(coder: aDecoder) 18 | makeUI() 19 | } 20 | 21 | // 渲染ui与数据绑定 22 | func makeUI() { 23 | // todo: 24 | 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /Dolphin/Common/Button.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 按钮视图rx-ui数据绑定,初始化默认配置 3 | // Created by wangxiang4 on 2022/11/27. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import SwiftUI 8 | 9 | public class Button: UIButton { 10 | 11 | override init(frame: CGRect) { 12 | super.init(frame: frame) 13 | makeUI() 14 | } 15 | 16 | required public init?(coder aDecoder: NSCoder) { 17 | super.init(coder: aDecoder) 18 | makeUI() 19 | } 20 | 21 | // 渲染ui与数据绑定 22 | func makeUI() { 23 | 24 | // rx主题绑定 25 | theme.backgroundImage(from: themeService.attribute { $0.secondary }, for: .normal) 26 | theme.backgroundImage(from: themeService.attribute { $0.secondary.withAlphaComponent(0.9) }, for: .selected) 27 | theme.backgroundImage(from: themeService.attribute { $0.secondary.withAlphaComponent(0.6) }, for: .disabled) 28 | 29 | // 初始化默认配置 30 | layer.masksToBounds = true 31 | titleLabel?.lineBreakMode = .byWordWrapping 32 | cornerRadius = Configs.BaseComponentDimensions.cornerRadius 33 | snp.makeConstraints { (make) in 34 | make.height.equalTo(Configs.BaseComponentDimensions.buttonHeight) 35 | } 36 | setNeedsDisplay() 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /Dolphin/Common/ImageView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 图片视图rx-ui数据绑定,初始化默认配置 3 | // Created by wangxiang4 on 2022/11/27. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import SwiftUI 8 | 9 | class ImageView: UIImageView { 10 | 11 | override init(frame: CGRect) { 12 | super.init(frame: frame) 13 | makeUI() 14 | } 15 | 16 | override init(image: UIImage?) { 17 | super.init(image: image) 18 | makeUI() 19 | } 20 | 21 | override init(image: UIImage?, highlightedImage: UIImage?) { 22 | super.init(image: image, highlightedImage: highlightedImage) 23 | makeUI() 24 | } 25 | 26 | required public init?(coder aDecoder: NSCoder) { 27 | super.init(coder: aDecoder) 28 | makeUI() 29 | } 30 | 31 | // 渲染ui与数据绑定 32 | func makeUI() { 33 | tintColor = .primary() 34 | layer.masksToBounds = true 35 | contentMode = .center 36 | setNeedsDisplay() 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /Dolphin/Common/Label.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 标题视图rx-ui数据绑定,初始化默认配置 3 | // Created by wangxiang4 on 2022/11/27. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import UIKit 8 | 9 | class Label: UILabel { 10 | 11 | var textInsets = UIEdgeInsets.zero { 12 | didSet { invalidateIntrinsicContentSize() } 13 | } 14 | 15 | override init(frame: CGRect) { 16 | super.init(frame: frame) 17 | makeUI() 18 | } 19 | 20 | required public init?(coder aDecoder: NSCoder) { 21 | super.init(coder: aDecoder) 22 | makeUI() 23 | } 24 | 25 | // 渲染ui与数据绑定 26 | func makeUI() { 27 | layer.masksToBounds = true 28 | numberOfLines = 1 29 | setNeedsDisplay() 30 | } 31 | } 32 | 33 | extension Label { 34 | 35 | override func textRect(forBounds bounds: CGRect, limitedToNumberOfLines numberOfLines: Int) -> CGRect { 36 | let insetRect = bounds.inset(by: textInsets) 37 | let textRect = super.textRect(forBounds: insetRect, limitedToNumberOfLines: numberOfLines) 38 | let invertedInsets = UIEdgeInsets(top: -textInsets.top, 39 | left: -textInsets.left, 40 | bottom: -textInsets.bottom, 41 | right: -textInsets.right) 42 | return textRect.inset(by: invertedInsets) 43 | } 44 | 45 | override func drawText(in rect: CGRect) { 46 | super.drawText(in: rect.inset(by: textInsets)) 47 | } 48 | 49 | var leftTextInset: CGFloat { 50 | get { return textInsets.left } 51 | set { textInsets.left = newValue } 52 | } 53 | 54 | var rightTextInset: CGFloat { 55 | get { return textInsets.right } 56 | set { textInsets.right = newValue } 57 | } 58 | 59 | var topTextInset: CGFloat { 60 | get { return textInsets.top } 61 | set { textInsets.top = newValue } 62 | } 63 | 64 | var bottomTextInset: CGFloat { 65 | get { return textInsets.bottom } 66 | set { textInsets.bottom = newValue } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /Dolphin/Common/NavigationController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 导航栏控制器数据绑定,初始化默认配置 3 | // Created by wangxiang4 on 2022/11/27. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import UIKit 8 | 9 | class NavigationController: UINavigationController { 10 | 11 | override var preferredStatusBarStyle: UIStatusBarStyle { 12 | return globalStatusBarStyle.value 13 | } 14 | 15 | override func viewDidLoad() { 16 | super.viewDidLoad() 17 | hero.isEnabled = true 18 | // 初始化数据绑定 19 | hero.modalAnimationType = .autoReverse(presenting: .fade) 20 | hero.navigationAnimationType = .autoReverse(presenting: .slide(direction: .left)) 21 | 22 | navigationBar.backIndicatorImage = R.image.icon_navigation_back() 23 | navigationBar.backIndicatorTransitionMaskImage = R.image.icon_navigation_back() 24 | 25 | navigationBar.theme.tintColor = themeService.attribute { $0.secondary } 26 | navigationBar.theme.barTintColor = themeService.attribute { $0.primaryDark } 27 | navigationBar.theme.titleTextAttributes = themeService.attribute { [NSAttributedString.Key.foregroundColor: $0.text] } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Dolphin/Common/PickerView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 下拉滚动选择视图rx-ui数据绑定,初始化默认配置 3 | // Created by wangxiang4 on 2022/11/27. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import SwiftUI 8 | 9 | class PickerView: UIPickerView { 10 | 11 | init () { 12 | super.init(frame: CGRect()) 13 | } 14 | 15 | override init(frame: CGRect) { 16 | super.init(frame: frame) 17 | makeUI() 18 | } 19 | 20 | required init?(coder aDecoder: NSCoder) { 21 | super.init(coder: aDecoder) 22 | makeUI() 23 | } 24 | 25 | // 渲染ui与数据绑定 26 | func makeUI() { 27 | // todo: 28 | 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Dolphin/Common/ScrollView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 滚动条视图rx-ui数据绑定,初始化默认配置 3 | // Created by wangxiang4 on 2022/11/27. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import SwiftUI 8 | 9 | class ScrollView: UIScrollView { 10 | 11 | override init(frame: CGRect) { 12 | super.init(frame: frame) 13 | makeUI() 14 | } 15 | 16 | required public init?(coder aDecoder: NSCoder) { 17 | super.init(coder: aDecoder) 18 | makeUI() 19 | } 20 | 21 | // 渲染ui与数据绑定 22 | func makeUI() { 23 | // todo: 24 | 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /Dolphin/Common/SearchBar.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 搜索栏视图rx-ui数据绑定,初始化默认配置 3 | // Created by wangxiang4 on 2022/11/27. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import SwiftUI 8 | 9 | class SearchBar: UISearchBar { 10 | 11 | override init(frame: CGRect) { 12 | super.init(frame: frame) 13 | makeUI() 14 | } 15 | 16 | required public init?(coder aDecoder: NSCoder) { 17 | super.init(coder: aDecoder) 18 | makeUI() 19 | } 20 | 21 | // 渲染ui与数据绑定 22 | func makeUI() { 23 | placeholder = R.string.localizable.commonSearch.key.localized() 24 | isTranslucent = false 25 | searchBarStyle = .minimal 26 | 27 | theme.tintColor = themeService.attribute { $0.secondary } 28 | theme.barTintColor = themeService.attribute { $0.primaryDark } 29 | 30 | if let textField = textField { 31 | textField.theme.textColor = themeService.attribute { $0.text } 32 | textField.theme.keyboardAppearance = themeService.attribute { $0.keyboardAppearance } 33 | } 34 | 35 | rx.textDidBeginEditing.asObservable().subscribe(onNext: { [weak self] () in 36 | self?.setShowsCancelButton(true, animated: true) 37 | }).disposed(by: rx.disposeBag) 38 | 39 | rx.textDidEndEditing.asObservable().subscribe(onNext: { [weak self] () in 40 | self?.setShowsCancelButton(false, animated: true) 41 | }).disposed(by: rx.disposeBag) 42 | 43 | rx.cancelButtonClicked.asObservable().subscribe(onNext: { [weak self] () in 44 | self?.resignFirstResponder() 45 | }).disposed(by: rx.disposeBag) 46 | 47 | rx.searchButtonClicked.asObservable().subscribe(onNext: { [weak self] () in 48 | self?.resignFirstResponder() 49 | }).disposed(by: rx.disposeBag) 50 | 51 | setNeedsDisplay() 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Dolphin/Common/SlideImageView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 幻灯片图片预览视图 3 | // Created by wangxiang4 on 2022/12/20. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import ImageSlideshow 8 | 9 | class SlideImageView: ImageSlideshow { 10 | 11 | override init(frame: CGRect) { 12 | super.init(frame: frame) 13 | makeUI() 14 | } 15 | 16 | required public init?(coder aDecoder: NSCoder) { 17 | super.init(coder: aDecoder) 18 | makeUI() 19 | } 20 | 21 | func makeUI() { 22 | contentScaleMode = .scaleAspectFit 23 | contentMode = .scaleAspectFill 24 | theme.backgroundColor = themeService.attribute { $0.primaryDark } 25 | borderWidth = Configs.BaseComponentDimensions.borderWidth 26 | borderColor = .white 27 | theme.tintColor = themeService.attribute { $0.secondary } 28 | slideshowInterval = 3 29 | activityIndicator = DefaultActivityIndicator(style: .white, color: UIColor.secondary()) 30 | } 31 | 32 | func setSources(sources: [URL]) { 33 | setImageInputs(sources.map({ (url) -> KingfisherSource in 34 | KingfisherSource(url: url) 35 | })) 36 | } 37 | 38 | func present(from controller: UIViewController) { 39 | self.presentFullScreenController(from: controller) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Dolphin/Common/SplitViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 平板分割视图控制器数据绑定,初始化默认配置 3 | // Created by wangxiang4 on 2022/11/27. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import SwiftUI 8 | 9 | class SplitViewController: UISplitViewController { 10 | 11 | override var preferredStatusBarStyle: UIStatusBarStyle { 12 | return globalStatusBarStyle.value 13 | } 14 | 15 | override func viewDidLoad() { 16 | super.viewDidLoad() 17 | 18 | // 初始化数据绑定 19 | delegate = self 20 | preferredDisplayMode = .allVisible 21 | globalStatusBarStyle.mapToVoid().subscribe(onNext: { [weak self] () in 22 | self?.setNeedsStatusBarAppearanceUpdate() 23 | }).disposed(by: rx.disposeBag) 24 | } 25 | } 26 | 27 | extension SplitViewController: UISplitViewControllerDelegate { 28 | 29 | func splitViewController(_ splitViewController: UISplitViewController, collapseSecondary secondaryViewController: UIViewController, onto primaryViewController: UIViewController) -> Bool { 30 | return true 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Dolphin/Common/StackView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 堆栈布局视图rx-ui数据绑定,初始化默认配置 3 | // Created by wangxiang4 on 2022/11/27. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import SwiftUI 8 | class StackView: UIStackView { 9 | 10 | override init(frame: CGRect) { 11 | super.init(frame: frame) 12 | makeUI() 13 | } 14 | 15 | required init(coder aDecoder: NSCoder) { 16 | super.init(coder: aDecoder) 17 | makeUI() 18 | } 19 | 20 | // 渲染ui与数据绑定 21 | func makeUI() { 22 | spacing = inset 23 | axis = .vertical 24 | setNeedsDisplay() 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Dolphin/Common/Switch.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 开关视图rx-ui数据绑定,初始化默认配置 3 | // Created by wangxiang4 on 2022/11/27. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import UIKit 8 | 9 | class Switch: UISwitch { 10 | 11 | override init(frame: CGRect) { 12 | super.init(frame: frame) 13 | makeUI() 14 | } 15 | 16 | required public init?(coder aDecoder: NSCoder) { 17 | super.init(coder: aDecoder) 18 | makeUI() 19 | } 20 | 21 | // 渲染ui与数据绑定 22 | func makeUI() { 23 | self.theme.tintColor = themeService.attribute { $0.secondary } 24 | self.theme.onTintColor = themeService.attribute { $0.secondary } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Dolphin/Common/Table View Cells/DefaultTableViewCellViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 默认表格列视图模型 3 | // Created by wangxiang4 on 2022/11/27. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | 8 | import Foundation 9 | import RxSwift 10 | import RxCocoa 11 | 12 | class DefaultTableViewCellViewModel: TableViewCellViewModel { 13 | 14 | // 标题 15 | let title = BehaviorRelay(value: nil) 16 | 17 | // 第一行描述 18 | let detail = BehaviorRelay(value: nil) 19 | 20 | // 第二行描述 21 | let secondDetail = BehaviorRelay(value: nil) 22 | 23 | // 第三行自定义Label组件视图 24 | let attributedDetail = BehaviorRelay(value: nil) 25 | 26 | // 左侧图片 27 | let image = BehaviorRelay(value: nil) 28 | 29 | // 左侧图片url地址 30 | let imageUrl = BehaviorRelay(value: nil) 31 | 32 | // 徽章图片 33 | let badge = BehaviorRelay(value: nil) 34 | 35 | // 徽章颜色 36 | let badgeColor = BehaviorRelay(value: nil) 37 | 38 | // 隐藏右箭头 39 | let hidesDisclosure = BehaviorRelay(value: false) 40 | 41 | } 42 | -------------------------------------------------------------------------------- /Dolphin/Common/Table View Cells/TableViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 基础表格列视图rx-ui数据绑定,初始化默认配置 3 | // Created by wangxiang4 on 2022/11/27. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import SwiftUI 8 | import RxSwift 9 | import RxCocoa 10 | 11 | class TableViewCell: UITableViewCell { 12 | 13 | required init?(coder aDecoder: NSCoder) { 14 | super.init(coder: aDecoder) 15 | makeUI() 16 | } 17 | 18 | // 给每个列创建单独的垃圾袋,这里表格列是属性共享的不可见区域列会拿出来重用,会导致列事件点击无效,rx冲突无法销毁 19 | var cellDisposeBag = DisposeBag() 20 | 21 | // 渲染ui与数据绑定 22 | func makeUI() { 23 | layer.masksToBounds = true 24 | selectionStyle = .none 25 | backgroundColor = .clear 26 | theme.selectionColor = themeService.attribute { $0.primary } 27 | containerView.theme.backgroundColor = themeService.attribute { $0.primary } 28 | setNeedsDisplay() 29 | } 30 | 31 | // 选中时显示的颜色 32 | var selectionColor: UIColor? { 33 | didSet { setSelected(isSelected, animated: true) } 34 | } 35 | 36 | // 创建约束布局 37 | lazy var containerView: View = { 38 | let view = View() 39 | view.backgroundColor = .clear 40 | view.cornerRadius = Configs.BaseComponentDimensions.cornerRadius 41 | self.addSubview(view) 42 | view.snp.makeConstraints({ (make) in 43 | make.edges.equalToSuperview().inset(UIEdgeInsets(horizontal: self.inset, vertical: self.inset/2)) 44 | }) 45 | return view 46 | }() 47 | 48 | // 创建栈堆布局 49 | lazy var stackView: StackView = { 50 | let subviews: [UIView] = [] 51 | let view = StackView(arrangedSubviews: subviews) 52 | view.axis = .horizontal 53 | view.alignment = .center 54 | self.containerView.addSubview(view) 55 | view.snp.makeConstraints({ (make) in 56 | make.edges.equalToSuperview().inset(inset/2) 57 | }) 58 | return view 59 | }() 60 | 61 | // 行选中事件 62 | override func setSelected(_ selected: Bool, animated: Bool) { 63 | super.setSelected(selected, animated: animated) 64 | backgroundColor = selected ? selectionColor : .clear 65 | } 66 | 67 | // VC视图模型绑定 68 | func bind(to viewModel: TableViewCellViewModel) { 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /Dolphin/Common/Table View Cells/TableViewCellViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 基础表格列视图模型 3 | // Created by wangxiang4 on 2022/11/27. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import RxSwift 8 | import RxCocoa 9 | 10 | class TableViewCellViewModel: NSObject { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /Dolphin/Common/TableView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 表格视图rx-ui数据绑定,初始化默认配置 3 | // Created by wangxiang4 on 2022/11/27. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | import SwiftUI 7 | 8 | class TableView: UITableView { 9 | 10 | init () { 11 | super.init(frame: CGRect(), style: .grouped) 12 | } 13 | 14 | override init(frame: CGRect, style: UITableView.Style) { 15 | super.init(frame: frame, style: style) 16 | makeUI() 17 | } 18 | 19 | required init?(coder aDecoder: NSCoder) { 20 | super.init(coder: aDecoder) 21 | makeUI() 22 | } 23 | 24 | // 渲染ui与数据绑定 25 | func makeUI() { 26 | rowHeight = UITableView.automaticDimension 27 | estimatedRowHeight = 50 28 | sectionHeaderHeight = 40 29 | backgroundColor = .clear 30 | cellLayoutMarginsFollowReadableWidth = false 31 | keyboardDismissMode = .onDrag 32 | separatorColor = .clear 33 | separatorInset = UIEdgeInsets(top: 0, left: inset, bottom: 0, right: 0) 34 | 35 | let uiView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: 1)) 36 | uiView.snp.makeConstraints { (make) in make.height.equalTo(1) } 37 | tableHeaderView = uiView 38 | tableFooterView = UIView() 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Dolphin/Common/TextField.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 文本框视图rx-ui数据绑定,初始化默认配置 3 | // Created by wangxiang4 on 2022/11/27. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import SwiftUI 8 | 9 | class TextField: UITextField { 10 | 11 | override init(frame: CGRect) { 12 | super.init(frame: frame) 13 | makeUI() 14 | } 15 | 16 | required public init?(coder aDecoder: NSCoder) { 17 | super.init(coder: aDecoder) 18 | makeUI() 19 | } 20 | 21 | override var placeholder: String? { 22 | didSet { 23 | themeService.switch(themeService.type) 24 | } 25 | } 26 | 27 | // 渲染ui与数据绑定 28 | func makeUI() { 29 | theme.textColor = themeService.attribute { $0.text } 30 | theme.tintColor = themeService.attribute { $0.secondary } 31 | theme.placeholderColor = themeService.attribute { $0.textGray } 32 | theme.borderColor = themeService.attribute { $0.text } 33 | theme.keyboardAppearance = themeService.attribute { $0.keyboardAppearance } 34 | 35 | layer.masksToBounds = true 36 | borderWidth = Configs.BaseComponentDimensions.borderWidth 37 | cornerRadius = Configs.BaseComponentDimensions.cornerRadius 38 | snp.makeConstraints { (make) in 39 | make.height.equalTo(Configs.BaseComponentDimensions.textFieldHeight) 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Dolphin/Common/Toolbar.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 工具栏视图rx-ui数据绑定,初始化默认配置 3 | // Created by wangxiang4 on 2022/11/27. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import SwiftUI 8 | class Toolbar: UIToolbar { 9 | 10 | override init(frame: CGRect) { 11 | super.init(frame: frame) 12 | makeUI() 13 | } 14 | 15 | required public init?(coder aDecoder: NSCoder) { 16 | super.init(coder: aDecoder) 17 | makeUI() 18 | } 19 | 20 | // 渲染ui与数据绑定 21 | func makeUI() { 22 | isTranslucent = false 23 | theme.barStyle = themeService.attribute { $0.barStyle } 24 | theme.barTintColor = themeService.attribute { $0.primaryDark } 25 | theme.tintColor = themeService.attribute { $0.secondary } 26 | snp.makeConstraints { (make) in 27 | make.height.equalTo(Configs.BaseComponentDimensions.tableRowHeight) 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Dolphin/Common/View.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 基础视图 3 | // Created by wangxiang4 on 2022/11/27. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import SwiftUI 8 | public class View: UIView { 9 | 10 | convenience init(width: CGFloat) { 11 | self.init(frame: CGRect(x: 0, y: 0, width: width, height: 0)) 12 | snp.makeConstraints { (make) in 13 | make.width.equalTo(width) 14 | } 15 | } 16 | 17 | convenience init(height: CGFloat) { 18 | self.init(frame: CGRect(x: 0, y: 0, width: 0, height: height)) 19 | snp.makeConstraints { (make) in 20 | make.height.equalTo(height) 21 | } 22 | } 23 | 24 | override init(frame: CGRect) { 25 | super.init(frame: frame) 26 | makeUI() 27 | } 28 | 29 | required public init?(coder aDecoder: NSCoder) { 30 | super.init(coder: aDecoder) 31 | makeUI() 32 | } 33 | 34 | func makeUI() { 35 | self.layer.masksToBounds = true 36 | setNeedsDisplay() 37 | } 38 | 39 | func getCenter() -> CGPoint { 40 | return convert(center, from: superview) 41 | } 42 | } 43 | 44 | extension UIView { 45 | 46 | var inset: CGFloat { 47 | return Configs.BaseComponentDimensions.inset 48 | } 49 | 50 | open func setPriority(_ priority: UILayoutPriority, for axis: NSLayoutConstraint.Axis) { 51 | self.setContentHuggingPriority(priority, for: axis) 52 | self.setContentCompressionResistancePriority(priority, for: axis) 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Dolphin/Common/ViewModelType.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 基础视图模型类型 3 | // Created by wangxiang4 on 2022/11/27. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import RxSwift 8 | import RxCocoa 9 | import ObjectMapper 10 | 11 | protocol ViewModelType { 12 | associatedtype Input 13 | associatedtype Output 14 | func transform(input: Input) -> Output 15 | } 16 | 17 | class ViewModel: NSObject { 18 | 19 | // 当前页码 20 | var PageCurrent = 1 21 | 22 | // 页面大小 23 | var PageSize = 10 24 | 25 | // 显示状态栏网络加载 26 | let loading = ActivityIndicator() 27 | 28 | // 显示头部刷新加载 29 | let headerLoading = ActivityIndicator() 30 | 31 | // 显示尾部刷新加载 32 | let footerLoading = ActivityIndicator() 33 | 34 | // 转换网络请错误 35 | let bindConverRequestError = PublishSubject() 36 | 37 | // 网络请求错误 38 | let requestError = PublishSubject() 39 | 40 | override init() { 41 | super.init() 42 | 43 | // 转换请求错误 44 | bindConverRequestError.asObservable().map { error -> ApiError? in 45 | 46 | // 响应错误 47 | var status: Int?, msg: String? 48 | 49 | // Alamofire原生实现请求手动抛异常 50 | if error is ApiError { 51 | let responseError = error as? ApiError 52 | status = responseError?.code 53 | msg = responseError?.errMessage 54 | 55 | // Moya扩展请求异常 56 | } else if error is MoyaError { 57 | let responseError = error as? MoyaError 58 | status = responseError?.response?.statusCode 59 | msg = responseError?.errorDescription 60 | } 61 | 62 | return ResponseException.getRequestError(status ?? -1, msg) 63 | 64 | }.filterNil().bind(to: requestError).disposed(by: rx.disposeBag) 65 | 66 | // 🧑‍💻打印请求错误输出 67 | requestError.subscribe(onNext: { (error) in 68 | logError("\(error)") 69 | }).disposed(by: rx.disposeBag) 70 | 71 | } 72 | 73 | deinit { 74 | logDebug("\(type(of: self)): 初始化完成!") 75 | logResourcesCount() 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /Dolphin/Configs/Configs.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 全局应用配置 3 | // Created by wangxiang4 on 2022/12/5. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import SwiftUI 8 | struct Configs { 9 | 10 | // APP配置 11 | struct App { 12 | static let baseUrl = "http://123.60.163.167:9999" 13 | static let gatewayAseEncodeSecret = "dolphin-platform" 14 | static let bundleIdentifier = Bundle.main.infoDictionary?["CFBundleIdentifier"] as? String ?? "Dolphin" 15 | } 16 | 17 | // 缓存键配置 18 | struct CacheKey { 19 | static let tokenEnhancerKey = "DOLPHIN_TOKEN_KEY" 20 | static let userInfoKey = "DOLPHIN_USER_INFO_KEY" 21 | static let firstLoadKey = "FIRST_LOAD_KEY" 22 | } 23 | 24 | // 基础组件尺寸配置 25 | struct BaseComponentDimensions { 26 | static let inset: CGFloat = 8 27 | static let tabBarHeight: CGFloat = 58 28 | static let toolBarHeight: CGFloat = 66 29 | static let navBarWithStatusBarHeight: CGFloat = 64 30 | static let cornerRadius: CGFloat = 5 31 | static let borderWidth: CGFloat = 1 32 | static let buttonHeight: CGFloat = 40 33 | static let textFieldHeight: CGFloat = 40 34 | static let tableRowHeight: CGFloat = 36 35 | static let segmentedControlHeight: CGFloat = 40 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /Dolphin/DependencyInjection/DIContainer.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 依赖注入管理容器 3 | // https://github.com/Swinject/Swinject/tree/master/Documentation 4 | // Created by wangxiang4 on 2022/12/5. 5 | // Copyright © 2022 dolphin-community. All rights reserved. 6 | // 7 | 8 | import Swinject 9 | 10 | final class DIContainer { 11 | 12 | static let shared = DIContainer() 13 | 14 | let container: Container = Container() 15 | let assembler: Assembler 16 | 17 | init() { 18 | // 初始化组装ioc对象 19 | assembler = Assembler( 20 | [ 21 | AppAssembly() 22 | ], 23 | container: container) 24 | } 25 | 26 | // 根据返回类型获取ioc实例 27 | func resolve() -> T { 28 | guard let resolvedType = container.resolve(T.self) else { 29 | fatalError() 30 | } 31 | return resolvedType 32 | } 33 | 34 | // 根据返回类型跟注册名称获取ioc实例 35 | func resolve(registrationName: String?) -> T { 36 | guard let resolvedType = container.resolve(T.self, name: registrationName) else { 37 | fatalError() 38 | } 39 | return resolvedType 40 | } 41 | 42 | // 根据返回类型传单个参 43 | func resolve(argument: Arg) -> T { 44 | guard let resolvedType = container.resolve(T.self, argument: argument) else { 45 | fatalError() 46 | } 47 | return resolvedType 48 | } 49 | 50 | // 根据返回类型传多个参 51 | func resolve(arguments arg1: Arg1, _ arg2: Arg2) -> T { 52 | guard let resolvedType = container.resolve(T.self, arguments: arg1, arg2) else { 53 | fatalError() 54 | } 55 | return resolvedType 56 | } 57 | 58 | // 根据返回类型跟注册名称传单个参 59 | func resolve(name: String?, argument: Arg) -> T { 60 | guard let resolvedType = container.resolve(T.self, name: name, argument: argument) else { 61 | fatalError() 62 | } 63 | return resolvedType 64 | } 65 | 66 | // 根据返回类型跟注册名称传多个参 67 | func resolve(name: String?, arguments arg1: Arg1, _ arg2: Arg2) -> T { 68 | guard let resolvedType = container.resolve(T.self, name: name, arguments: arg1, arg2) else { 69 | fatalError() 70 | } 71 | return resolvedType 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /Dolphin/DependencyInjection/DependencyAssemblers/AppAssembly.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 应用程序依赖注入装配 3 | // Created by wangxiang4 on 2022/12/5. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import Swinject 8 | 9 | final class AppAssembly: Assembly { 10 | 11 | func assemble(container: Container) { 12 | 13 | // 应用程序 14 | container.register(Application.self) { resolver in 15 | Application() 16 | }.inObjectScope(.container) 17 | 18 | // 应用程序委托 19 | container.register(AppDelegate.self) { resolver in 20 | AppDelegate() 21 | }.inObjectScope(.container) 22 | 23 | // 登录授权管理 24 | container.register(AuthManager.self) { resolver in 25 | AuthManager() 26 | }.inObjectScope(.container) 27 | 28 | // 第三方依赖库管理 29 | container.register(LibsManager.self) { resolver in 30 | LibsManager() 31 | }.inObjectScope(.container) 32 | 33 | // 程序新功能特性管理 34 | container.register(WhatsNewManager.self) { resolver in 35 | WhatsNewManager() 36 | }.inObjectScope(.container) 37 | 38 | // 网络请求 39 | container.register(HttpRequest.self) { resolver in 40 | HttpRequest() 41 | }.inObjectScope(.container) 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /Dolphin/Entity/BaseEntity.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 基础模型 3 | // Created by wangxiang4 on 2022/12/16. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import Foundation 8 | import ObjectMapper 9 | class BaseEntity: Mappable { 10 | 11 | /** 多租户ID */ 12 | var tenantId: String? 13 | 14 | /** 当前用户 */ 15 | var currentUser: DolphinUser? 16 | 17 | required init?(map: Map) {} 18 | init() {} 19 | 20 | func mapping(map: Map) { 21 | // todo: 转换处理 22 | tenantId <- map["tenantId"] 23 | currentUser <- map["currentUser"] 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /Dolphin/Entity/CommonEntity.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 通用模型 3 | // Created by wangxiang4 on 2022/12/16. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import Foundation 8 | import ObjectMapper 9 | class CommonEntity: BaseEntity { 10 | 11 | /** 创建id */ 12 | var createById: String? 13 | 14 | /** 创建者 */ 15 | var createByName: String? 16 | 17 | /** 创建时间 */ 18 | var createTime: String? 19 | 20 | /** 更新id */ 21 | var updateById: String? 22 | 23 | /** 更新者 */ 24 | var updateByName: String? 25 | 26 | /** 更新时间 */ 27 | var updateTime: String? 28 | 29 | /** 备注 */ 30 | var remarks: String? 31 | 32 | /** 删除标志(0代表存在 1代表删除)*/ 33 | var delFlag: String? 34 | 35 | required init?(map: Map) { super.init(map: map) } 36 | override init() { super.init() } 37 | 38 | override func mapping(map: Map) { 39 | super.mapping(map: map) 40 | // todo: 转换处理 41 | createById <- map["createById"] 42 | createByName <- map["createByName"] 43 | createTime <- map["createTime"] 44 | updateById <- map["updateById"] 45 | updateByName <- map["updateByName"] 46 | updateTime <- map["updateTime"] 47 | remarks <- map["remarks"] 48 | delFlag <- map["delFlag"] 49 | } 50 | 51 | } 52 | 53 | -------------------------------------------------------------------------------- /Dolphin/Entity/DolphinUser.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 扩展安全框架用户信息 3 | // Created by wangxiang4 on 2022/12/16. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import Foundation 8 | import ObjectMapper 9 | class DolphinUser: Mappable { 10 | 11 | /** 用户id */ 12 | var id: String? 13 | 14 | /** 用户名称 */ 15 | var username: String? 16 | 17 | /** 用户密码 */ 18 | var password: String? 19 | 20 | /** 部门ID */ 21 | var deptId: String? 22 | 23 | /** 用户手机号 */ 24 | var phone: String? 25 | 26 | /** 账户是否被冻结 */ 27 | var enabled: Bool? 28 | 29 | /** 多租户ID */ 30 | var tenantId: String? 31 | 32 | /** 用户按钮权限 */ 33 | var authorities: [[String: String]]? 34 | 35 | /** 帐户未锁定 */ 36 | var accountNonLocked: Bool? 37 | 38 | /** 帐户未过期 */ 39 | var accountNonExpired: Bool? 40 | 41 | /** 凭证未过期 */ 42 | var credentialsNonExpired: Bool? 43 | 44 | required init?(map: Map) {} 45 | init() {} 46 | 47 | func mapping(map: Map) { 48 | // todo: 转换处理 49 | id <- map["id"] 50 | username <- map["username"] 51 | password <- map["password"] 52 | deptId <- map["deptId"] 53 | phone <- map["phone"] 54 | enabled <- map["enabled"] 55 | tenantId <- map["tenantId"] 56 | authorities <- map["authorities"] 57 | accountNonLocked <- map["accountNonLocked"] 58 | accountNonExpired <- map["accountNonExpired"] 59 | credentialsNonExpired <- map["credentialsNonExpired"] 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /Dolphin/Entity/Message.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 通知消息实体类 3 | // Created by wangxiang4 on 2022/12/5. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import Foundation 8 | import ObjectMapper 9 | 10 | 11 | // xxx: 目前微服务那边消息模块没有数据,拿文件模块OSS文件模型做数据演示 12 | class OSSFile: CommonEntity { 13 | 14 | /** 15 | * 编号 16 | */ 17 | var id: String? 18 | 19 | /** 20 | * 文件名 21 | */ 22 | var fileName: String? 23 | 24 | /** 25 | * 容器名称 26 | */ 27 | var bucketName: String? 28 | 29 | /** 30 | * 原文件名 31 | */ 32 | var original: String? 33 | 34 | /** 35 | * 文件类型 36 | */ 37 | var type: String? 38 | 39 | /** 40 | * 文件大小 41 | */ 42 | var fileSize: Int64? 43 | 44 | required init?(map: Map) { super.init(map: map) } 45 | override init() { super.init() } 46 | 47 | override func mapping(map: Map) { 48 | super.mapping(map: map) 49 | 50 | id <- map["id"] 51 | fileName <- map["fileName"] 52 | bucketName <- map["bucketName"] 53 | original <- map["original"] 54 | type <- map["type"] 55 | fileSize <- map["fileSize"] 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Dolphin/Entity/TokenEnhancer.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 令牌增强输出对象 3 | // Created by wangxiang4 on 2022/12/5. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import Foundation 8 | import ObjectMapper 9 | struct TokenEnhancer: Mappable { 10 | 11 | /** 访问token */ 12 | var access_token: String? 13 | 14 | /** 客户端ID */ 15 | var clientId: String? 16 | 17 | /** 过期时间(毫秒为单位) */ 18 | var expires_in: Int? 19 | 20 | /** 证书字段 */ 21 | var license: String? 22 | 23 | /** 刷新token */ 24 | var refresh_token: String? 25 | 26 | /** 授权权限范围 */ 27 | var scope: String? 28 | 29 | /** token类型 */ 30 | var token_type: String? 31 | 32 | /** 用户信息 */ 33 | var user_info: DolphinUser? 34 | 35 | init?(map: Map) {} 36 | init() {} 37 | 38 | mutating func mapping(map: Map) { 39 | // todo: 转换处理 40 | access_token <- map["access_token"] 41 | clientId <- map["clientId"] 42 | expires_in <- map["expires_in"] 43 | license <- map["license"] 44 | refresh_token <- map["refresh_token"] 45 | scope <- map["scope"] 46 | token_type <- map["token_type"] 47 | user_info <- map["user_info"] 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /Dolphin/Entity/TreeEntity.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 树结构模型 3 | // Created by wangxiang4 on 2022/12/16. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import Foundation 8 | import ObjectMapper 9 | class TreeEntity: CommonEntity { 10 | 11 | /** 父级编号 **/ 12 | var parentId: String? 13 | 14 | /** 名称 */ 15 | var name: String? 16 | 17 | /** 排序 **/ 18 | var sort: Int? 19 | 20 | var children: [T] = [] 21 | 22 | required init?(map: Map) { super.init(map: map) } 23 | override init() { super.init() } 24 | 25 | override func mapping(map: Map) { 26 | super.mapping(map: map) 27 | // todo: 转换处理 28 | parentId <- map["parentId"] 29 | name <- map["name"] 30 | sort <- map["sort"] 31 | children <- map["children"] 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /Dolphin/Extensions/CATransform3D/CATransform3D+Dolphin.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 扩展核心动画CATransform3D视图变形 3 | // Created by wangxiang4 on 2022/12/5. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import SwiftUI 8 | private let defaultPerspective: CGFloat = -1.0 / 500 9 | 10 | extension CATransform3D { 11 | 12 | // 3D轴 13 | enum Axis { case x, y, z } 14 | 15 | static var identity: CATransform3D { 16 | return CATransform3DIdentity 17 | } 18 | 19 | // 设置旋转 20 | func rotate(_ axis: Axis, by degree: Degree) -> CATransform3D { 21 | let radians = degree.radians 22 | switch axis { 23 | case .x: 24 | return CATransform3DRotate(self, radians, 1, 0, 0) 25 | case .y: 26 | return CATransform3DRotate(self, radians, 0, 1, 0) 27 | case .z: 28 | return CATransform3DRotate(self, radians, 0, 0, 1) 29 | } 30 | } 31 | 32 | // 设置缩放 33 | func scale(_ axis: Axis, by scale: CGFloat) -> CATransform3D { 34 | switch axis { 35 | case .x: 36 | return CATransform3DScale(self, scale, 1, 1) 37 | case .y: 38 | return CATransform3DScale(self, 1, scale, 1) 39 | case .z: 40 | return CATransform3DScale(self, 1, 1, scale) 41 | } 42 | } 43 | 44 | // 设置平移 45 | func translate(_ axis: Axis, by value: CGFloat) -> CATransform3D { 46 | switch axis { 47 | case .x: 48 | return CATransform3DTranslate(self, value, 0, 0) 49 | case .y: 50 | return CATransform3DTranslate(self, 0, value, 0) 51 | case .z: 52 | return CATransform3DTranslate(self, 0, 0, value) 53 | } 54 | } 55 | 56 | // 设置角度 57 | func perspective(_ m34: CGFloat = defaultPerspective) -> CATransform3D { 58 | var transform = self 59 | transform.m34 = m34 60 | return transform 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /Dolphin/Extensions/CATransform3D/Degree.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 动画角度 3 | // Created by wangxiang4 on 2022/12/5. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import SwiftUI 8 | struct Degree { 9 | 10 | let value: Double 11 | 12 | var radians: CGFloat { 13 | return CGFloat(value * Double.pi / 180.0) 14 | } 15 | } 16 | 17 | // MARK: - 自定义减去角度度运算符 18 | prefix func -(degree: Degree) -> Degree { 19 | return Degree(value: -1 * degree.value) 20 | } 21 | 22 | // MARK: - Double 23 | extension Double { 24 | var degrees: Degree { 25 | return Degree(value: self) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Dolphin/Extensions/Foundation/Foundation+Dolphin.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 扩展基础库 3 | // Created by wangxiang4 on 2022/12/5. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import Foundation 8 | 9 | extension Int { 10 | 11 | func sizeFromKB() -> String { 12 | return (self*1024).sizeFromByte() 13 | } 14 | 15 | func sizeFromByte() -> String { 16 | return ByteCountFormatter.string(fromByteCount: Int64(self), countStyle: .file) 17 | } 18 | 19 | func kFormatted() -> String { 20 | let sign = ((self < 0) ? "-" : "" ) 21 | if self < 1000 { 22 | return "\(sign)\(self)" 23 | } 24 | let num = fabs(self.double) 25 | let exp: Int = Int(log10(num) / 3.0 ) 26 | let units: [String] = ["K", "M", "G", "T", "P", "E"] 27 | let roundedNum: Double = round(10 * num / pow(1000.0, Double(exp))) / 10 28 | return "\(sign)\(roundedNum)\(units[exp-1])" 29 | } 30 | } 31 | 32 | extension String { 33 | 34 | // 检查是否为空字符串 35 | var isBlank: Bool { 36 | // 扔掉空格和换行符 37 | let trimmedStr = self.trimmingCharacters(in: .whitespacesAndNewlines) 38 | return trimmedStr.isEmpty 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /Dolphin/Extensions/RxSwift/KafkaRefresh+Rx.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 扩展下拉刷新库 3 | // Created by wangxiang4 on 2022/12/5. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import Foundation 8 | import RxCocoa 9 | import RxSwift 10 | import KafkaRefresh 11 | 12 | extension Reactive where Base: KafkaRefreshControl { 13 | 14 | // 处理下拉刷新回调 15 | public var isAnimating: Binder { 16 | return Binder(self.base) { refreshControl, active in 17 | if active { 18 | // todo: 下拉刷新开始 19 | } else { 20 | // todo: 下拉刷新结束 21 | refreshControl.endRefreshing() 22 | } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Dolphin/Extensions/RxSwift/Kingfisher+Rx.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 扩展图片处理库 3 | // Created by wangxiang4 on 2022/12/5. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import SwiftUI 8 | import RxCocoa 9 | import RxSwift 10 | import Kingfisher 11 | 12 | extension Reactive where Base: UIImageView { 13 | 14 | public var imageURL: Binder { 15 | return self.imageURL(withPlaceholder: nil) 16 | } 17 | 18 | public func imageURL(withPlaceholder placeholderImage: UIImage?, options: KingfisherOptionsInfo? = []) -> Binder { 19 | return Binder(self.base, binding: { (imageView, url) in 20 | imageView.kf.setImage(with: url, 21 | placeholder: placeholderImage, 22 | options: options, 23 | progressBlock: nil, 24 | completionHandler: { (result) in }) 25 | }) 26 | } 27 | } 28 | 29 | extension ImageCache: ReactiveCompatible {} 30 | 31 | extension Reactive where Base: ImageCache { 32 | 33 | func retrieveCacheSize() -> Observable { 34 | return Single.create { single in 35 | self.base.calculateDiskStorageSize { (result) in 36 | do { 37 | single(.success(Int(try result.get()))) 38 | } catch { 39 | single(.failure(error)) 40 | } 41 | } 42 | return Disposables.create { } 43 | }.asObservable() 44 | } 45 | 46 | public func clearCache() -> Observable { 47 | return Single.create { single in 48 | self.base.clearMemoryCache() 49 | self.base.clearDiskCache(completion: { 50 | single(.success(())) 51 | }) 52 | return Disposables.create { } 53 | }.asObservable() 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Dolphin/Extensions/RxSwift/Observable+Logging.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 扩展可观测活动日志输出 3 | // Created by wangxiang4 on 2022/12/5. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import Foundation 8 | import RxSwift 9 | 10 | extension Observable { 11 | func logError(prefix: String = "Error: ") -> Observable { 12 | return self.do(onNext: nil, 13 | onError: { (error) in 14 | print("\(prefix)\(error)") 15 | }, 16 | onCompleted: nil, 17 | onSubscribe: nil, 18 | onDispose: nil) 19 | 20 | } 21 | 22 | func logServerError(message: String) -> Observable { 23 | return self.do(onNext: nil, 24 | onError: { (error) in 25 | print("\(message)") 26 | print("Error: \(error.localizedDescription). \n") 27 | }, 28 | onCompleted: nil, 29 | onSubscribe: nil, 30 | onDispose: nil) 31 | } 32 | 33 | func logNext() -> Observable { 34 | return self.do(onNext: { (element) in 35 | print("\(element)") 36 | }, 37 | onError: nil, 38 | onCompleted: nil, 39 | onSubscribe: nil, 40 | onDispose: nil) 41 | 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Dolphin/Extensions/UIColor/UIColor+Dolphin.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 扩展UI颜色组件 3 | // Created by wangxiang4 on 2022/12/5. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import SwiftUI 8 | 9 | extension UIColor { 10 | 11 | static func primary() -> UIColor { 12 | return themeService.type.associatedObject.primary 13 | } 14 | 15 | static func primaryDark() -> UIColor { 16 | return themeService.type.associatedObject.primaryDark 17 | } 18 | 19 | static func secondary() -> UIColor { 20 | return themeService.type.associatedObject.secondary 21 | } 22 | 23 | static func secondaryDark() -> UIColor { 24 | return themeService.type.associatedObject.secondaryDark 25 | } 26 | 27 | static func separator() -> UIColor { 28 | return themeService.type.associatedObject.separator 29 | } 30 | 31 | static func text() -> UIColor { 32 | return themeService.type.associatedObject.text 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Dolphin/Extensions/UIFont/UIFont+Dolphin.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 扩展UI字体组件 3 | // Created by wangxiang4 on 2022/12/5. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | 8 | import SwiftUI 9 | import Foundation 10 | 11 | extension UIFont { 12 | 13 | static func navigationTitleFont() -> UIFont { 14 | return UIFont.systemFont(ofSize: 17.0) 15 | } 16 | 17 | static func titleFont() -> UIFont { 18 | return UIFont.systemFont(ofSize: 17.0) 19 | } 20 | 21 | static func descriptionFont() -> UIFont { 22 | return UIFont.systemFont(ofSize: 14.0) 23 | } 24 | } 25 | 26 | extension UIFont { 27 | 28 | // 获取所以系统字体名称 29 | static func allSystemFontsNames() -> [String] { 30 | var fontsNames = [String]() 31 | let fontFamilies = UIFont.familyNames 32 | for fontFamily in fontFamilies { 33 | let fontsForFamily = UIFont.fontNames(forFamilyName: fontFamily) 34 | for fontName in fontsForFamily { 35 | fontsNames.append(fontName) 36 | } 37 | } 38 | return fontsNames 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Dolphin/Extensions/UIImage/UIImage+Dolphin.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 扩展UI图片组件 3 | // Created by wangxiang4 on 2022/12/5. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | 8 | import SwiftUI 9 | import Foundation 10 | 11 | extension UIImage { 12 | // 填充图片 13 | func filled(withColor color: UIColor) -> UIImage { 14 | UIGraphicsBeginImageContextWithOptions(size, false, scale) 15 | color.setFill() 16 | guard let context = UIGraphicsGetCurrentContext() else { return self } 17 | 18 | context.translateBy(x: 0, y: size.height) 19 | context.scaleBy(x: 1.0, y: -1.0) 20 | context.setBlendMode(CGBlendMode.normal) 21 | 22 | let rect = CGRect(x: 0, y: 0, width: size.width, height: size.height) 23 | guard let mask = cgImage else { return self } 24 | context.clip(to: rect, mask: mask) 25 | context.fill(rect) 26 | 27 | let newImage = UIGraphicsGetImageFromCurrentImageContext()! 28 | UIGraphicsEndImageContext() 29 | return newImage 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Dolphin/Extensions/UIView/UIView+Dolphin.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 扩展UI基础视图 3 | // Created by wangxiang4 on 2022/12/5. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import UIKit 8 | import Foundation 9 | 10 | extension UIView { 11 | 12 | // 制作圆角布局 13 | func makeRoundedCorners(_ radius: CGFloat) { 14 | layer.cornerRadius = radius 15 | layer.masksToBounds = true 16 | } 17 | 18 | // 制作圆角 19 | func makeRoundedCorners() { 20 | makeRoundedCorners(bounds.size.width / 2) 21 | } 22 | 23 | // 添加模糊视图 24 | func blur(style: UIBlurEffect.Style) { 25 | unBlur() 26 | let blurEffect = UIBlurEffect(style: style) 27 | let blurEffectView = UIVisualEffectView(effect: blurEffect) 28 | insertSubview(blurEffectView, at: 0) 29 | blurEffectView.snp.makeConstraints({ (make) in 30 | make.edges.equalToSuperview() 31 | }) 32 | } 33 | 34 | // 移除模糊视图 35 | func unBlur() { 36 | subviews.filter { (view) -> Bool in 37 | view as? UIVisualEffectView != nil 38 | }.forEach { (view) in 39 | view.removeFromSuperview() 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Dolphin/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleExecutable 6 | $(EXECUTABLE_NAME) 7 | CFBundleIdentifier 8 | $(PRODUCT_BUNDLE_IDENTIFIER) 9 | CFBundleInfoDictionaryVersion 10 | 1.0 11 | CFBundleName 12 | $(PRODUCT_NAME) 13 | CFBundlePackageType 14 | APPL 15 | CFBundleShortVersionString 16 | 1.0.0 17 | CFBundleURLTypes 18 | 19 | 20 | CFBundleTypeRole 21 | Editor 22 | CFBundleURLSchemes 23 | 24 | Dolphin 25 | 26 | 27 | 28 | CFBundleVersion 29 | 1 30 | LSRequiresIPhoneOS 31 | 32 | NSAppTransportSecurity 33 | 34 | NSAllowsArbitraryLoads 35 | 36 | 37 | NSCameraUsageDescription 38 | 海豚生态需要您的同意,才能访问联系人相机 39 | NSContactsUsageDescription 40 | 海豚生态需要您的同意,才能访问联系人 41 | NSPhotoLibraryUsageDescription 42 | 海豚生态需要您的同意,才能访问相册 43 | UILaunchStoryboardName 44 | LaunchScreen 45 | UIMainStoryboardFile 46 | Main 47 | UIRequiredDeviceCapabilities 48 | 49 | armv7 50 | 51 | UIStatusBarStyle 52 | UIStatusBarStyleDefault 53 | UISupportedInterfaceOrientations 54 | 55 | UIInterfaceOrientationPortrait 56 | 57 | UISupportedInterfaceOrientations~ipad 58 | 59 | UIInterfaceOrientationPortrait 60 | UIInterfaceOrientationPortraitUpsideDown 61 | UIInterfaceOrientationLandscapeLeft 62 | UIInterfaceOrientationLandscapeRight 63 | 64 | UIViewControllerBasedStatusBarAppearance 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /Dolphin/Managers/AuthManager.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 登录授权管理 3 | // https://github.com/kishikawakatsumi/KeychainAccess 4 | // Created by wangxiang4 on 2022/12/5. 5 | // Copyright © 2022 dolphin-community. All rights reserved. 6 | // 7 | import KeychainAccess 8 | import ObjectMapper 9 | import RxSwift 10 | import RxCocoa 11 | 12 | class AuthManager { 13 | 14 | fileprivate let keychain = Keychain(service: Configs.App.bundleIdentifier) 15 | 16 | // 令牌对象更改监听 17 | let tokenChanged = PublishSubject() 18 | 19 | var tokenEnhancer: TokenEnhancer? { 20 | get { 21 | guard let jsonString = keychain[Configs.CacheKey.tokenEnhancerKey] else { return nil } 22 | return Mapper().map(JSONString: jsonString) 23 | } 24 | set { 25 | if let tokenEnhancer = newValue, let jsonString = tokenEnhancer.toJSONString() { 26 | keychain[Configs.CacheKey.tokenEnhancerKey] = jsonString 27 | } else { 28 | keychain[Configs.CacheKey.tokenEnhancerKey] = nil 29 | } 30 | tokenChanged.onNext(newValue) 31 | } 32 | } 33 | 34 | // 设置令牌对象 35 | class func setTokenEnhancer(tokenEnhancer: TokenEnhancer) { 36 | let authManager: AuthManager = DIContainer.shared.resolve() 37 | authManager.tokenEnhancer = tokenEnhancer 38 | } 39 | 40 | // 移除令牌对象 41 | class func removeTokenEnhancer() { 42 | let authManager: AuthManager = DIContainer.shared.resolve() 43 | authManager.tokenEnhancer = nil 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /Dolphin/Managers/LogManager.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 日志管理 3 | // Created by wangxiang4 on 2022/12/5. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import CocoaLumberjack 8 | import RxSwift 9 | 10 | public func logDebug(_ message: @autoclosure () -> String) { 11 | DDLogDebug(message()) 12 | } 13 | 14 | public func logError(_ message: @autoclosure () -> String) { 15 | DDLogError(message()) 16 | } 17 | 18 | public func logInfo(_ message: @autoclosure () -> String) { 19 | DDLogInfo(message()) 20 | } 21 | 22 | public func logVerbose(_ message: @autoclosure () -> String) { 23 | DDLogVerbose(message()) 24 | } 25 | 26 | public func logWarn(_ message: @autoclosure () -> String) { 27 | DDLogWarn(message()) 28 | } 29 | 30 | public func logResourcesCount() { 31 | #if DEBUG 32 | logDebug("RxSwift resources count: \(RxSwift.Resources.total)") 33 | #endif 34 | } 35 | -------------------------------------------------------------------------------- /Dolphin/Managers/Reachability.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 网络连接状况管理 3 | // Created by wangxiang4 on 2022/12/5. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import RxSwift 8 | import Alamofire 9 | 10 | // 一个可观察的,当应用程序上线时完成(可能立即完成) 11 | func connectedToInternet() -> Observable { 12 | return ReachabilityManager.shared.reach 13 | } 14 | 15 | private class ReachabilityManager: NSObject { 16 | 17 | static let shared = ReachabilityManager() 18 | 19 | let reachSubject = ReplaySubject.create(bufferSize: 1) 20 | var reach: Observable { 21 | return reachSubject.asObservable() 22 | } 23 | 24 | override init() { 25 | super.init() 26 | NetworkReachabilityManager.default?.startListening(onUpdatePerforming: { (status) in 27 | switch status { 28 | case .notReachable: 29 | self.reachSubject.onNext(false) 30 | case .reachable: 31 | self.reachSubject.onNext(true) 32 | case .unknown: 33 | self.reachSubject.onNext(false) 34 | } 35 | }) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Dolphin/Modules/Home/Cells/HomeCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 主页表格自定义基础列视图 3 | // Created by wangxiang4 on 2022/11/29. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import SwiftUI 8 | class HomeCell: DefaultTableViewCell { 9 | 10 | override func makeUI() { 11 | super.makeUI() 12 | leftImageView.contentMode = .center 13 | leftImageView.cornerRadius = 0 14 | leftImageView.snp.updateConstraints { (make) in 15 | make.size.equalTo(30) 16 | } 17 | detailLabel.isHidden = true 18 | attributedDetailLabel.isHidden = true 19 | secondDetailLabel.textAlignment = .right 20 | textsStackView.axis = .horizontal 21 | textsStackView.distribution = .fillEqually 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Dolphin/Modules/Home/Cells/HomeCell.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /Dolphin/Modules/Home/Cells/HomeCellViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 主页表格自定义基础列视图模型 3 | // Created by wangxiang4 on 2022/11/29. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import RxSwift 8 | import RxCocoa 9 | class HomeCellViewModel: DefaultTableViewCellViewModel { 10 | 11 | init(with title: String, detail: String?, image: UIImage?, hidesDisclosure: Bool) { 12 | super.init() 13 | self.title.accept(title) 14 | self.secondDetail.accept(detail) 15 | self.image.accept(image) 16 | self.hidesDisclosure.accept(hidesDisclosure) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Dolphin/Modules/Home/HomeSection.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 渲染自定义表格列 3 | // Created by wangxiang4 on 2022/11/29. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import Foundation 8 | import RxDataSources 9 | 10 | enum HomeSection { 11 | case setting(title: String, items: [HomeSectionItem]) 12 | } 13 | 14 | enum HomeSectionItem { 15 | // 消息通知 16 | case notificationItem(viewModel: HomeCellViewModel) 17 | 18 | // 闪光灯通知 19 | case flashItem(viewModel: HomeCellViewModel) 20 | 21 | // 震动反馈 22 | case vibrationItem(viewModel: HomeCellViewModel) 23 | 24 | // 语音播报 25 | case voiceItem(viewModel: HomeCellViewModel) 26 | 27 | // 跳转软件设置 28 | case settingsItem(viewModel: HomeCellViewModel) 29 | 30 | // 打开照相机 31 | case cameraItem(viewModel: HomeCellViewModel) 32 | 33 | // 打开相册 34 | case albumItem(viewModel: HomeCellViewModel) 35 | } 36 | 37 | // 扩展类比较 38 | extension HomeSectionItem: IdentifiableType { 39 | typealias Identity = String 40 | var identity: Identity { 41 | switch self { 42 | case .notificationItem(let viewModel), 43 | .flashItem(let viewModel), 44 | .vibrationItem(let viewModel), 45 | .voiceItem(let viewModel), 46 | .settingsItem(let viewModel), 47 | .cameraItem(let viewModel), 48 | .albumItem(let viewModel): return viewModel.title.value ?? "" 49 | } 50 | } 51 | } 52 | 53 | extension HomeSectionItem: Equatable { 54 | static func == (lhs: HomeSectionItem, rhs: HomeSectionItem) -> Bool { 55 | return lhs.identity == rhs.identity 56 | } 57 | } 58 | 59 | // 扩展表格科目分类数据源 60 | extension HomeSection: AnimatableSectionModelType, IdentifiableType { 61 | typealias Item = HomeSectionItem 62 | typealias Identity = String 63 | var identity: Identity { return title } 64 | 65 | var title: String { 66 | switch self { 67 | case .setting(let title, _): return title 68 | } 69 | } 70 | 71 | var items: [HomeSectionItem] { 72 | switch self { 73 | case .setting(_, let items): return items.map {$0} 74 | } 75 | } 76 | 77 | init(original: HomeSection, items: [Item]) { 78 | switch original { 79 | case .setting(let title, let items): self = .setting(title: title, items: items) 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /Dolphin/Modules/Language/LanguageCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 设置国际化语言自定义基础列视图 3 | // Created by wangxiang4 on 2022/11/29. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import SwiftUI 8 | 9 | class LanguageCell: DefaultTableViewCell { 10 | 11 | override func makeUI() { 12 | super.makeUI() 13 | leftImageView.isHidden = true 14 | } 15 | 16 | override func setSelected(_ selected: Bool, animated: Bool) { 17 | super.setSelected(selected, animated: animated) 18 | // Configure the view for the selected state 19 | rightImageView.image = selected ? R.image.icon_cell_check()?.template : nil 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Dolphin/Modules/Language/LanguageCell.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Dolphin/Modules/Language/LanguageCellViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 设置国际化语言自定义基础列视图模型 3 | // Created by wangxiang4 on 2022/11/29. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import Foundation 8 | import RxSwift 9 | import RxCocoa 10 | 11 | class LanguageCellViewModel: DefaultTableViewCellViewModel { 12 | 13 | let language: String 14 | 15 | init(with language: String) { 16 | self.language = language 17 | super.init() 18 | title.accept(displayName(forLanguage: language)) 19 | } 20 | } 21 | 22 | func displayName(forLanguage language: String) -> String { 23 | let local = Locale(identifier: language) 24 | if let displayName = local.localizedString(forIdentifier: language) { 25 | return displayName.capitalized(with: local) 26 | } 27 | return String() 28 | } 29 | -------------------------------------------------------------------------------- /Dolphin/Modules/Language/LanguageViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 设置国际化语言视图控制器 3 | // Created by wangxiang4 on 2022/11/29. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import SwiftUI 8 | import RxSwift 9 | import RxCocoa 10 | import RxDataSources 11 | 12 | private let reuseIdentifier = R.reuseIdentifier.languageCell.identifier 13 | 14 | class LanguageViewController: TableViewController { 15 | 16 | lazy var saveButtonItem: BarButtonItem = { 17 | let view = BarButtonItem(title: "", style: .plain, target: self, action: nil) 18 | return view 19 | }() 20 | 21 | override func viewDidLoad() { 22 | super.viewDidLoad() 23 | } 24 | 25 | override func makeUI() { 26 | super.makeUI() 27 | 28 | languageChanged.subscribe(onNext: { [weak self] () in 29 | self?.navigationTitle = R.string.localizable.languageNavigationTitle.key.localized() 30 | self?.saveButtonItem.title = R.string.localizable.commonSave.key.localized() 31 | }).disposed(by: rx.disposeBag) 32 | 33 | navigationItem.rightBarButtonItem = saveButtonItem 34 | tableView.register(R.nib.languageCell) 35 | tableView.headRefreshControl = nil 36 | tableView.footRefreshControl = nil 37 | } 38 | 39 | override func bindViewModel() { 40 | super.bindViewModel() 41 | guard let viewModel = viewModel as? LanguageViewModel else { return } 42 | 43 | let refresh = Observable.of(Observable.just(()), languageChanged.asObservable()).merge() 44 | let input = LanguageViewModel.Input(trigger: refresh, 45 | saveTrigger: saveButtonItem.rx.tap.asDriver(), 46 | selection: tableView.rx.modelSelected(LanguageCellViewModel.self).asDriver()) 47 | let output = viewModel.transform(input: input) 48 | 49 | output.items.drive(tableView.rx.items(cellIdentifier: reuseIdentifier, cellType: LanguageCell.self)) { tableView, viewModel, cell in 50 | cell.bind(to: viewModel) 51 | }.disposed(by: rx.disposeBag) 52 | 53 | output.saved.drive(onNext: { [weak self] () in 54 | self?.navigationController?.dismiss(animated: true, completion: nil) 55 | }).disposed(by: rx.disposeBag) 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Dolphin/Modules/Language/LanguageViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 设置国际化语言视图模型 3 | // Created by wangxiang4 on 2022/11/29. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import Foundation 8 | import RxCocoa 9 | import RxSwift 10 | import Localize_Swift 11 | 12 | class LanguageViewModel: ViewModel, ViewModelType { 13 | 14 | struct Input { 15 | let trigger: Observable 16 | let saveTrigger: Driver 17 | let selection: Driver 18 | } 19 | 20 | struct Output { 21 | let items: Driver<[LanguageCellViewModel]> 22 | let saved: Driver 23 | } 24 | 25 | private var currentLanguage: BehaviorRelay 26 | 27 | override init() { 28 | currentLanguage = BehaviorRelay(value: Localize.currentLanguage()) 29 | } 30 | 31 | func transform(input: Input) -> Output { 32 | let elements = BehaviorRelay<[LanguageCellViewModel]>(value: []) 33 | 34 | input.trigger.map({ () -> [LanguageCellViewModel] in 35 | let languages = Localize.availableLanguages(true) 36 | return languages.map({ (language) -> LanguageCellViewModel in 37 | let viewModel = LanguageCellViewModel(with: language) 38 | return viewModel 39 | }) 40 | }).bind(to: elements).disposed(by: rx.disposeBag) 41 | 42 | let saved = input.saveTrigger.map { () -> Void in 43 | let language = self.currentLanguage.value 44 | Localize.setCurrentLanguage(language) 45 | } 46 | 47 | input.selection.drive(onNext: { (cellViewModel) in 48 | let language = cellViewModel.language 49 | self.currentLanguage.accept(language) 50 | }).disposed(by: rx.disposeBag) 51 | 52 | return Output(items: elements.asDriver(), saved: saved.asDriver(onErrorJustReturn: ())) 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Dolphin/Modules/Login/Animation/CritterAnimatable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 3D动画执行接口 3 | // Created by wangxiang4 on 2022/12/13. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import SwiftUI 8 | 9 | typealias SavedState = () -> Void 10 | 11 | // 3D动画部件执行协议 12 | protocol CritterAnimatable { 13 | func currentState() -> SavedState 14 | func applyActiveStartState() 15 | func applyActiveEndState() 16 | func applyInactiveState() 17 | func applyPeekState() 18 | func applyUnPeekState() 19 | } 20 | 21 | // 3D动画部件执行默认实现 22 | extension CritterAnimatable where Self: UIView { 23 | 24 | func currentState() -> SavedState { 25 | let currentState = layer.transform 26 | return { 27 | self.layer.transform = currentState 28 | } 29 | } 30 | 31 | func applyActiveStartState() { } 32 | 33 | func applyActiveEndState() { } 34 | 35 | func applyInactiveState() { 36 | layer.transform = .identity 37 | } 38 | 39 | func applyPeekState() { } 40 | 41 | func applyUnPeekState() { } 42 | } 43 | 44 | // 执行集合中的3D动画 45 | extension Sequence where Iterator.Element == CritterAnimatable { 46 | 47 | func applyActiveStartState() { 48 | forEach { $0.applyActiveStartState() } 49 | } 50 | 51 | func applyActiveEndState() { 52 | forEach { $0.applyActiveEndState() } 53 | } 54 | 55 | func applyInactiveState() { 56 | forEach { $0.applyInactiveState() } 57 | } 58 | 59 | func applyPeekState() { 60 | forEach { $0.applyPeekState() } 61 | } 62 | 63 | func applyUnPeekState() { 64 | forEach { $0.applyUnPeekState() } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /Dolphin/Modules/Login/Animation/CritterAssets.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 动物动画图片资源 3 | // Created by wangxiang4 on 2022/12/13. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import SwiftUI 8 | extension UIImage { 9 | 10 | struct Critter { 11 | static let body = #imageLiteral(resourceName: "icon_login_body") 12 | static let doeEye = #imageLiteral(resourceName: "icon_login_eye_doe") 13 | static let eye = #imageLiteral(resourceName: "icon_login_eye") 14 | static let head = #imageLiteral(resourceName: "icon_login_head") 15 | static let leftArm = #imageLiteral(resourceName: "icon_login_arm") 16 | static let leftEar = #imageLiteral(resourceName: "icon_login_ear") 17 | static let mouthCircle = #imageLiteral(resourceName: "icon_login_mouth_circle") 18 | static let mouthFull = #imageLiteral(resourceName: "icon_login_mouth_full") 19 | static let mouthHalf = #imageLiteral(resourceName: "icon_login_mouth_half") 20 | static let mouthSmile = #imageLiteral(resourceName: "icon_login_mouth_smile") 21 | static let muzzle = #imageLiteral(resourceName: "icon_login_mouth_muzzle") 22 | static let nose = #imageLiteral(resourceName: "icon_login_mouth_nose") 23 | static let rightEar: UIImage = { 24 | let leftEar = UIImage.Critter.leftEar 25 | return UIImage( 26 | cgImage: leftEar.cgImage!, 27 | scale: leftEar.scale, 28 | orientation: .upMirrored 29 | ) 30 | }() 31 | static let rightArm: UIImage = { 32 | let leftArm = UIImage.Critter.leftArm 33 | return UIImage( 34 | cgImage: leftArm.cgImage!, 35 | scale: leftArm.scale, 36 | orientation: .upMirrored 37 | ) 38 | }() 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Dolphin/Modules/Login/Animation/Parts/Body.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 身体动画部分 3 | // Created by wangxiang4 on 2022/12/5. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import SwiftUI 8 | final class Body: UIImageView, CritterAnimatable { 9 | 10 | convenience init() { 11 | self.init(image: UIImage.Critter.body) 12 | layer.zPosition = -30 13 | frame = CGRect(x: 33.9, y: 109.2, width: 92.1, height: 73.4) 14 | } 15 | 16 | // MARK: - CritterAnimatable 17 | func applyActiveStartState() { 18 | layer.transform = CATransform3D 19 | .identity 20 | .perspective() 21 | .rotate(.y, by: -12.degrees) 22 | } 23 | 24 | func applyActiveEndState() { 25 | layer.transform = CATransform3D 26 | .identity 27 | .perspective() 28 | .rotate(.y, by: 12.degrees) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Dolphin/Modules/Login/Animation/Parts/Head.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 头动画部分 3 | // Created by wangxiang4 on 2022/12/5. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import SwiftUI 8 | final class Head: UIImageView, CritterAnimatable { 9 | 10 | convenience init() { 11 | self.init(image: UIImage.Critter.head) 12 | frame = CGRect(x: 27.3, y: 52.1, width: 105.5, height: 90.9) 13 | } 14 | 15 | // MARK: - CritterAnimatable 16 | func applyActiveStartState() { 17 | layer.transform = CATransform3D 18 | .identity 19 | .rotate(.x, by: -20.0.degrees) 20 | .rotate(.y, by: -18.0.degrees) 21 | .perspective() 22 | } 23 | 24 | func applyActiveEndState() { 25 | layer.transform = CATransform3D 26 | .identity 27 | .rotate(.x, by: -20.0.degrees) 28 | .rotate(.y, by: 18.0.degrees) 29 | .perspective() 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Dolphin/Modules/Login/Animation/Parts/LeftArm.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 左手动画部分 3 | // Created by wangxiang4 on 2022/12/5. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import SwiftUI 8 | final class LeftArm: UIImageView, CritterAnimatable { 9 | 10 | var isShy = false 11 | 12 | convenience init() { 13 | self.init(image: UIImage.Critter.leftArm) 14 | layer.zPosition = 30 15 | } 16 | 17 | override func didMoveToSuperview() { 18 | super.didMoveToSuperview() 19 | guard let superview = superview else { return } 20 | 21 | let originY = superview.bounds.maxY 22 | frame = CGRect(x: 25.1, y: originY, width: 42.3, height: 93.2) 23 | } 24 | 25 | func applyShyState() { 26 | if isShy { 27 | layer.transform = CATransform3D 28 | .identity 29 | .translate(.y, by: -82.6) 30 | } else { 31 | layer.transform = .identity 32 | } 33 | } 34 | 35 | func applyPeekState() { 36 | layer.transform = CATransform3D 37 | .identity 38 | .translate(.y, by: -70.6) 39 | } 40 | 41 | func applyUnPeekState() { 42 | if isShy { 43 | applyShyState() 44 | } else { 45 | applyInactiveState() 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Dolphin/Modules/Login/Animation/Parts/LeftEar.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 左耳动画部分 3 | // Created by wangxiang4 on 2022/12/5. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import SwiftUI 8 | final class LeftEar: UIImageView, CritterAnimatable { 9 | 10 | convenience init() { 11 | self.init(image: UIImage.Critter.leftEar) 12 | frame = CGRect(x: -9.1, y: -3.3, width: 36.6, height: 36.6) 13 | } 14 | 15 | // MARK: - CritterAnimatable 16 | func applyActiveStartState() { 17 | layer.transform = CATransform3D 18 | .identity 19 | .translate(.x, by: 10) 20 | } 21 | 22 | func applyActiveEndState() { 23 | layer.transform = CATransform3D 24 | .identity 25 | .translate(.x, by: 2) 26 | .translate(.y, by: 12) 27 | .rotate(.z, by: -8.0.degrees) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Dolphin/Modules/Login/Animation/Parts/LeftEarMask.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 左耳遮罩动画部分,需要遮住要不然执行耳朵动画耳朵会露出来 3 | // Created by wangxiang4 on 2022/12/5. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import SwiftUI 8 | final class LeftEarMask: UIImageView, CritterAnimatable { 9 | 10 | convenience init() { 11 | self.init(image: UIImage.Critter.head) 12 | layer.anchorPoint = CGPoint(x: 1, y: 0) 13 | } 14 | 15 | override func didMoveToSuperview() { 16 | super.didMoveToSuperview() 17 | guard let superview = superview else { return } 18 | 19 | frame = superview.bounds 20 | mask = { 21 | let mask = UIView() 22 | mask.backgroundColor = .black 23 | var frame = superview.bounds 24 | frame.size.width = frame.width / 2 25 | mask.frame = frame 26 | return mask 27 | }() 28 | } 29 | 30 | // MARK: - CritterAnimatable 31 | func applyActiveStartState() { 32 | layer.transform = .identity 33 | } 34 | 35 | func applyActiveEndState() { 36 | layer.transform = CATransform3D 37 | .identity 38 | .scale(.x, by: 0.82) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Dolphin/Modules/Login/Animation/Parts/LeftEye.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 左眼动画部分 3 | // Created by wangxiang4 on 2022/12/5. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import SwiftUI 8 | 9 | final class LeftEye: UIImageView, CritterAnimatable { 10 | 11 | private let p1 = CGPoint(x: 21.8, y: 28.8) 12 | private let p2 = CGPoint(x: 9.7, y: 41.1) 13 | 14 | convenience init() { 15 | self.init(image: UIImage.Critter.eye) 16 | frame = CGRect(x: p1.x, y: p1.y, width: 11.7, height: 11.7) 17 | } 18 | 19 | // MARK: - CritterAnimatable 20 | func applyActiveStartState() { 21 | let eyeScale: CGFloat = 1.12 22 | let eyeTransform = CATransform3D 23 | .identity 24 | .scale(.x, by: eyeScale) 25 | .scale(.y, by: eyeScale) 26 | .scale(.z, by: 1.01) // 🎩✨ Magic to prevent 'jumping' 27 | 28 | layer.transform = eyeTransform 29 | .translate(.x, by: p2.x - p1.x) 30 | .translate(.y, by: p2.y - p1.y) 31 | } 32 | 33 | func applyActiveEndState() { 34 | let eyeScale: CGFloat = 1.12 35 | let eyeTransform = CATransform3D 36 | .identity 37 | .scale(.x, by: eyeScale) 38 | .scale(.y, by: eyeScale) 39 | .scale(.z, by: 1.01) // 🎩✨ Magic to prevent 'jumping' 40 | 41 | layer.transform = eyeTransform 42 | .translate(.x, by: -(p2.x - p1.x)) 43 | .translate(.y, by: p2.y - p1.y) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Dolphin/Modules/Login/Animation/Parts/Muzzle.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 嘴型动画部分 3 | // Created by wangxiang4 on 2022/12/5. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import SwiftUI 8 | final class Muzzle: UIImageView, CritterAnimatable { 9 | 10 | private let p1 = CGPoint(x: 24, y: 43) 11 | private let p2 = CGPoint(x: 11.2, y: 48) 12 | 13 | convenience init() { 14 | self.init(image: UIImage.Critter.muzzle) 15 | frame = CGRect(x: p1.x, y: p1.y, width: 57.5, height: 46.3) 16 | } 17 | 18 | // MARK: - CritterAnimatable 19 | func applyActiveStartState() { 20 | layer.transform = CATransform3D 21 | .identity 22 | .translate(.x, by: p2.x - p1.x) 23 | .translate(.y, by: p2.y - p1.y) 24 | } 25 | 26 | func applyActiveEndState() { 27 | layer.transform = CATransform3D 28 | .identity 29 | .translate(.x, by: -(p2.x - p1.x)) 30 | .translate(.y, by: p2.y - p1.y) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Dolphin/Modules/Login/Animation/Parts/Nose.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 鼻子动画部分 3 | // Created by wangxiang4 on 2022/12/5. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import SwiftUI 8 | final class Nose: UIImageView, CritterAnimatable { 9 | 10 | private let p1 = CGPoint(x: 22.2, y: 2.2) 11 | private let p2 = CGPoint(x: 12.6, y: 5.2) 12 | 13 | convenience init() { 14 | self.init(image: UIImage.Critter.nose) 15 | frame = CGRect(x: p1.x, y: p1.y, width: 13, height: 9.6) 16 | } 17 | 18 | // MARK: - CritterAnimatable 19 | func applyActiveStartState() { 20 | layer.transform = CATransform3D 21 | .identity 22 | .translate(.x, by: p2.x - p1.x) 23 | .translate(.y, by: p2.y - p1.y) 24 | } 25 | 26 | func applyActiveEndState() { 27 | layer.transform = CATransform3D 28 | .identity 29 | .translate(.x, by: -(p2.x - p1.x)) 30 | .translate(.y, by: p2.y - p1.y) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Dolphin/Modules/Login/Animation/Parts/RightArm.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 右手动画部分 3 | // Created by wangxiang4 on 2022/12/5. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import SwiftUI 8 | final class RightArm: UIImageView, CritterAnimatable { 9 | 10 | var isShy = false 11 | 12 | convenience init() { 13 | self.init(image: UIImage.Critter.rightArm) 14 | layer.zPosition = 30 15 | } 16 | 17 | override func didMoveToSuperview() { 18 | super.didMoveToSuperview() 19 | guard let superview = superview else { return } 20 | 21 | let originY = superview.bounds.maxY 22 | frame = CGRect(x: 92.6, y: originY, width: 42.3, height: 93.2) 23 | } 24 | 25 | func applyShyState() { 26 | if isShy { 27 | layer.transform = CATransform3D 28 | .identity 29 | .translate(.y, by: -82.6) 30 | } else { 31 | layer.transform = .identity 32 | } 33 | } 34 | 35 | func applyPeekState() { 36 | layer.transform = CATransform3D 37 | .identity 38 | .translate(.y, by: -70.6) 39 | } 40 | 41 | func applyUnPeekState() { 42 | if isShy { 43 | applyShyState() 44 | } else { 45 | applyInactiveState() 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Dolphin/Modules/Login/Animation/Parts/RightEar.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 右耳动画部分 3 | // Created by wangxiang4 on 2022/12/5. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import SwiftUI 8 | final class RightEar: UIImageView, CritterAnimatable { 9 | 10 | convenience init() { 11 | self.init(image: UIImage.Critter.rightEar) 12 | frame = CGRect(x: 77.9, y: -3.3, width: 36.6, height: 36.6) 13 | } 14 | 15 | // MARK: - CritterAnimatable 16 | func applyActiveStartState() { 17 | layer.transform = CATransform3D 18 | .identity 19 | .translate(.x, by: -2) 20 | .translate(.y, by: 12) 21 | .rotate(.z, by: 8.0.degrees) 22 | } 23 | 24 | func applyActiveEndState() { 25 | layer.transform = CATransform3D 26 | .identity 27 | .translate(.x, by: -10) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Dolphin/Modules/Login/Animation/Parts/RightEarMask.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 右耳遮罩动画部分,需要遮住要不然执行耳朵动画耳朵会露出来 3 | // Created by wangxiang4 on 2022/12/5. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import SwiftUI 8 | final class RightEarMask: UIImageView, CritterAnimatable { 9 | 10 | convenience init() { 11 | self.init(image: UIImage.Critter.head) 12 | layer.anchorPoint = CGPoint(x: 0, y: 0) 13 | } 14 | 15 | override func didMoveToSuperview() { 16 | super.didMoveToSuperview() 17 | guard let superview = superview else { return } 18 | 19 | frame = superview.bounds 20 | mask = { 21 | let mask = UIView() 22 | mask.backgroundColor = .black 23 | var frame = superview.bounds 24 | frame.origin.x = frame.midX 25 | frame.size.width = frame.width / 2 26 | mask.frame = frame 27 | return mask 28 | }() 29 | } 30 | 31 | // MARK: - CritterAnimatable 32 | func applyActiveStartState() { 33 | layer.transform = CATransform3D 34 | .identity 35 | .scale(.x, by: 0.82) 36 | } 37 | 38 | func applyActiveEndState() { 39 | layer.transform = .identity 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Dolphin/Modules/Login/Animation/Parts/RightEye.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 右眼动画部分 3 | // Created by wangxiang4 on 2022/12/5. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import SwiftUI 8 | 9 | final class RightEye: UIImageView, CritterAnimatable { 10 | 11 | private let p1 = CGPoint(x: 72.4, y: 28.8) 12 | private let p2 = CGPoint(x: 62.1, y: 41.1) 13 | 14 | convenience init() { 15 | self.init(image: UIImage.Critter.eye) 16 | frame = CGRect(x: p1.x, y: p1.y, width: 11.7, height: 11.7) 17 | } 18 | 19 | // MARK: - CritterAnimatable 20 | func applyActiveStartState() { 21 | let eyeScale: CGFloat = 1.12 22 | let eyeTransform = CATransform3D 23 | .identity 24 | .scale(.x, by: eyeScale) 25 | .scale(.y, by: eyeScale) 26 | .scale(.z, by: 1.01) // 🎩✨ Magic to prevent 'jumping' 27 | 28 | layer.transform = eyeTransform 29 | .translate(.x, by: p2.x - p1.x) 30 | .translate(.y, by: p2.y - p1.y) 31 | } 32 | 33 | func applyActiveEndState() { 34 | let eyeScale: CGFloat = 1.12 35 | let eyeTransform = CATransform3D 36 | .identity 37 | .scale(.x, by: eyeScale) 38 | .scale(.y, by: eyeScale) 39 | .scale(.z, by: 1.01) // 🎩✨ Magic to prevent 'jumping' 40 | 41 | layer.transform = eyeTransform 42 | .translate(.x, by: -(p2.x - p1.x)) 43 | .translate(.y, by: p2.y - p1.y) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Dolphin/Modules/Main/HomeTabBarViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 首页标签栏目视图模型 3 | // Created by wangxiang4 on 2022/11/27. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import Foundation 8 | import RxCocoa 9 | import RxSwift 10 | import WhatsNewKit 11 | 12 | class HomeTabBarViewModel: ViewModel, ViewModelType { 13 | 14 | // 双向绑定输入 15 | struct Input { 16 | let whatsNewTrigger: Observable 17 | } 18 | 19 | // 双向绑定输出 20 | struct Output { 21 | let openWhatsNew: Driver 22 | } 23 | 24 | let whatsNewManager: WhatsNewManager 25 | 26 | override init() { 27 | whatsNewManager = DIContainer.shared.resolve() 28 | } 29 | 30 | func transform(input: Input) -> Output { 31 | let whatsNew = whatsNewManager.whatsNew() 32 | let whatsNewItems = input.whatsNewTrigger.take(1).map { _ in whatsNew } 33 | return Output(openWhatsNew: whatsNewItems.asDriverOnErrorJustComplete()) 34 | } 35 | 36 | func viewModel(for tabBarItem: HomeTabBarItem) -> ViewModel { 37 | switch tabBarItem { 38 | case .home: 39 | let viewModel = HomeViewModel() 40 | return viewModel 41 | case .workbench: 42 | let viewModel = WorkbenchViewModel() 43 | return viewModel 44 | case .message: 45 | let viewModel = MessageViewModel() 46 | return viewModel 47 | case .user: 48 | let viewModel = UserViewModel() 49 | return viewModel 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Dolphin/Modules/Main/InitialSplitViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 默认平板分割视图控制器右视图场景 3 | // Created by wangxiang4 on 2022/11/27. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import SwiftUI 8 | class InitialSplitViewController: TableViewController { 9 | 10 | override func viewDidLoad() { 11 | super.viewDidLoad() 12 | } 13 | 14 | override func makeUI() { 15 | super.makeUI() 16 | // 移除头部跟底部刷新,引导页展示 17 | tableView.headRefreshControl = nil 18 | tableView.footRefreshControl = nil 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Dolphin/Modules/Main/MainViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MainViewController.swift 3 | // Dolphin 4 | // 5 | // Created by wangxiang4 on 2022/12/9. 6 | // Copyright © 2022 dolphin-community. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | import Kingfisher 11 | class MainViewController: UIViewController { 12 | 13 | @IBOutlet weak var resultImage: UIImageView! 14 | 15 | override func viewDidLoad() { 16 | super.viewDidLoad() 17 | let path = Bundle.main.path(forResource: "main", ofType: "gif") 18 | let url = URL(fileURLWithPath: path!) 19 | let provider = LocalFileImageDataProvider(fileURL: url) 20 | resultImage.kf.setImage(with: provider) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Dolphin/Modules/Main/Workbench/WorkbenchViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 工作台视图模型 3 | // Created by 福尔摩翔 on 2022/11/29. 4 | // Copyright © 2022 entfrm All rights reserved. 5 | // 6 | 7 | import Foundation 8 | import RxCocoa 9 | import RxSwift 10 | 11 | class WorkbenchViewModel: ViewModel, ViewModelType { 12 | 13 | struct Input { 14 | } 15 | 16 | struct Output { 17 | } 18 | 19 | func transform(input: Input) -> Output { 20 | return Output() 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Dolphin/Modules/Message/Cells/MessageCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 通知表格自定义基础列视图 3 | // Created by wangxiang4 on 2022/11/29. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import SwiftUI 8 | import RxSwift 9 | 10 | class MessageCell: DefaultTableViewCell { 11 | 12 | override func makeUI() { 13 | super.makeUI() 14 | titleLabel.numberOfLines = 2 15 | leftImageView.cornerRadius = 0 16 | } 17 | 18 | override func bind(to viewModel: TableViewCellViewModel) { 19 | super.bind(to: viewModel) 20 | guard let viewModel = viewModel as? MessageCellViewModel else { return } 21 | 22 | // 不能使用 rx.disposeBag 重用列,rx销毁冲突 23 | cellDisposeBag = DisposeBag() 24 | 25 | // 行点击绑定回调 26 | containerView.rx.tap().map { _ in viewModel.ossFile }.filterNil().bind(to: viewModel.rowSelected).disposed(by: cellDisposeBag) 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /Dolphin/Modules/Message/Cells/MessageCell.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Dolphin/Modules/Message/Cells/MessageCellViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 通知表格自定义基础列视图模型 3 | // Created by wangxiang4 on 2022/11/29. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import Foundation 8 | import RxSwift 9 | import RxCocoa 10 | 11 | class MessageCellViewModel: DefaultTableViewCellViewModel { 12 | 13 | // 行数据 14 | let ossFile: OSSFile? 15 | 16 | // 行点击 17 | let rowSelected = PublishSubject() 18 | 19 | init(with ossFile: OSSFile) { 20 | self.ossFile = ossFile 21 | super.init() 22 | // 设置列数据 23 | title.accept(ossFile.original) 24 | detail.accept(ossFile.createTime) 25 | image.accept(R.image.icon_cell_submodule()?.template) 26 | hidesDisclosure.accept(true) 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /Dolphin/Modules/Message/MessageViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 通知视图控制器 3 | // Created by wangxiang4 on 2022/11/29. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import SwiftUI 8 | import RxSwift 9 | import RxCocoa 10 | import RxDataSources 11 | import Toast_Swift 12 | 13 | private let reuseIdentifier = R.reuseIdentifier.messageCell.identifier 14 | 15 | class MessageViewController: TableViewController { 16 | 17 | override func viewDidLoad() { 18 | super.viewDidLoad() 19 | } 20 | 21 | override func makeUI() { 22 | super.makeUI() 23 | languageChanged.subscribe(onNext: { [weak self] () in 24 | self?.navigationTitle = R.string.localizable.homeTabBarMessageTitle.key.localized() 25 | }).disposed(by: rx.disposeBag) 26 | tableView.register(R.nib.messageCell) 27 | } 28 | 29 | override func bindViewModel() { 30 | super.bindViewModel() 31 | // 网络请求错误吐司提示 32 | viewModel?.requestError.subscribe(onNext: { [weak self] (error) in 33 | self?.view.makeToast(error.errMessage, image: R.image.icon_toast_warning()) 34 | }).disposed(by: rx.disposeBag) 35 | guard let viewModel = viewModel as? MessageViewModel else { return } 36 | let refresh = Observable.of(Observable.just(()), headerRefreshTrigger).merge() 37 | let input = MessageViewModel.Input(headerRefresh: refresh, footerRefresh: footerRefreshTrigger) 38 | let output = viewModel.transform(input: input) 39 | 40 | output.items.asDriver(onErrorJustReturn: []) 41 | .drive(tableView.rx.items(cellIdentifier: reuseIdentifier, cellType: MessageCell.self)) { tableView, viewModel, cell in 42 | cell.bind(to: viewModel) 43 | }.disposed(by: rx.disposeBag) 44 | 45 | output.rowSelected.drive(onNext: { [weak self] item in 46 | logDebug("\(item.toJSON())") 47 | var style = ToastManager.shared.style 48 | style.backgroundColor = UIColor.Material.green 49 | self?.view.makeToast("当前行数据为:\(item.toJSON())", position: .top, style: style) 50 | }).disposed(by: rx.disposeBag) 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Dolphin/Modules/Theme/ThemeCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 设置主题颜色自定义基础列视图 3 | // Created by wangxiang4 on 2022/11/29. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import SwiftUI 8 | 9 | class ThemeCell: DefaultTableViewCell { 10 | 11 | override func makeUI() { 12 | super.makeUI() 13 | rightImageView.isHidden = true 14 | } 15 | 16 | override func bind(to viewModel: TableViewCellViewModel) { 17 | super.bind(to: viewModel) 18 | guard let viewModel = viewModel as? ThemeCellViewModel else { return } 19 | 20 | viewModel.imageColor.asDriver().drive(leftImageView.rx.backgroundColor).disposed(by: rx.disposeBag) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Dolphin/Modules/Theme/ThemeCell.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Dolphin/Modules/Theme/ThemeCellViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 设置主题颜色自定义基础列视图模型 3 | // Created by wangxiang4 on 2022/11/29. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import Foundation 8 | import RxSwift 9 | import RxCocoa 10 | 11 | class ThemeCellViewModel: DefaultTableViewCellViewModel { 12 | 13 | let imageColor = BehaviorRelay(value: nil) 14 | 15 | let theme: ColorTheme 16 | 17 | init(with theme: ColorTheme) { 18 | self.theme = theme 19 | super.init() 20 | title.accept(theme.title) 21 | imageColor.accept(theme.color) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Dolphin/Modules/Theme/ThemeViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 设置国际化语言视图控制器 3 | // Created by wangxiang4 on 2022/11/29. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import SwiftUI 8 | import RxSwift 9 | import RxCocoa 10 | 11 | private let reuseIdentifier = R.reuseIdentifier.themeCell.identifier 12 | 13 | class ThemeViewController: TableViewController { 14 | 15 | override func viewDidLoad() { 16 | super.viewDidLoad() 17 | } 18 | 19 | override func makeUI() { 20 | super.makeUI() 21 | languageChanged.subscribe(onNext: { [weak self] () in 22 | self?.navigationTitle = R.string.localizable.themeNavigationTitle.key.localized() 23 | }).disposed(by: rx.disposeBag) 24 | tableView.register(R.nib.themeCell) 25 | tableView.headRefreshControl = nil 26 | tableView.footRefreshControl = nil 27 | } 28 | 29 | override func bindViewModel() { 30 | super.bindViewModel() 31 | guard let viewModel = viewModel as? ThemeViewModel else { return } 32 | 33 | let input = ThemeViewModel.Input(refresh: Observable.just(()), 34 | selection: tableView.rx.modelSelected(ThemeCellViewModel.self).asDriver()) 35 | let output = viewModel.transform(input: input) 36 | 37 | output.items.drive(tableView.rx.items(cellIdentifier: reuseIdentifier, cellType: ThemeCell.self)) { tableView, viewModel, cell in 38 | cell.bind(to: viewModel) 39 | }.disposed(by: rx.disposeBag) 40 | 41 | output.selected.drive(onNext: { [weak self] (cellViewModel) in 42 | self?.navigationController?.dismiss(animated: true, completion: nil) 43 | }).disposed(by: rx.disposeBag) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Dolphin/Modules/Theme/ThemeViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 设置主题颜色视图模型 3 | // Created by wangxiang4 on 2022/11/29. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import Foundation 8 | import RxCocoa 9 | import RxSwift 10 | import RxDataSources 11 | 12 | class ThemeViewModel: ViewModel, ViewModelType { 13 | 14 | struct Input { 15 | let refresh: Observable 16 | let selection: Driver 17 | } 18 | 19 | struct Output { 20 | let items: Driver<[ThemeCellViewModel]> 21 | let selected: Driver 22 | } 23 | 24 | func transform(input: Input) -> Output { 25 | 26 | let elements = input.refresh 27 | .map { ColorTheme.allValues } 28 | .map { $0.map { ThemeCellViewModel(with: $0) } } 29 | .asDriver(onErrorJustReturn: []) 30 | 31 | let selected = input.selection 32 | 33 | selected.drive(onNext: { (cellViewModel) in 34 | let color = cellViewModel.theme 35 | let theme = ThemeType.currentTheme().withColor(color: color) 36 | themeService.switch(theme) 37 | }).disposed(by: rx.disposeBag) 38 | 39 | return Output(items: elements, selected: selected) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Dolphin/Modules/User/Cells/UserCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 设置表格自定义基础列视图 3 | // Created by wangxiang4 on 2022/11/29. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import SwiftUI 8 | class UserCell: DefaultTableViewCell { 9 | 10 | override func makeUI() { 11 | super.makeUI() 12 | leftImageView.contentMode = .center 13 | leftImageView.cornerRadius = 0 14 | leftImageView.snp.updateConstraints { (make) in 15 | make.size.equalTo(30) 16 | } 17 | detailLabel.isHidden = true 18 | attributedDetailLabel.isHidden = true 19 | secondDetailLabel.textAlignment = .right 20 | textsStackView.axis = .horizontal 21 | textsStackView.distribution = .fillEqually 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Dolphin/Modules/User/Cells/UserCell.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Dolphin/Modules/User/Cells/UserCellViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 设置表格自定义基础列视图模型 3 | // Created by wangxiang4 on 2022/11/29. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import Foundation 8 | import RxSwift 9 | import RxCocoa 10 | 11 | class UserCellViewModel: DefaultTableViewCellViewModel { 12 | 13 | init(with title: String, detail: String?, image: UIImage?, hidesDisclosure: Bool) { 14 | super.init() 15 | self.title.accept(title) 16 | self.secondDetail.accept(detail) 17 | self.image.accept(image) 18 | self.hidesDisclosure.accept(hidesDisclosure) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Dolphin/Modules/User/Cells/UserSwitchCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 设置表格自定义开关列视图 3 | // Created by wangxiang4 on 2022/11/29. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import SwiftUI 8 | 9 | class UserSwitchCell: DefaultTableViewCell { 10 | 11 | lazy var switchView: Switch = { 12 | let view = Switch() 13 | return view 14 | }() 15 | 16 | override func makeUI() { 17 | super.makeUI() 18 | leftImageView.contentMode = .center 19 | leftImageView.cornerRadius = 0 20 | leftImageView.snp.updateConstraints { (make) in 21 | make.size.equalTo(30) 22 | } 23 | stackView.insertArrangedSubview(switchView, at: 2) 24 | leftImageView.theme.tintColor = themeService.attribute { $0.secondary } 25 | } 26 | 27 | override func bind(to viewModel: TableViewCellViewModel) { 28 | super.bind(to: viewModel) 29 | guard let viewModel = viewModel as? UserSwitchCellViewModel else { return } 30 | viewModel.isEnabled.asDriver().drive(switchView.rx.isOn).disposed(by: rx.disposeBag) 31 | switchView.rx.isOn.bind(to: viewModel.switchChanged).disposed(by: rx.disposeBag) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Dolphin/Modules/User/Cells/UserSwitchCell.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Dolphin/Modules/User/Cells/UserSwitchCellViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 设置表格自定义开关列视图模型 3 | // Created by wangxiang4 on 2022/11/29. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import Foundation 8 | import RxSwift 9 | import RxCocoa 10 | 11 | class UserSwitchCellViewModel: DefaultTableViewCellViewModel { 12 | 13 | let isEnabled = BehaviorRelay(value: false) 14 | 15 | let switchChanged = PublishSubject() 16 | 17 | init(with title: String, detail: String?, image: UIImage?, hidesDisclosure: Bool, isEnabled: Bool) { 18 | super.init() 19 | self.title.accept(title) 20 | self.secondDetail.accept(detail) 21 | self.image.accept(image) 22 | self.hidesDisclosure.accept(hidesDisclosure) 23 | self.isEnabled.accept(isEnabled) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Dolphin/Modules/User/UserSection.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 渲染自定义表格列 3 | // Created by wangxiang4 on 2022/11/29. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import Foundation 8 | import RxDataSources 9 | 10 | enum UserSection { 11 | case setting(title: String, items: [UserSectionItem]) 12 | } 13 | 14 | enum UserSectionItem { 15 | 16 | // 夜间模式 17 | case nightModeItem(viewModel: UserSwitchCellViewModel) 18 | 19 | // 切换主题颜色 20 | case themeItem(viewModel: UserCellViewModel) 21 | 22 | // 切换国际化语言 23 | case languageItem(viewModel: UserCellViewModel) 24 | 25 | // 清除图片缓存 26 | case removeCacheItem(viewModel: UserCellViewModel) 27 | 28 | // 新特性 29 | case whatsNewItem(viewModel: UserCellViewModel) 30 | 31 | // 登出 32 | case logoutItem(viewModel: UserCellViewModel) 33 | } 34 | 35 | extension UserSectionItem: IdentifiableType { 36 | typealias Identity = String 37 | var identity: Identity { 38 | switch self { 39 | case .nightModeItem(let viewModel): return viewModel.title.value ?? "" 40 | case .themeItem(let viewModel), 41 | .languageItem(let viewModel), 42 | .removeCacheItem(let viewModel), 43 | .whatsNewItem(let viewModel), 44 | .logoutItem(let viewModel): return viewModel.title.value ?? "" 45 | } 46 | } 47 | } 48 | 49 | extension UserSectionItem: Equatable { 50 | static func == (lhs: UserSectionItem, rhs: UserSectionItem) -> Bool { 51 | return lhs.identity == rhs.identity 52 | } 53 | } 54 | 55 | extension UserSection: AnimatableSectionModelType, IdentifiableType { 56 | typealias Item = UserSectionItem 57 | 58 | typealias Identity = String 59 | var identity: Identity { return title } 60 | 61 | var title: String { 62 | switch self { 63 | case .setting(let title, _): return title 64 | } 65 | } 66 | 67 | var items: [UserSectionItem] { 68 | switch self { 69 | case .setting(_, let items): return items.map {$0} 70 | } 71 | } 72 | 73 | init(original: UserSection, items: [Item]) { 74 | switch original { 75 | case .setting(let title, let items): self = .setting(title: title, items: items) 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /Dolphin/Modules/Workbench/WorkbenchViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 工作台视图模型 3 | // Created by wangxiang4 on 2022/11/29. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import Foundation 8 | import RxCocoa 9 | import RxSwift 10 | 11 | class WorkbenchViewModel: ViewModel, ViewModelType { 12 | 13 | struct Input { 14 | } 15 | 16 | struct Output { 17 | } 18 | 19 | func transform(input: Input) -> Output { 20 | return Output() 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Dolphin/Resources/2048.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/2048.jpeg -------------------------------------------------------------------------------- /Dolphin/Resources/Assets.xcassets/AppIcon.appiconset/dolphin 1024px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Assets.xcassets/AppIcon.appiconset/dolphin 1024px.png -------------------------------------------------------------------------------- /Dolphin/Resources/Assets.xcassets/AppIcon.appiconset/dolphin 120px 1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Assets.xcassets/AppIcon.appiconset/dolphin 120px 1.png -------------------------------------------------------------------------------- /Dolphin/Resources/Assets.xcassets/AppIcon.appiconset/dolphin 120px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Assets.xcassets/AppIcon.appiconset/dolphin 120px.png -------------------------------------------------------------------------------- /Dolphin/Resources/Assets.xcassets/AppIcon.appiconset/dolphin 152px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Assets.xcassets/AppIcon.appiconset/dolphin 152px.png -------------------------------------------------------------------------------- /Dolphin/Resources/Assets.xcassets/AppIcon.appiconset/dolphin 167px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Assets.xcassets/AppIcon.appiconset/dolphin 167px.png -------------------------------------------------------------------------------- /Dolphin/Resources/Assets.xcassets/AppIcon.appiconset/dolphin 180px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Assets.xcassets/AppIcon.appiconset/dolphin 180px.png -------------------------------------------------------------------------------- /Dolphin/Resources/Assets.xcassets/AppIcon.appiconset/dolphin 20px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Assets.xcassets/AppIcon.appiconset/dolphin 20px.png -------------------------------------------------------------------------------- /Dolphin/Resources/Assets.xcassets/AppIcon.appiconset/dolphin 29px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Assets.xcassets/AppIcon.appiconset/dolphin 29px.png -------------------------------------------------------------------------------- /Dolphin/Resources/Assets.xcassets/AppIcon.appiconset/dolphin 40px 1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Assets.xcassets/AppIcon.appiconset/dolphin 40px 1.png -------------------------------------------------------------------------------- /Dolphin/Resources/Assets.xcassets/AppIcon.appiconset/dolphin 40px 2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Assets.xcassets/AppIcon.appiconset/dolphin 40px 2.png -------------------------------------------------------------------------------- /Dolphin/Resources/Assets.xcassets/AppIcon.appiconset/dolphin 40px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Assets.xcassets/AppIcon.appiconset/dolphin 40px.png -------------------------------------------------------------------------------- /Dolphin/Resources/Assets.xcassets/AppIcon.appiconset/dolphin 58px 1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Assets.xcassets/AppIcon.appiconset/dolphin 58px 1.png -------------------------------------------------------------------------------- /Dolphin/Resources/Assets.xcassets/AppIcon.appiconset/dolphin 58px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Assets.xcassets/AppIcon.appiconset/dolphin 58px.png -------------------------------------------------------------------------------- /Dolphin/Resources/Assets.xcassets/AppIcon.appiconset/dolphin 60px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Assets.xcassets/AppIcon.appiconset/dolphin 60px.png -------------------------------------------------------------------------------- /Dolphin/Resources/Assets.xcassets/AppIcon.appiconset/dolphin 76px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Assets.xcassets/AppIcon.appiconset/dolphin 76px.png -------------------------------------------------------------------------------- /Dolphin/Resources/Assets.xcassets/AppIcon.appiconset/dolphin 80px 1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Assets.xcassets/AppIcon.appiconset/dolphin 80px 1.png -------------------------------------------------------------------------------- /Dolphin/Resources/Assets.xcassets/AppIcon.appiconset/dolphin 80px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Assets.xcassets/AppIcon.appiconset/dolphin 80px.png -------------------------------------------------------------------------------- /Dolphin/Resources/Assets.xcassets/AppIcon.appiconset/dolphin 87px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Assets.xcassets/AppIcon.appiconset/dolphin 87px.png -------------------------------------------------------------------------------- /Dolphin/Resources/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Dolphin/Resources/Assets.xcassets/image_no_result.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "image_no_result.pdf", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Dolphin/Resources/Assets.xcassets/image_no_result.imageset/image_no_result.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Assets.xcassets/image_no_result.imageset/image_no_result.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Assets.xcassets/launch_image.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "launch_image.pdf", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Dolphin/Resources/Assets.xcassets/launch_image.imageset/launch_image.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Assets.xcassets/launch_image.imageset/launch_image.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_button_star.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon_button_star.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_button_star.imageset/icon_button_star.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_button_star.imageset/icon_button_star.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_button_tom.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "tom.pdf", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_button_tom.imageset/tom.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_button_tom.imageset/tom.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_button_unstar.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon_button_unstar.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_button_unstar.imageset/icon_button_unstar.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_button_unstar.imageset/icon_button_unstar.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_button_user_plus.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon_button_user_plus.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_button_user_plus.imageset/icon_button_user_plus.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_button_user_plus.imageset/icon_button_user_plus.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_button_user_x.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon_button_user_x.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_button_user_x.imageset/icon_button_user_x.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_button_user_x.imageset/icon_button_user_x.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_acknowledgements.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon_cell_acknowledgements.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_acknowledgements.imageset/icon_cell_acknowledgements.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_cell_acknowledgements.imageset/icon_cell_acknowledgements.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_badge_collaborator.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon_cell_badge_collaborator.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_badge_collaborator.imageset/icon_cell_badge_collaborator.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_cell_badge_collaborator.imageset/icon_cell_badge_collaborator.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_badge_search.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon_cell_badge_search.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_badge_search.imageset/icon_cell_badge_search.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_cell_badge_search.imageset/icon_cell_badge_search.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_badge_star.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon_cell_badge_star.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_badge_star.imageset/icon_cell_badge_star.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_cell_badge_star.imageset/icon_cell_badge_star.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_badge_tag.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon_cell_badge_tag.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_badge_tag.imageset/icon_cell_badge_tag.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_cell_badge_tag.imageset/icon_cell_badge_tag.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_badge_user.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon_cell_badge_user.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_badge_user.imageset/icon_cell_badge_user.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_cell_badge_user.imageset/icon_cell_badge_user.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_check.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon_cell_check.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_check.imageset/icon_cell_check.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_cell_check.imageset/icon_cell_check.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_cloc.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "icon_cell_cloc.pdf", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_cloc.imageset/icon_cell_cloc.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_cell_cloc.imageset/icon_cell_cloc.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_company.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon_cell_company.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_company.imageset/icon_cell_company.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_cell_company.imageset/icon_cell_company.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_contact_no_image.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon_cell_contact_no_image.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_contact_no_image.imageset/icon_cell_contact_no_image.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_cell_contact_no_image.imageset/icon_cell_contact_no_image.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_created.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon_cell_created.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_created.imageset/icon_cell_created.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_cell_created.imageset/icon_cell_created.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_dir.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon_cell_dir.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_dir.imageset/icon_cell_dir.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_cell_dir.imageset/icon_cell_dir.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_disclosure.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon_cell_disclosure.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_disclosure.imageset/icon_cell_disclosure.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_cell_disclosure.imageset/icon_cell_disclosure.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_events.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon_cell_events.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_events.imageset/icon_cell_events.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_cell_events.imageset/icon_cell_events.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_file.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon_cell_file.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_file.imageset/icon_cell_file.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_cell_file.imageset/icon_cell_file.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_frown.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon_cell_frown.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_frown.imageset/icon_cell_frown.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_cell_frown.imageset/icon_cell_frown.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_issues.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon_cell_issues.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_issues.imageset/icon_cell_issues.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_cell_issues.imageset/icon_cell_issues.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_language.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon_cell_language.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_language.imageset/icon_cell_language.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_cell_language.imageset/icon_cell_language.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_link.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon_cell_link.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_link.imageset/icon_cell_link.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_cell_link.imageset/icon_cell_link.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_logout.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon_cell_logout.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_logout.imageset/icon_cell_logout.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_cell_logout.imageset/icon_cell_logout.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_night_mode.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon_cell_night_mode.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_night_mode.imageset/icon_cell_night_mode.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_cell_night_mode.imageset/icon_cell_night_mode.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_profile_summary.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon_cell_profile_summary.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_profile_summary.imageset/icon_cell_profile_summary.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_cell_profile_summary.imageset/icon_cell_profile_summary.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_readme.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon_cell_readme.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_readme.imageset/icon_cell_readme.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_cell_readme.imageset/icon_cell_readme.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_releases.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon_cell_releases.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_releases.imageset/icon_cell_releases.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_cell_releases.imageset/icon_cell_releases.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_remove.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon_cell_remove.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_remove.imageset/icon_cell_remove.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_cell_remove.imageset/icon_cell_remove.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_size.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon_cell_size.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_size.imageset/icon_cell_size.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_cell_size.imageset/icon_cell_size.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_smile.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon_cell_smile.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_smile.imageset/icon_cell_smile.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_cell_smile.imageset/icon_cell_smile.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_source.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon_cell_source.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_source.imageset/icon_cell_source.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_cell_source.imageset/icon_cell_source.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_star.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon_cell_star.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_star.imageset/icon_cell_star.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_cell_star.imageset/icon_cell_star.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_stars_history.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon_cell_stars_history.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_stars_history.imageset/icon_cell_stars_history.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_cell_stars_history.imageset/icon_cell_stars_history.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_submodule.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon_cell_submodule.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_submodule.imageset/icon_cell_submodule.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_cell_submodule.imageset/icon_cell_submodule.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_theme.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon_cell_theme.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_theme.imageset/icon_cell_theme.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_cell_theme.imageset/icon_cell_theme.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_updated.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon_cell_updated.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_updated.imageset/icon_cell_updated.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_cell_updated.imageset/icon_cell_updated.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_whats_new.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon_cell_whats_new.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_cell_whats_new.imageset/icon_cell_whats_new.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_cell_whats_new.imageset/icon_cell_whats_new.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_login_arm.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "arm.pdf", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | }, 12 | "properties" : { 13 | "preserves-vector-representation" : true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_login_arm.imageset/arm.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_login_arm.imageset/arm.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_login_body.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "body.pdf", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | }, 12 | "properties" : { 13 | "preserves-vector-representation" : true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_login_body.imageset/body.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_login_body.imageset/body.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_login_ear.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "ear.pdf", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | }, 12 | "properties" : { 13 | "preserves-vector-representation" : true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_login_ear.imageset/ear.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_login_ear.imageset/ear.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_login_eye.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "eye.pdf", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | }, 12 | "properties" : { 13 | "preserves-vector-representation" : true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_login_eye.imageset/eye.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_login_eye.imageset/eye.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_login_eye_doe.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "eye-doe.pdf", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | }, 12 | "properties" : { 13 | "preserves-vector-representation" : true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_login_eye_doe.imageset/eye-doe.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_login_eye_doe.imageset/eye-doe.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_login_head.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "face.pdf", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | }, 12 | "properties" : { 13 | "preserves-vector-representation" : true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_login_head.imageset/face.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_login_head.imageset/face.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_login_mouth_circle.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "mouth-circle.pdf", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | }, 12 | "properties" : { 13 | "preserves-vector-representation" : true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_login_mouth_circle.imageset/mouth-circle.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_login_mouth_circle.imageset/mouth-circle.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_login_mouth_closed.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "mouth-closed.pdf", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | }, 12 | "properties" : { 13 | "preserves-vector-representation" : true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_login_mouth_closed.imageset/mouth-closed.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_login_mouth_closed.imageset/mouth-closed.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_login_mouth_full.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "mouth-open.pdf", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_login_mouth_full.imageset/mouth-open.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_login_mouth_full.imageset/mouth-open.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_login_mouth_half.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "mouth-half.pdf", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | }, 12 | "properties" : { 13 | "preserves-vector-representation" : true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_login_mouth_half.imageset/mouth-half.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_login_mouth_half.imageset/mouth-half.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_login_mouth_muzzle.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "muzzle.pdf", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_login_mouth_muzzle.imageset/muzzle.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_login_mouth_muzzle.imageset/muzzle.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_login_mouth_nose.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "nose.pdf", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_login_mouth_nose.imageset/nose.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_login_mouth_nose.imageset/nose.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_login_mouth_smile.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "mouth-smile.pdf", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | }, 12 | "properties" : { 13 | "preserves-vector-representation" : true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_login_mouth_smile.imageset/mouth-smile.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_login_mouth_smile.imageset/mouth-smile.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_login_password_hide.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "password-hide.pdf", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | }, 12 | "properties" : { 13 | "preserves-vector-representation" : true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_login_password_hide.imageset/password-hide.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_login_password_hide.imageset/password-hide.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_login_password_show.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "password-show.pdf", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | }, 12 | "properties" : { 13 | "preserves-vector-representation" : true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_login_password_show.imageset/password-show.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_login_password_show.imageset/password-show.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_login_qq.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "QQ.pdf", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_login_qq.imageset/QQ.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_login_qq.imageset/QQ.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_login_wechat.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "WeChat.pdf", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_login_wechat.imageset/WeChat.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_login_wechat.imageset/WeChat.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_navigation_back.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon_navigation_back.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_navigation_back.imageset/icon_navigation_back.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_navigation_back.imageset/icon_navigation_back.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_navigation_close.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon_navigation_close.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_navigation_close.imageset/icon_navigation_close.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_navigation_close.imageset/icon_navigation_close.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_navigation_forward.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon_navigation_forward.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_navigation_forward.imageset/icon_navigation_forward.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_navigation_forward.imageset/icon_navigation_forward.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_navigation_history.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon_navigation_history.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_navigation_history.imageset/icon_navigation_history.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_navigation_history.imageset/icon_navigation_history.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_navigation_language.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon_navigation_language.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_navigation_language.imageset/icon_navigation_language.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_navigation_language.imageset/icon_navigation_language.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_navigation_refresh.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon_navigation_refresh.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_navigation_refresh.imageset/icon_navigation_refresh.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_navigation_refresh.imageset/icon_navigation_refresh.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_navigation_stop.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon_navigation_stop.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_navigation_stop.imageset/icon_navigation_stop.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_navigation_stop.imageset/icon_navigation_stop.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_navigation_theme.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon_navigation_theme.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_navigation_theme.imageset/icon_navigation_theme.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_navigation_theme.imageset/icon_navigation_theme.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_navigation_web.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon_navigation_web.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_navigation_web.imageset/icon_navigation_web.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_navigation_web.imageset/icon_navigation_web.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_oa_button.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "icon_oa_button.pdf", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_oa_button.imageset/icon_oa_button.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_oa_button.imageset/icon_oa_button.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_oa_button1.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "leave.svg", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_oa_button2.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "overtime.svg", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_oa_button2.imageset/overtime.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_oa_button3.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "travel.svg", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_oa_button4.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "resignation.svg", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_oa_slideImage1.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "1.svg", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_oa_slideImage2.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "2.svg", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_oa_slideImage3.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "3.svg", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_oa_slideImage4.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "4.svg", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_oa_slideImage5.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "5.svg", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_oa_slideImage6.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "6.svg", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_oa_slideImage7.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "7.svg", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_tabbar_activity.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "icon_tabbar_activity.pdf", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_tabbar_activity.imageset/icon_tabbar_activity.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_tabbar_activity.imageset/icon_tabbar_activity.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_tabbar_home.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "home.pdf", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | }, 12 | "properties" : { 13 | "localizable" : true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_tabbar_home.imageset/home.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_tabbar_home.imageset/home.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_tabbar_login.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "icon_tabbar_login.pdf", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | }, 12 | "properties" : { 13 | "localizable" : true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_tabbar_login.imageset/icon_tabbar_login.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_tabbar_login.imageset/icon_tabbar_login.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_tabbar_news.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon_tabbar_news.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_tabbar_news.imageset/icon_tabbar_news.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_tabbar_news.imageset/icon_tabbar_news.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_tabbar_profile.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon_tabbar_profile.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_tabbar_profile.imageset/icon_tabbar_profile.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_tabbar_profile.imageset/icon_tabbar_profile.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_tabbar_search.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon_tabbar_search.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_tabbar_search.imageset/icon_tabbar_search.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_tabbar_search.imageset/icon_tabbar_search.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_tabbar_settings.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon_tabbar_settings.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_tabbar_settings.imageset/icon_tabbar_settings.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_tabbar_settings.imageset/icon_tabbar_settings.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_tabbar_workbench.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "workbench.pdf", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_tabbar_workbench.imageset/workbench.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_tabbar_workbench.imageset/workbench.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_toast_error.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon_toast_error.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_toast_error.imageset/icon_toast_error.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_toast_error.imageset/icon_toast_error.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_toast_success.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon_toast_success.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_toast_success.imageset/icon_toast_success.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_toast_success.imageset/icon_toast_success.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_toast_warning.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon_toast_warning.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_toast_warning.imageset/icon_toast_warning.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_toast_warning.imageset/icon_toast_warning.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_user_tom.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "tom@2x.pdf", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_user_tom.imageset/tom@2x.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_user_tom.imageset/tom@2x.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_whatsnew_color.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "color.pdf", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_whatsnew_color.imageset/color.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_whatsnew_color.imageset/color.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_whatsnew_ioc.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "ioc.pdf", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_whatsnew_ioc.imageset/ioc.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_whatsnew_ioc.imageset/ioc.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_whatsnew_ios.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "ios.pdf", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_whatsnew_ios.imageset/ios.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_whatsnew_ios.imageset/ios.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_whatsnew_mvvm.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "mvvm.pdf", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Dolphin/Resources/Icons.xcassets/icon_whatsnew_mvvm.imageset/mvvm.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/Icons.xcassets/icon_whatsnew_mvvm.imageset/mvvm.pdf -------------------------------------------------------------------------------- /Dolphin/Resources/en.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | // 2 | // 英文国际化配置 3 | // https://developer.apple.com/documentation/foundation/nsbundle/1417526-developmentlocalization 4 | // Created by wangxiang4 on 2022/12/5. 5 | // Copyright © 2022 dolphin-community. All rights reserved. 6 | // 7 | 8 | /* 通用 */ 9 | "Common.Yes" = "Yes"; 10 | "Common.No" = "No"; 11 | "Common.OK" = "OK"; 12 | "Common.Cancel" = "Cancel"; 13 | "Common.Done" = "Done"; 14 | "Common.Back" = "Back"; 15 | "Common.Close" = "Close"; 16 | "Common.Edit" = "Edit"; 17 | "Common.Next" = "Next"; 18 | "Common.Skip" = "Skip"; 19 | "Common.Reset" = "Reset"; 20 | "Common.Save" = "Save"; 21 | "Common.Delete" = "Delete"; 22 | "Common.Search" = "Search"; 23 | "Common.Success" = "Success"; 24 | "Common.Error" = "Error"; 25 | "Common.NoResults" = "No Data"; 26 | 27 | /* 网络连接 */ 28 | "Toast.ConnectionBack.Message" = "Back online"; 29 | "Toast.ConnectionLost.Message" = "No connection"; 30 | 31 | /* 主页TabBar */ 32 | "Home.TabBar.Home.Title" = "Home"; 33 | "Home.TabBar.Workbench.Title" = "Workbench"; 34 | "Home.TabBar.Message.Title" = "Message"; 35 | "Home.TabBar.User.Title" = "My"; 36 | 37 | /* 设置 */ 38 | "User.NightMode.Title" = "Night mode"; 39 | "User.Theme.Title" = "Color theme"; 40 | "User.Language.Title" = "Language"; 41 | "User.RemoveCache.Title" = "Remove cache"; 42 | "User.RemoveCache.Alert.SuccessMessage" = "Cache Successfully Cleared"; 43 | "User.WhatsNew.Title" = "Whats New"; 44 | "User.LogOut.Title" = "Log Out"; 45 | "User.Logout.Alert.Message" = "Are you sure want to log out from login?"; 46 | "User.Logout.Alert.ConfirmButton.Title" = "Logout"; 47 | 48 | /* 语言 */ 49 | "Language.Navigation.Title" = "Language"; 50 | /* 主题 */ 51 | "Theme.Navigation.Title" = "Color theme"; 52 | 53 | /* 什么是新的 */ 54 | "WhatsNew.Title" = "Whats New"; 55 | "WhatsNew.Item1.Title" = "MVVM Architecture"; 56 | "WhatsNew.Item1.Subtitle" = "RXSwift and Rx extensions are widely used internally to build functions, making code maintenance easier"; 57 | "WhatsNew.Item2.Title" = "Theme"; 58 | "WhatsNew.Item2.Subtitle" = "You can use two different themes, Light and Dark"; 59 | "WhatsNew.Item3.Title" = "Use SwiftUi to write the interface"; 60 | "WhatsNew.Item3.Subtitle" = "SwiftUi writing interface allows code version control to be better managed, XID can also be used, and story version can be used to pursue speed"; 61 | "WhatsNew.Item4.Title" = "Integration SWInject"; 62 | "WhatsNew.Item4.Subtitle" = "Swinject Help your application split into loosely coupled components that make it easier to develop, test, and maintain"; 63 | "WhatsNew.CompletionButton.Title" = "Continue"; 64 | -------------------------------------------------------------------------------- /Dolphin/Resources/main.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/main.gif -------------------------------------------------------------------------------- /Dolphin/Resources/voice.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangxiang4/dolphin-ios/5f85aae0dc1f0613535abad30513d1c8198fc4ec/Dolphin/Resources/voice.mp3 -------------------------------------------------------------------------------- /Dolphin/Resources/zh-Hans.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | // 2 | // 中文国际化配置 3 | // https://developer.apple.com/documentation/foundation/nsbundle/1417526-developmentlocalization 4 | // Created by wangxiang4 on 2022/12/5. 5 | // Copyright © 2022 dolphin-community. All rights reserved. 6 | // 7 | 8 | /* 通用 */ 9 | "Common.Yes" = "是"; 10 | "Common.No" = "否"; 11 | "Common.OK" = "好的"; 12 | "Common.Cancel" = "取消"; 13 | "Common.Done" = "完成"; 14 | "Common.Back" = "返回"; 15 | "Common.Close" = "关闭"; 16 | "Common.Edit" = "编辑"; 17 | "Common.Next" = "下一步"; 18 | "Common.Skip" = "跳过"; 19 | "Common.Reset" = "重置"; 20 | "Common.Save" = "保存"; 21 | "Common.Delete" = "删除"; 22 | "Common.Search" = "搜索"; 23 | "Common.Success" = "成功"; 24 | "Common.Error" = "错误"; 25 | "Common.NoResults" = "暂无数据"; 26 | 27 | /* 网络连接 */ 28 | "Toast.ConnectionBack.Message" = "连接已恢复"; 29 | "Toast.ConnectionLost.Message" = "网络已断开"; 30 | 31 | /* 主页TabBar */ 32 | "Home.TabBar.Home.Title" = "首页"; 33 | "Home.TabBar.Workbench.Title" = "工作台"; 34 | "Home.TabBar.Message.Title" = "消息"; 35 | "Home.TabBar.User.Title" = "我的"; 36 | 37 | /* 设置 */ 38 | "User.NightMode.Title" = "夜间模式"; 39 | "User.Theme.Title" = "颜色主题"; 40 | "User.Language.Title" = "语言"; 41 | "User.RemoveCache.Title" = "删除缓存"; 42 | "User.RemoveCache.Alert.SuccessMessage" = "成功清除缓存"; 43 | "User.WhatsNew.Title" = "什么是新的"; 44 | "User.LogOut.Title" = "退出"; 45 | "User.Logout.Alert.Message" = "您确定要退出登录吗?"; 46 | "User.Logout.Alert.ConfirmButton.Title" = "退出"; 47 | 48 | /* 语言 */ 49 | "Language.Navigation.Title" = "语言"; 50 | /* 主题 */ 51 | "Theme.Navigation.Title" = "颜色主题"; 52 | 53 | /* 什么是新的 */ 54 | "WhatsNew.Title" = "最近更新"; 55 | "WhatsNew.Item1.Title" = "MVVM架构"; 56 | "WhatsNew.Item1.Subtitle" = "内部大量使用了RXSwift与Rx扩展来构建功能,抽离了视图、模型层内部采用RX进行数据绑定,明确层级职责,让代码维护变得更简单."; 57 | "WhatsNew.Item2.Title" = "主题切换"; 58 | "WhatsNew.Item2.Subtitle" = "强大的主题定制在每一个细节,内置Light和Dark两种的外观主题,以及自定义的颜色主题(默认内置十多种颜色)."; 59 | "WhatsNew.Item3.Title" = "APPLE设备多端运行"; 60 | "WhatsNew.Item3.Subtitle" = "采用了Mac Catalyst技术已适配MacOS、Ios、IpadOS (可在Iphone、Ipad、M系列芯片的MacBook下运行)."; 61 | "WhatsNew.Item4.Title" = "IOC控制反转"; 62 | "WhatsNew.Item4.Subtitle" = "集成Swinject实现了IOC依赖控制反转,帮助您的应用程序拆分为松散耦合的组件,可以更轻松地开发、测试和维护这些组件."; 63 | "WhatsNew.CompletionButton.Title" = "继续"; 64 | -------------------------------------------------------------------------------- /Dolphin/Utils/CommonUtil/ArrayUtil.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 数组工具类 3 | // Created by wangxiang4 on 2022/12/18. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import Foundation 8 | 9 | class ArrayUtil { 10 | 11 | /** 12 | * Return the array is empty. 13 | * 14 | * @param array The array. 15 | * @return {@code true}: yes
{@code false}: no 16 | */ 17 | class func isEmpty(_ arr: [AnyObject]?) -> Bool { 18 | return arr?.count == 0 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /Dolphin/Utils/CommonUtil/PermissionUtil.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 应用权限权限工具 3 | // Created by wangxiang4 on 2022/12/16. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import Foundation 8 | 9 | class PermissionUtil { 10 | 11 | /** 用户登出 */ 12 | static func logout() { 13 | (DIContainer.shared.resolve() as HttpRequest).logout() 14 | User.removeUserInfo() 15 | AuthManager.removeTokenEnhancer() 16 | let application: Application = DIContainer.shared.resolve() 17 | application.window!.rootViewController = LoginViewController(viewModel: LoginViewModel()) 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /Dolphin/Utils/CommonUtil/StrUtil.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 字符串工具类 3 | // Created by wangxiang4 on 2022/12/16. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import Foundation 8 | 9 | class StrUtil { 10 | 11 | /** 12 | * Return whether the string is null or whitespace. 13 | * 14 | * @param s The string. 15 | * @return {@code true}: yes
{@code false}: no 16 | */ 17 | class func isTrimEmpty(_ str: String?) -> Bool { 18 | var s = str 19 | return (str == nil || s?.trim().count == 0) 20 | } 21 | 22 | /** 23 | * Return whether the string is null or 0-length. 24 | * 25 | * @param s The string. 26 | * @return {@code true}: yes
{@code false}: no 27 | */ 28 | class func isEmpty(_ str: String?) -> Bool { 29 | var s = str 30 | return (str == nil || s?.count == 0) 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /Dolphin/Utils/Networking/Api/ResultResponse.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 结果响应模型 3 | // Created by wangxiang4 on 2022/12/7. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import Foundation 8 | import ObjectMapper 9 | 10 | class BaseResultResponse: Mappable { 11 | 12 | /** 13 | * 成功标记 14 | */ 15 | let SUCCESS = 200 16 | 17 | /** 18 | * 失败标记 19 | */ 20 | let FAIL = 500 21 | 22 | /** 23 | * 未认证 24 | */ 25 | let UNAUTH = 401 26 | 27 | /** 28 | * 状态编码 29 | */ 30 | var code: Int? 31 | 32 | /** 33 | * 提示消息 34 | */ 35 | var msg: String? 36 | 37 | /** 38 | * 结果集数量统计 39 | */ 40 | var total: Int? 41 | 42 | required init?(map: Map) {} 43 | init() {} 44 | 45 | func mapping(map: Map) { 46 | code <- map["code"] 47 | msg <- map["msg"] 48 | total <- map["total"] 49 | } 50 | } 51 | 52 | // xxx: ObjectMapper解析泛型对象,必须实现Mappable,由于swift集合类型无法实现Mappable,导致json映射始终为空,目前抽离公共类直接写死,等待官方出解决方案 53 | class BaseResultResponseArray: BaseResultResponse { 54 | 55 | /** 56 | * 结果集 57 | */ 58 | var data: [T]? 59 | 60 | override required init?(map: Map) { super.init(map: map) } 61 | override init() { super.init() } 62 | 63 | override func mapping(map: Map) { 64 | super.mapping(map: map) 65 | 66 | data <- map["data"] 67 | } 68 | 69 | } 70 | 71 | class BaseResultResponseObject: BaseResultResponse { 72 | 73 | /** 74 | * 结果集 75 | */ 76 | var data: T? 77 | 78 | override required init?(map: Map) { super.init(map: map) } 79 | override init() { super.init() } 80 | 81 | override func mapping(map: Map) { 82 | super.mapping(map: map) 83 | 84 | data <- map["data"] 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /Dolphin/Utils/Networking/Exception/ResponseException.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 返回异常处理 3 | // Created by wangxiang4 on 2022/12/15. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import Foundation 8 | import Moya 9 | 10 | // 错误类型 11 | typealias MoyaError = Moya.MoyaError 12 | 13 | class ApiError: Swift.Error { 14 | 15 | var code: Int? 16 | 17 | var errMessage: String? 18 | 19 | init(_ code: Int?, _ errMessage: String?) { 20 | self.code = code 21 | self.errMessage = errMessage 22 | } 23 | } 24 | 25 | class ResponseException { 26 | 27 | class func getRequestError(_ status: Int, _ msg: String?) -> ApiError { 28 | var errMessage = "" 29 | 30 | switch status { 31 | case 401: errMessage = "用户没有权限(令牌、用户名、密码错误)" 32 | case 403: errMessage = "用户得到授权,但是访问是被禁止的!" 33 | case 404: errMessage = "资源不存在" 34 | case 405: errMessage = "操作异常,不允许的请求方法" 35 | case 408: errMessage = "网络请求超时" 36 | case 424: errMessage = "令牌过期,请重新登录!" 37 | PermissionUtil.logout() 38 | case 426: errMessage = "用户名或密码错误或者当前用户不存在" 39 | case 428: errMessage = "验证码错误,请重新输入!" 40 | case 429: errMessage = "请求过频繁" 41 | case 500: errMessage = "服务器错误,请联系管理员!" 42 | case 501: errMessage = "网络未实现" 43 | case 502: errMessage = "网络错误" 44 | case 503: errMessage = "服务器不可用" 45 | case 504: errMessage = "网络超时" 46 | case 505: errMessage = "http版本不支持该请求!" 47 | default: errMessage = StrUtil.isEmpty(msg) ? "操作异常,请联系系统管理员!" : msg! 48 | } 49 | 50 | return ApiError(status, errMessage) 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /DolphinTests/DolphinTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 功能测试 3 | // Created by wangxiang4 on 2022/12/5. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import XCTest 8 | @testable import 海豚生态 9 | 10 | class DolphinTests: XCTestCase { 11 | 12 | override func setUp() { 13 | super.setUp() 14 | // Put setup code here. This method is called before the invocation of each test method in the class. 15 | } 16 | 17 | override func tearDown() { 18 | // Put teardown code here. This method is called after the invocation of each test method in the class. 19 | super.tearDown() 20 | } 21 | 22 | func testExample() { 23 | // This is an example of a functional test case. 24 | // Use XCTAssert and related functions to verify your tests produce the correct results. 25 | } 26 | 27 | func testPerformanceExample() { 28 | // This is an example of a performance test case. 29 | self.measure { 30 | // Put the code you want to measure the time of here. 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /DolphinTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleExecutable 6 | $(EXECUTABLE_NAME) 7 | CFBundleIdentifier 8 | $(PRODUCT_BUNDLE_IDENTIFIER) 9 | CFBundleInfoDictionaryVersion 10 | 1.0 11 | CFBundleName 12 | $(PRODUCT_NAME) 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0.0 17 | CFBundleVersion 18 | 1 19 | 20 | 21 | -------------------------------------------------------------------------------- /DolphinTests/Models/UserTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 用户模型转换测试 3 | // Created by wangxiang4 on 2022/12/5. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import Quick 8 | import Nimble 9 | @testable import 海豚生态 10 | 11 | class UserTests: QuickSpec { 12 | 13 | override func spec() { 14 | 15 | let name = "admin" 16 | let password = "123456" 17 | 18 | describe("Test from JSON Mapper") { 19 | it("User") { 20 | let data: [String: Any] = [ "userName": name, "password": password ] 21 | let user = User(JSON: data) 22 | 23 | expect(user?.userName) == name 24 | expect(user?.password) == password 25 | 26 | } 27 | } 28 | 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /DolphinTests/Modules/User/UserViewModelTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // 用户模块测试 3 | // Created by wangxiang4 on 2022/12/5. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import Quick 8 | import Nimble 9 | import RxSwift 10 | @testable import 海豚生态 11 | 12 | class UserViewModelTests: QuickSpec { 13 | 14 | override func spec() { 15 | 16 | beforeEach { 17 | // todo: 18 | } 19 | 20 | afterEach { 21 | // todo: 22 | } 23 | 24 | describe("test user") { 25 | it("Test") { 26 | // todp: 27 | } 28 | } 29 | 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /DolphinUITests/DolphinUITests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ui界面测试 3 | // Created by wangxiang4 on 2022/12/5. 4 | // Copyright © 2022 dolphin-community. All rights reserved. 5 | // 6 | 7 | import XCTest 8 | 9 | class DolphinUITests: XCTestCase { 10 | 11 | override func setUp() { 12 | super.setUp() 13 | 14 | // Put setup code here. This method is called before the invocation of each test method in the class. 15 | 16 | // In UI tests it is usually best to stop immediately when a failure occurs. 17 | continueAfterFailure = false 18 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 19 | 20 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 21 | let app = XCUIApplication() 22 | setupSnapshot(app) 23 | app.launch() 24 | } 25 | 26 | override func tearDown() { 27 | // Put teardown code here. This method is called after the invocation of each test method in the class. 28 | super.tearDown() 29 | } 30 | 31 | // 用户场景截图 32 | func testScreenshotUser() { 33 | let element = XCUIApplication().children(matching: .window).element(boundBy: 0).children(matching: .other).element.children(matching: .other).element 34 | element.children(matching: .other).element(boundBy: 3).tap() 35 | sleep(1) 36 | element.children(matching: .other).element(boundBy: 1).tap() 37 | sleep(1) 38 | element.children(matching: .other).element(boundBy: 3).tap() 39 | 40 | sleep(5) 41 | snapshot("03_user_screen") 42 | } 43 | 44 | // 首页场景截图 45 | func testScreenshotHome() { 46 | sleep(5) 47 | snapshot("01_Home") 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /DolphinUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleExecutable 6 | $(EXECUTABLE_NAME) 7 | CFBundleIdentifier 8 | $(PRODUCT_BUNDLE_IDENTIFIER) 9 | CFBundleInfoDictionaryVersion 10 | 1.0 11 | CFBundleName 12 | $(PRODUCT_NAME) 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0.0 17 | CFBundleVersion 18 | 1 19 | 20 | 21 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | # 隐示冻结对象重用冻结的对象只会创建一次,类似于单例 2 | # frozen_string_literal: true 3 | 4 | # 设置安装源 5 | source "https://rubygems.org" 6 | 7 | gem 'cocoapods' # https://github.com/CocoaPods/CocoaPods 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023-PRESENT Dolphin Ecology 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | --------------------------------------------------------------------------------