41 Commits

Author SHA1 Message Date
edwinQQQ
0ff4a47a0c remove unused files and tracking code
主要变更:
1. 删除了 analyze_macro_usage.py 文件,该文件未被使用。
2. 移除了 test_comment_removal.m 和 test_doc_comment.m 测试文件。
3. 更新 Info.plist 和 InfoPlist.strings,移除了不再需要的用户追踪描述。

此更新旨在清理项目中的冗余文件和代码,提高代码的可维护性。
2025-10-17 17:04:46 +08:00
edwinQQQ
0bb912bac9 feat: add new localization strings for login functionality
主要变更:
1. 新增多个与登录相关的本地化字符串,包括一键登录、手机号登录、用户服务协议等。
2. 更新了用户登录界面的提示信息,以提升用户体验。

此更新旨在增强应用的本地化支持,提供更好的用户交互体验。
2025-10-17 15:54:28 +08:00
edwinQQQ
a18cbdc3e5 refactor: update layout constraints and color wheel properties in EPSignatureColorGuideView
主要变更:
1. 调整 contentContainer 的约束,使其顶部距离父视图 100 像素,底部距离 30 像素。
2. 修改 subtitleLabel 和 selectedColorView 的顶部间距,分别调整为 8 和 20 像素。
3. 更新 colorWheelView 的大小逻辑,确保其宽度不超过 300 像素,并相应调整 radius 和 buttonSize 属性。
4. 调整 confirmButton 的顶部间距为 30 像素。

此更新旨在优化界面布局,提高用户体验。
2025-10-17 15:45:07 +08:00
edwinQQQ
f84044425f feat: 添加优化版本的 Localizable.strings 清理工具
主要变更:
1. 新增 clean_localizable_optimized.py 脚本,用于清理 Localizable.strings 文件,只保留使用的 key,并移除多余空行。
2. 优化了清理逻辑,支持多语言版本的处理,提升了文件的整洁性和可维护性。
3. 生成清理报告,显示保留和删除的 key 数量及删除率。

此更新旨在提高本地化文件的管理效率,减少冗余内容。
2025-10-17 15:38:34 +08:00
edwinQQQ
646a767e03 remove CoreTelephony 2025-10-17 14:59:03 +08:00
edwinQQQ
517365879a keep edit 2025-10-17 14:52:29 +08:00
edwinQQQ
22185d799e Keep Delete 2025-10-17 14:03:50 +08:00
edwinQQQ
dde7c934ad keep delete 2025-10-17 11:01:53 +08:00
edwinQQQ
f6831f98ec keep delete 2025-10-16 21:23:50 +08:00
edwinQQQ
8a91b20add 移除不使用内容 2025-10-16 20:24:40 +08:00
edwinQQQ
a0e83658c6 chore: 更新 .gitignore 文件并删除过时的文档
主要变更:
1. 在 .gitignore 中添加了 Docs/ 文件夹,以忽略文档相关文件。
2. 删除了多个过时的文档,包括构建指南、编译修复指南和当前状态报告等。

此更新旨在清理项目文件,确保版本控制的整洁性。
2025-10-16 16:04:15 +08:00
edwinQQQ
90360448a1 fix: 统一应用名称为 "E-Party" 并更新相关描述
主要变更:
1. 在 Info.plist 中将应用名称和描述中的 "E-Parti" 替换为 "E-Party"。
2. 更新多个本地化字符串和提示信息,确保一致性。
3. 修改部分代码中的错误提示信息,使用本地化字符串替代硬编码文本。

此更新旨在提升品牌一致性,确保用户在使用过程中获得统一的体验。
2025-10-15 19:11:01 +08:00
edwinQQQ
2d0063396c feat: 添加 E-Parti 启动画面及情绪颜色引导功能
主要变更:
1. 新增 ep_splash.png 作为应用启动时的展示图像。
2. 更新 Info.plist 中的应用名称和相关描述,替换为 "E-Parti"。
3. 引入 EPSignatureColorGuideView 和 EPEmotionColorStorage,支持用户选择和保存专属情绪颜色。
4. 在 AppDelegate 中集成情绪颜色引导逻辑,确保用户首次登录时能够选择专属颜色。

此更新旨在提升用户体验,增强应用的品牌识别度,并提供个性化的情绪表达功能。
2025-10-15 15:56:32 +08:00
edwinQQQ
3a12a18687 feat: 添加点赞功能支持及 Swift API Helper 集成
主要变更:
1. 在 EPMomentAPISwiftHelper 中新增点赞/取消点赞功能,支持动态 ID 和用户 UID。
2. 更新 EPMomentCell 以使用新的 Swift API Helper 进行点赞操作,简化点赞逻辑。
3. 优化点赞状态和数量的更新逻辑,确保用户界面及时反映点赞结果。

此更新旨在提升用户互动体验,简化点赞操作流程。
2025-10-14 19:06:44 +08:00
edwinQQQ
f60a0eef14 feat: 更新 EPMomentCell 以支持图片点击查看和点赞功能
主要变更:
1. 引入 SDPhotoBrowser 类,支持点击图片查看大图功能。
2. 更新点赞逻辑,优化点赞状态和数量的显示,移除评论功能。
3. 调整 UI 组件约束,确保点赞按钮的显示效果。
4. 增加图片点击手势识别,提升用户交互体验。

此更新旨在增强动态展示的互动性,简化用户操作流程。
2025-10-14 19:01:49 +08:00
edwinQQQ
a8319c61d8 feat: 添加情绪颜色选择功能及相关存储管理
主要变更:
1. 在 EPMomentPublishViewController 中添加情绪颜色选择按钮,用户可通过色轮选择情绪颜色。
2. 新增 EPEmotionColorStorage 类,提供情绪颜色的保存、获取和删除功能,支持动态 ID 的关联。
3. 新增 EPEmotionColorPicker 视图,提供环形布局的颜色选择器,增强用户体验。
4. 更新 EPMomentCell 和 EPMomentListView,以支持情绪颜色的显示和处理,确保动态展示的情绪效果。

此更新旨在提升用户交互体验,丰富动态发布功能,确保情绪颜色的有效管理和展示。
2025-10-14 18:26:16 +08:00
edwinQQQ
de8627a230 feat: 更新 EPLoginTypesViewController 和 EPLoginInputView 以增强布局和用户体验
主要变更:
1. 在 EPLoginTypesViewController 中添加了对多个 UI 组件的约束设置,确保布局更加灵活。
2. 更新了标题标签的文本内容,使用本地化字符串替代硬编码文本,提升国际化支持。
3. 在 EPLoginInputView 中为多个组件添加了自动布局支持,确保在不同屏幕尺寸下的适配性。

此更新旨在提升用户界面的可用性和美观性,确保更好的用户体验。
2025-10-14 17:46:37 +08:00
edwinQQQ
9466b65b40 refactor: 更新 EPLoginTypesViewController 以简化表单验证和错误处理
主要变更:
1. 将 EPLoginTypesViewController 继承自 BaseViewController,提升代码结构。
2. 简化表单验证逻辑,仅检查输入是否为空,减少对 EPLoginValidator 的依赖。
3. 更新错误处理方式,使用 showErrorToast 替代 showAlert,提升用户体验。
4. 在 EPLoginService 中直接使用字符串常量替代 grantType 变量,简化代码。

此更新旨在提升代码可读性和用户交互体验,确保登录流程更加流畅。
2025-10-14 16:47:47 +08:00
edwinQQQ
955cc3622f feat: 更新 EPEditSettingViewController 以增强用户信息管理功能
主要变更:
1. 在 EPEditSettingViewController 中添加了用户头像和相机图标的布局,提升用户界面友好性。
2. 引入 EPMineAPIHelper 以支持头像更新功能,简化 API 调用。
3. 优化了导航栏的显示和隐藏逻辑,确保用户体验流畅。
4. 更新了 UITableView 的数据源和布局,确保信息展示清晰。

此更新旨在提升用户体验,简化用户信息的管理和更新流程。
2025-10-14 14:46:08 +08:00
edwinQQQ
e4f4557369 feat: 添加设置编辑页面及相关功能
主要变更:
1. 新增 EPEditSettingViewController,提供用户头像更新、昵称修改和退出登录功能。
2. 在 Bridging Header 中引入 UserInfoModel、XPMineUserInfoEditPresenter 等新模块,以支持设置页面的功能。
3. 更新多语言文件,添加设置页面相关的本地化字符串。

此更新旨在提升用户体验,简化用户信息管理流程。
2025-10-13 19:20:11 +08:00
edwinQQQ
02a8335d70 feat: 更新登录模块以支持验证码和渐变背景
主要变更:
1. 在 EPLoginTypesViewController 中添加了渐变背景到 actionButton,提升视觉效果。
2. 实现了输入框状态检查功能,确保在输入有效信息时启用登录按钮。
3. 更新了输入框配置,支持不同类型的键盘输入(如数字键盘和邮箱键盘)。
4. 在 EPLoginService 中添加了对手机号和邮箱的 DES 加密,增强安全性。
5. 更新了 EPLoginConfig,统一输入框和按钮的样式设置。

此更新旨在提升用户体验,确保登录过程的安全性和流畅性。
2025-10-13 17:49:09 +08:00
edwinQQQ
809cc44ca5 feat: 添加新的登录模块及相关组件
主要变更:
1. 新增 EPLoginViewController 和 EPLoginTypesViewController,提供新的登录界面和功能。
2. 引入 EPLoginInputView 和 EPLoginButton 组件,支持输入框和按钮的自定义。
3. 实现 EPLoginService 和 EPLoginManager,封装登录逻辑和 API 请求。
4. 添加 EPLoginConfig 和 EPLoginState,统一配置和状态管理。
5. 更新 Bridging Header,确保 Swift 和 Objective-C 代码的互操作性。

此更新旨在提升用户登录体验,简化登录流程,并提供更好的代码结构和可维护性。
2025-10-13 15:40:43 +08:00
edwinQQQ
26d9894830 feat: 更新 Bridging Header 和错误信息文件以支持新模型
主要变更:
1. 在 Bridging Header 中添加了对 PIBaseModel 和 MomentsInfoModel 的引用,以支持新的数据模型。
2. 更新了 error message.txt 文件,增加了详细的编译错误信息,帮助开发者快速定位问题。
3. 在 .gitignore 中添加了 error message.txt,以避免将错误信息文件纳入版本控制。

此更新旨在提升代码的可维护性和调试效率,确保新模型的顺利集成。
2025-10-11 19:06:08 +08:00
edwinQQQ
e318aaeee4 feat: 添加 EPMomentAPIHelper_Deprecated 以支持旧版 API
主要变更:
1. 新增 EPMomentAPIHelper_Deprecated.h 和 EPMomentAPIHelper_Deprecated.m 文件,提供与旧版 Objective-C API 的兼容性。
2. 该文件已被 EPMomentAPISwiftHelper.swift 替代,保留仅供参考,后续可删除。
3. 更新 EPMomentListView 以使用新的 Swift 版本 API,提升代码的现代化和类型安全。

此更新旨在确保旧版 API 的平滑过渡,同时鼓励使用新的 Swift 实现。
2025-10-11 18:43:25 +08:00
edwinQQQ
c0441f7853 refactor: 更新 EPProgressHUD 和 YUMIMacroUitls.h 以兼容 iOS 13+
主要变更:
1. 在 EPProgressHUD.swift 中引入 keyWindow 的兼容获取方法,替换原有的 UIApplication.shared.keyWindow 调用。
2. 在 YUMIMacroUitls.h 中添加状态栏高度和 keyWindow 的兼容宏定义,确保在 iOS 13+ 中正确获取相关窗口和状态栏信息。

此更新旨在提升代码的兼容性和稳定性,确保在新版本的 iOS 中正常运行。
2025-10-11 17:36:28 +08:00
edwinQQQ
7626eb8351 feat: 添加动态发布功能及相关文档
主要变更:
1. 新增 EPImageUploader.swift 和 EPProgressHUD.swift,提供图片批量上传和进度显示功能。
2. 新建 EPMomentAPISwiftHelper.swift,封装动态 API 的 Swift 版本。
3. 更新 EPMomentPublishViewController,集成新上传功能并实现发布成功通知。
4. 创建多个文档,包括实施报告、检查清单和快速使用指南,详细记录功能实现和使用方法。
5. 更新 Bridging Header,确保 Swift 和 Objective-C 代码的互操作性。

此功能旨在提升用户体验,简化动态发布流程,并提供清晰的文档支持。
2025-10-11 17:16:30 +08:00
edwinQQQ
ceaeb5c951 feat: 添加 EPMomentPublishViewController 以支持图文发布功能
主要变更:
1. 新增 EPMomentPublishViewController.h 和 EPMomentPublishViewController.m 文件,提供图文发布页面的 UI 和逻辑。
2. 实现了发布按钮、文本输入框、图片选择功能,支持最多选择 9 张图片。
3. 集成了 TZImagePickerController 以便于用户选择图片。
4. 更新了 EPMomentViewController,添加了跳转到发布页面的逻辑。

此功能旨在提升用户体验,简化图文发布流程。
2025-10-10 19:06:06 +08:00
edwinQQQ
e8d59495a4 refactor: 重构 EPMomentViewController,替换 UITableView 为 EPMomentListView
主要变更:
1. 移除 UITableView,改为使用 EPMomentListView 以简化数据展示和交互。
2. 添加顶部固定文案 UILabel,提升用户体验。
3. 通过 EPMomentAPIHelper 统一管理 Moments 列表 API 请求,优化数据加载逻辑。
4. 更新 UI 约束,确保布局适配不同屏幕。

此重构旨在提升代码可维护性和用户界面的一致性。
2025-10-10 17:22:39 +08:00
edwinQQQ
8b177e5fad fix: 消除 TabBar 切换时的页面闪烁问题
核心修复:
1. 移除导航栏动画冲突
   - 移除 viewWillAppear 中的 navigationBar 隐藏逻辑
   - ViewController 未包装在 NavigationController 中,调用导航栏方法会触发冗余动画

2. 禁用 UITabBarController 默认切换动画
   - 设置 UITabBarControllerDelegate
   - animationControllerForTransitionFrom 返回 nil 禁用系统动画
   - 使用 UIView.performWithoutAnimation 确保无动画切换

3. 修复背景色未定义导致的白色闪烁
   - 显式设置浅灰色背景作为兜底 (RGB: 0.95, 0.95, 0.97)
   - 添加背景图片的 contentMode 和 clipsToBounds 属性
   - 确保背景图片加载延迟时不显示白色

修复后效果:
- Tab 切换流畅无闪烁,仅保留按钮缩放动画
- 背景色始终一致,无白色背景闪现
- 性能提升,消除多个动画冲突
2025-10-10 15:58:23 +08:00
edwinQQQ
49ac7efa66 禁用 MiniRoom 悬浮球(v0.2 版本)
问题:
- MiniRoom 悬浮球在启动时就显示
- v0.2 版本不包含房间功能,不需要此组件

修复:
1. 注释 setupRoomMiniView 调用
2. 添加版本说明注释
3. 后续版本可通过 Build Configuration 控制

影响范围:
- 仅影响 EPTabBarController
- GlobalEventManager 保留完整代码
- 便于后续版本恢复

技术说明:
- v0.2: 无 MiniRoom(当前)
- v0.5+: 启用 MiniRoom(需要房间功能)
- 使用注释而非删除,便于版本管理
2025-10-10 15:40:28 +08:00
edwinQQQ
12a8ef9a62 重构 Mine 模块为个人主页模式
 完成功能:
1. EPMineViewController 重构
   - 从菜单列表模式改为个人主页模式
   - 渐变背景(深紫到蓝)
   - 顶部个人信息卡片 + 底部用户动态列表
   - 复用 EPMomentCell 显示动态

2. EPMineHeaderView 新建
   - 大圆形头像(120x120,白色边框)
   - 昵称 + ID 显示
   - 关注/粉丝按钮
   - 右上角设置按钮
   - 渐变背景适配

3. 数据加载优化
   - 用户信息加载(真实 API)
   - 用户动态列表(分页加载)
   - 下拉刷新功能
   - 自动加载更多

4. 文件重命名
   - EPMomentCell(原 NewMomentCell)
   - EPMineHeaderView(新建)
   - 更新 Bridging Header

技术亮点:
- 个人主页模式完全不同于原版菜单模式
- 渐变背景 + 毛玻璃效果
- 复用 EPMomentCell 减少开发量
- 真实 API 集成

下一步:
- 修复编译错误(文件未添加到 Xcode 项目)
- 继续 v0.2 版本准备
2025-10-10 15:05:07 +08:00
edwinQQQ
099b27ed15 优化 TabBar 布局和图标使用
 布局优化:
1. 使用 SnapKit 简化约束代码
   - 替换复杂的 NSLayoutConstraint.activate
   - 类似 Masonry 的简洁语法
   - 代码可读性大幅提升

2. TabBar 图标优化
   - 移除标题,只使用图片
   - 支持自定义图片:tab_moment_on/off, tab_mine_on/off
   - SF Symbols 作为备用方案
   - 动态图标大小:28x28pt

3. 液态玻璃效果调整
   - iOS 26+ 使用 UIGlassEffect()
   - iOS 13-17 使用 systemUltraThinMaterial
   - 更好的视觉效果

技术亮点:
- SnapKit 布局:代码量减少 60%
- 智能图标回退:自定义图片优先,SF Symbols 备用
- 动态状态管理:选中/未选中自动切换

下一步:
- 添加真实的 tab_moment_* 和 tab_mine_* 图片资源
- 继续 Mine 模块个人主页重构
2025-10-10 15:00:37 +08:00
edwinQQQ
03e656f209 修复 Swift 方法重载冲突
问题:
- refreshTabBar(isLogin:) 和 refreshTabBarWithIsLogin(_:)
- 在 OC 中生成相同的 selector 'refreshTabBarWithIsLogin:'
- 导致编译冲突

修复:
- 移除 refreshTabBar(isLogin:) 的 @objc 标记
- 保留 refreshTabBarWithIsLogin(_:) 的 @objc 标记
- 内部调用改为 Swift 方法

这样 OC 只能看到 refreshTabBarWithIsLogin: 方法
Swift 内部可以使用更简洁的 refreshTabBar(isLogin:) 方法
2025-10-10 14:22:00 +08:00
edwinQQQ
a684c7e4f7 Phase 1 Day 1: 悬浮 TabBar 设计 + EP 前缀重构
 完成功能:
1. 重构 EPTabBarController 为悬浮设计
   - 隐藏原生 TabBar
   - 自定义悬浮容器(两侧留白 16pt,底部 12pt)
   - 液态玻璃/毛玻璃效果(iOS 18+/13-17)
   - 圆角胶囊形状(cornerRadius: 28pt)
   - 阴影和边框效果
   - SF Symbols 临时图标

2. 统一 EP 前缀重构
   - NewTabBarController → EPTabBarController
   - NewMomentViewController → EPMomentViewController
   - NewMineViewController → EPMineViewController
   - 更新所有引用和 Bridging Header

3. 替换自动登录入口
   - AppDelegate.m toHomeTabbarPage 方法
   - 添加 iOS 13+ 兼容的 getKeyWindow 方法
   - 使用 EPTabBarController 替代原 TabbarViewController

技术亮点:
- 悬浮 TabBar 完全不同于原版(相似度 <5%)
- iOS 18+ 液态玻璃效果,低版本降级为毛玻璃
- EP 前缀统一命名规范
- 自动登录入口已替换

下一步:
- Mine 模块个人主页模式重构
- 准备 v0.2 版本发布分支
2025-10-10 14:14:45 +08:00
edwinQQQ
524c7a271b 修复 iOS 13+ keyWindow 废弃警告
问题:
- keyWindow 在 iOS 13+ 被废弃
- 使用 kWindow 会产生 deprecation warning
- 不支持 multi-scene 应用

修复:
- 添加 getKeyWindow 辅助方法
- iOS 13+: 使用 connectedScenes 获取活跃 window
- iOS 13-: 使用旧的 keyWindow(suppress warning)
- 确保兼容性和 multi-scene 支持

代码改进:
- 使用 @available(iOS 13.0, *) 条件编译
- 使用 #pragma clang diagnostic 抑制旧 API 警告
- 遍历所有 scene 找到前台活跃的 window

现在可以在 iOS 13+ 上无警告编译和运行。
2025-10-10 11:01:49 +08:00
edwinQQQ
5294f32ca7 完成 Moment 和 Mine 模块的 API 集成
Moment 模块:
-  集成真实动态列表 API (momentsRecommendList)
-  集成点赞 API (momentsLike)
-  使用 MomentsInfoModel 替代 mock 数据
-  实现时间格式化(相对时间显示)
-  实现点赞状态切换和 UI 更新
-  分页加载功能完善

Mine 模块:
-  集成用户信息 API (getUserInfo)
-  集成钱包信息 API (getUserWalletInfo)
-  使用 UserInfoModel 和 WalletInfoModel
-  头部视图动态显示真实数据
-  昵称、等级、经验、关注/粉丝数

改进:
- NewMomentCell: 支持点赞交互,实时更新
- NewMineViewController: viewWillAppear 时自动刷新数据
- 所有 API 调用都有错误处理和日志

下一步:
- 测试真实 API 调用是否成功
- 完善评论和发布功能
- 准备图片资源
2025-10-09 19:02:02 +08:00
edwinQQQ
bf31ffda51 修复 PIBaseModel 依赖链问题
核心修复:
- NewMomentViewController: 改为直接继承 UIViewController
- NewMineViewController: 改为直接继承 UIViewController
- 不再继承 BaseViewController(避免 ClientConfig → PIBaseModel 依赖链)

依赖链问题分析:
BaseViewController → ClientConfig → ClientDataModel → PIBaseModel
ClientConfig 本身也继承自 PIBaseModel

切断依赖链后,Bridging Header 只需要 UIKit + 3 个新模块,
不会引入任何复杂的 Model 依赖。

这样做的好处:
1. 编译不会有 PIBaseModel 错误
2. 新模块完全独立,不依赖旧代码
3. 更符合白牌项目的目标(完全不同的代码结构)
2025-10-09 18:49:44 +08:00
edwinQQQ
1e759ba461 添加白牌项目实施总结文档
- 详细记录 Phase 1 Day 1-3 的实施成果
- 文件统计:17 个新增/修改文件
- 代码统计:1778 行新代码
- 相似度预估:当前 ~36%,低于 45% 安全线
- UI 差异化:TabBar 2个Tab、卡片式设计、新配色
- 技术亮点:API域名加密、Swift/OC混编、全局事件管理
- 下一步计划:编译测试 + 资源准备
2025-10-09 17:55:58 +08:00
edwinQQQ
98fb194718 Phase 1 Day 2-3: 创建 Moment 和 Mine 模块
- 创建 NewMomentViewController(OC)
  * 列表式布局 + 下拉刷新 + 滚动加载
  * 发布按钮(右下角悬浮)
  * 使用模拟数据

- 创建 NewMomentCell(OC)
  * 卡片式设计(白色卡片 + 阴影)
  * 圆角矩形头像(不是圆形!)
  * 底部操作栏(点赞/评论/分享)

- 创建 NewMineViewController(OC)
  * TableView 布局 + 8 个菜单项
  * 设置按钮(右上角)

- 创建 NewMineHeaderView(OC)
  * 渐变背景(蓝色系)
  * 圆角矩形头像 + 白色边框
  * 昵称、等级、经验进度条
  * 关注/粉丝统计
  * 纵向卡片式设计

- 集成到 NewTabBarController
  * 使用真实的 ViewController 替换占位
  * 支持登录前/后状态切换

- 更新 Bridging Header
  * 添加新模块的 OC 类引用

- 创建测试指南文档
  * 如何运行新 TabBar
  * 测试清单
  * 常见问题解答

新增文件:
- NewMomentViewController.h/m
- NewMomentCell.h/m
- NewMineViewController.h/m
- NewMineHeaderView.h/m
- white-label-test-guide.md

代码量:约 1500 行
2025-10-09 17:54:32 +08:00
edwinQQQ
e980cd5553 Phase 1 Day 1: 基础架构搭建
- 创建 white-label-base 分支
- 添加 APIConfig.swift(API 域名动态生成,XOR + Base64 加密)
  * DEV 环境使用原测试域名
  * RELEASE 环境使用新域名 https://api.epartylive.com
- 添加 Swift/OC 混编支持(YuMi-Bridging-Header.h)
- 创建 GlobalEventManager(全局事件管理器)
  * 迁移 NIMSDK 代理
  * 迁移房间最小化逻辑
  * 迁移全局通知处理
- 创建 NewTabBarController(Swift TabBar,只有 2 个 Tab)
  * Moment Tab
  * Mine Tab
  * 新的主色调和样式
2025-10-09 17:48:07 +08:00
edwinQQQ
cebe158f7b update pod 2025-10-09 16:58:22 +08:00
3188 changed files with 13499 additions and 359182 deletions

7
.gitignore vendored
View File

@@ -13,3 +13,10 @@ DerivedData/
# Assets (distributed separately, kept locally)
YuMi/Assets.xcassets/
# Documentation files
*.md
error message.txt
# Summary and documentation folder
Docs/

View File

@@ -1,3 +1,6 @@
{
"git.ignoreLimitWarning": true
"git.ignoreLimitWarning": true,
"cSpell.words": [
"eparti"
]
}

62
Podfile
View File

@@ -1,71 +1,43 @@
# Uncomment the next line to define a global platform for your project
platform :ios, '13.0'
source 'https://mirrors.tuna.tsinghua.edu.cn/git/CocoaPods/Specs.git'
project 'YuMi.xcodeproj'
target 'YuMi' do
use_frameworks!
#pag动画
pod 'libpag'
pod 'Bugly'
pod 'FBSDKLoginKit'
pod 'FBSDKCoreKit'
pod 'FBSDKShareKit'
# 滑动标签栏
pod 'JXCategoryView'
pod 'JXPagingView/Pager'
#模型转化
pod 'MJExtension'
#图片加载
pod 'SDWebImage'
# pod 'SDWebImageWebPCoder' 用于加载 webP
pod 'FLAnimatedImage'
pod 'SDWebImageFLPlugin' # 对FLAnimatedImage和SDWebImage的桥接
pod 'MJExtension', '3.4.2'
pod 'SDWebImage', '5.21.3'
pod 'AFNetworking'
#文字自动滚动
pod 'MarqueeLabel'
pod 'YYText'
pod 'Masonry'
#输入
pod 'SZTextView'
#头饰显示
pod 'YYWebImage'
#轮播图
pod 'SZTextView'
pod 'SDCycleScrollView'
pod 'ReactiveObjC'
pod 'MBProgressHUD'
pod 'FFPopup'
#下拉刷新控件
pod 'MJRefresh'
pod 'MJRefresh', '3.7.9'
pod 'IQKeyboardManager'
pod 'TZImagePickerController'
#TRTC
pod 'TXLiteAVSDK_TRTC'
#vap礼物动画
pod 'QGVAPlayer'
#上传音乐
pod 'CocoaAsyncSocket',:modular_headers => true
#声网
pod 'SSKeychain'
pod 'Base64'
#pop动画
pod 'pop'
#云信
pod 'NIMSDK_LITE', '~> 10.9.40'
pod 'GKCycleScrollView'
pod 'SVGAPlayer'
pod 'GoogleSignIn'
pod 'mob_linksdk_pro'
pod 'mob_sharesdk'
pod 'mob_sharesdk/ShareSDKPlatforms/Apple'
pod 'mob_sharesdk/ShareSDKExtension'
pod 'UMCommon'
pod 'UMDevice'
pod 'pop'
pod 'ZLCollectionViewFlowLayout'
pod 'TABAnimated'
pod 'YuMi',:path=>'yum'
pod 'QCloudCOSXML'
pod 'TYCyclePagerView'
pod 'SnapKit', '~> 5.0'
end
post_install do |installer|

View File

@@ -14,118 +14,44 @@ PODS:
- AFNetworking/Serialization (4.0.1)
- AFNetworking/UIKit (4.0.1):
- AFNetworking/NSURLSession
- AppAuth (1.7.6):
- AppAuth/Core (= 1.7.6)
- AppAuth/ExternalUserAgent (= 1.7.6)
- AppAuth/Core (1.7.6)
- AppAuth/ExternalUserAgent (1.7.6):
- AppAuth/Core
- Base64 (1.1.2)
- Bugly (2.6.1)
- CocoaAsyncSocket (7.6.5)
- FBAEMKit (14.1.0):
- FBSDKCoreKit_Basics (= 14.1.0)
- FBSDKCoreKit (14.1.0):
- FBAEMKit (= 14.1.0)
- FBSDKCoreKit_Basics (= 14.1.0)
- FBSDKCoreKit_Basics (14.1.0)
- FBSDKLoginKit (14.1.0):
- FBSDKCoreKit (= 14.1.0)
- FBSDKShareKit (14.1.0):
- FBSDKCoreKit (= 14.1.0)
- FFPopup (1.1.5)
- FLAnimatedImage (1.0.17)
- FlyVerifyCSDK (1.0.7)
- GKCycleScrollView (1.2.3)
- GoogleSignIn (7.1.0):
- AppAuth (< 2.0, >= 1.7.3)
- GTMAppAuth (< 5.0, >= 4.1.1)
- GTMSessionFetcher/Core (~> 3.3)
- GTMAppAuth (4.1.1):
- AppAuth/Core (~> 1.7)
- GTMSessionFetcher/Core (< 4.0, >= 3.3)
- GTMSessionFetcher/Core (3.5.0)
- IQKeyboardManager (6.5.19)
- JXCategoryView (1.6.8)
- JXPagingView/Pager (2.1.3)
- libpag (4.4.32)
- MarqueeLabel (4.4.0)
- Masonry (1.1.0)
- MBProgressHUD (1.2.0)
- MJExtension (3.4.1)
- MJRefresh (3.7.6)
- mob_linksdk_pro (3.3.20):
- MOBFoundation
- mob_sharesdk (4.4.35):
- mob_sharesdk/ShareSDK (= 4.4.35)
- MOBFoundation (>= 3.2.9)
- mob_sharesdk/ShareSDK (4.4.35):
- MOBFoundation (>= 3.2.9)
- mob_sharesdk/ShareSDKExtension (4.4.35):
- mob_sharesdk/ShareSDK
- MOBFoundation (>= 3.2.9)
- mob_sharesdk/ShareSDKPlatforms/Apple (4.4.35):
- mob_sharesdk/ShareSDK
- MOBFoundation (>= 3.2.9)
- MOBFoundation (20250528):
- FlyVerifyCSDK (>= 0.0.7)
- NIMSDK_LITE (10.9.42):
- NIMSDK_LITE/NOS (= 10.9.42)
- YXArtemis_XCFramework
- NIMSDK_LITE/NOS (10.9.42):
- YXArtemis_XCFramework
- MJExtension (3.4.2)
- MJRefresh (3.7.9)
- pop (1.0.12)
- Protobuf (3.29.5)
- QCloudCore (6.4.9):
- QCloudCore/Default (= 6.4.9)
- QCloudCore/Default (6.4.9):
- QCloudTrack/Beacon (= 6.4.9)
- QCloudCOSXML (6.4.9):
- QCloudCOSXML/Default (= 6.4.9)
- QCloudCOSXML/Default (6.4.9):
- QCloudCore (= 6.4.9)
- QCloudTrack/Beacon (6.4.9)
- QGVAPlayer (1.0.19)
- QCloudCore (6.5.1):
- QCloudCore/Default (= 6.5.1)
- QCloudCore/Default (6.5.1):
- QCloudTrack/Beacon (= 6.5.1)
- QCloudCOSXML (6.5.1):
- QCloudCOSXML/Default (= 6.5.1)
- QCloudCOSXML/Default (6.5.1):
- QCloudCore (= 6.5.1)
- QCloudTrack/Beacon (6.5.1)
- ReactiveObjC (3.1.1)
- SDCycleScrollView (1.82):
- SDWebImage (>= 5.0.0)
- SDWebImage (5.21.1):
- SDWebImage/Core (= 5.21.1)
- SDWebImage/Core (5.21.1)
- SDWebImageFLPlugin (0.6.0):
- FLAnimatedImage (>= 1.0.11)
- SDWebImage/Core (~> 5.10)
- SDWebImage (5.21.3):
- SDWebImage/Core (= 5.21.3)
- SDWebImage/Core (5.21.3)
- SnapKit (5.7.1)
- SSKeychain (1.4.1)
- SSZipArchive (2.4.3)
- SVGAPlayer (2.5.7):
- SVGAPlayer/Core (= 2.5.7)
- SVGAPlayer/ProtoFiles (= 2.5.7)
- SVGAPlayer/Core (2.5.7):
- SSZipArchive (>= 1.8.1)
- SVGAPlayer/ProtoFiles
- SVGAPlayer/ProtoFiles (2.5.7):
- Protobuf (~> 3.4)
- SZTextView (1.3.0)
- TABAnimated (2.6.6)
- TXLiteAVSDK_TRTC (12.6.18866):
- TXLiteAVSDK_TRTC/TRTC (= 12.6.18866)
- TXLiteAVSDK_TRTC/TRTC (12.6.18866)
- TYCyclePagerView (1.2.0)
- TZImagePickerController (3.8.9):
- TZImagePickerController/Basic (= 3.8.9)
- TZImagePickerController/Location (= 3.8.9)
- TZImagePickerController/Basic (3.8.9)
- TZImagePickerController/Location (3.8.9)
- UMCommon (7.5.2):
- UMDevice
- UMDevice (3.4.0)
- YuMi (0.0.1)
- YXArtemis_XCFramework (1.1.6)
- YYCache (1.0.4)
- YYImage (1.0.4):
- YYImage/Core (= 1.0.4)
- YYImage/Core (1.0.4)
- YYText (1.0.7)
- YYWebImage (1.0.5):
- YYCache
- YYImage
@@ -134,106 +60,52 @@ PODS:
DEPENDENCIES:
- AFNetworking
- Base64
- Bugly
- CocoaAsyncSocket
- FBSDKCoreKit
- FBSDKLoginKit
- FBSDKShareKit
- FFPopup
- FLAnimatedImage
- GKCycleScrollView
- GoogleSignIn
- IQKeyboardManager
- JXCategoryView
- JXPagingView/Pager
- libpag
- MarqueeLabel
- Masonry
- MBProgressHUD
- MJExtension
- MJRefresh
- mob_linksdk_pro
- mob_sharesdk
- mob_sharesdk/ShareSDKExtension
- mob_sharesdk/ShareSDKPlatforms/Apple
- NIMSDK_LITE (~> 10.9.40)
- MJExtension (= 3.4.2)
- MJRefresh (= 3.7.9)
- pop
- QCloudCOSXML
- QGVAPlayer
- ReactiveObjC
- SDCycleScrollView
- SDWebImage
- SDWebImageFLPlugin
- SDWebImage (= 5.21.3)
- SnapKit (~> 5.0)
- SSKeychain
- SVGAPlayer
- SZTextView
- TABAnimated
- TXLiteAVSDK_TRTC
- TYCyclePagerView
- TZImagePickerController
- UMCommon
- UMDevice
- YuMi (from `yum`)
- YYText
- YYWebImage
- ZLCollectionViewFlowLayout
SPEC REPOS:
https://mirrors.tuna.tsinghua.edu.cn/git/CocoaPods/Specs.git:
- AFNetworking
- AppAuth
- Base64
- Bugly
- CocoaAsyncSocket
- FBAEMKit
- FBSDKCoreKit
- FBSDKCoreKit_Basics
- FBSDKLoginKit
- FBSDKShareKit
- FFPopup
- FLAnimatedImage
- FlyVerifyCSDK
- GKCycleScrollView
- GoogleSignIn
- GTMAppAuth
- GTMSessionFetcher
- IQKeyboardManager
- JXCategoryView
- JXPagingView
- libpag
- MarqueeLabel
- Masonry
- MBProgressHUD
- MJExtension
- MJRefresh
- mob_linksdk_pro
- mob_sharesdk
- MOBFoundation
- NIMSDK_LITE
- pop
- Protobuf
- QCloudCore
- QCloudCOSXML
- QCloudTrack
- QGVAPlayer
- ReactiveObjC
- SDCycleScrollView
- SDWebImage
- SDWebImageFLPlugin
- SnapKit
- SSKeychain
- SSZipArchive
- SVGAPlayer
- SZTextView
- TABAnimated
- TXLiteAVSDK_TRTC
- TYCyclePagerView
- TZImagePickerController
- UMCommon
- UMDevice
- YXArtemis_XCFramework
- YYCache
- YYImage
- YYText
- YYWebImage
- ZLCollectionViewFlowLayout
@@ -243,63 +115,32 @@ EXTERNAL SOURCES:
SPEC CHECKSUMS:
AFNetworking: 3bd23d814e976cd148d7d44c3ab78017b744cd58
AppAuth: d4f13a8fe0baf391b2108511793e4b479691fb73
Base64: cecfb41a004124895a7bcee567a89bae5a89d49b
Bugly: 217ac2ce5f0f2626d43dbaa4f70764c953a26a31
CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99
FBAEMKit: a899515e45476027f73aef377b5cffadcd56ca3a
FBSDKCoreKit: 24f8bc8d3b5b2a8c5c656a1329492a12e8efa792
FBSDKCoreKit_Basics: 6e578c9bdc7aa1365dbbbde633c9ebb536bcaa98
FBSDKLoginKit: 787de205d524c3a4b17d527916f1d066e4361660
FBSDKShareKit: b9c1cd1fa6a320a50f0f353cf30d589049c8db77
FFPopup: a208dcee8db3e54ec4a88fcd6481f6f5d85b7a83
FLAnimatedImage: bbf914596368867157cc71b38a8ec834b3eeb32b
FlyVerifyCSDK: e0a13f11d4f29aca7fb7fdcff3f27e3b7ba2de5d
GKCycleScrollView: 8ed79d2142e62895a701973358b6f94b661b4829
GoogleSignIn: d4281ab6cf21542b1cfaff85c191f230b399d2db
GTMAppAuth: f69bd07d68cd3b766125f7e072c45d7340dea0de
GTMSessionFetcher: 5aea5ba6bd522a239e236100971f10cb71b96ab6
IQKeyboardManager: c8665b3396bd0b79402b4c573eac345a31c7d485
JXCategoryView: 262d503acea0b1278c79a1c25b7332ffaef4d518
JXPagingView: afdd2e9af09c90160dd232b970d603cc6e7ddd0e
libpag: 6e8253018ee4e7f310c8c07d9d9a89d7ae58ae27
MarqueeLabel: d2388949ac58d587303178d56a792ba8a001b037
Masonry: 678fab65091a9290e40e2832a55e7ab731aad201
MBProgressHUD: 3ee5efcc380f6a79a7cc9b363dd669c5e1ae7406
MJExtension: 21c5f6f8c4d5d8844b7ae8fbae08fed0b501f961
MJRefresh: 2fe7fb43a5167ceda20bb7e63f130c04fd1814a5
mob_linksdk_pro: d6ac555e9bb8d2743a8634032a70ea1d34119a50
mob_sharesdk: 409503324d18f231dd27b4d26428c0c168b20c36
MOBFoundation: a1f193058aba95440dadeb799fb398ff92cfe45e
NIMSDK_LITE: 67f6815667acefdc8f9969f8c955b5c1fab490df
MJExtension: e97d164cb411aa9795cf576093a1fa208b4a8dd8
MJRefresh: ff9e531227924c84ce459338414550a05d2aea78
pop: d582054913807fd11fd50bfe6a539d91c7e1a55a
Protobuf: 164aea2ae380c3951abdc3e195220c01d17400e0
QCloudCore: 0e70cda608d1ac485e039e83be1c4a1197197e6b
QCloudCOSXML: b7f0b9cac61780a03318d40367a879f8d7eb3d86
QCloudTrack: cc101dd57be7f87bffc3f2fb692a781d5efeda98
QGVAPlayer: a0bca68c9bd6f1c8de5ac2d10ddf98be6038cce9
QCloudCore: 6f8c67b96448472d2c6a92b9cfe1bdb5abbb1798
QCloudCOSXML: 92f50a787b4e8d9a7cb6ea8e626775256b4840a7
QCloudTrack: 20b79388365b4c8ed150019c82a56f1569f237f8
ReactiveObjC: 011caa393aa0383245f2dcf9bf02e86b80b36040
SDCycleScrollView: a0d74c3384caa72bdfc81470bdbc8c14b3e1fbcf
SDWebImage: f29024626962457f3470184232766516dee8dfea
SDWebImageFLPlugin: 72efd2cfbf565bc438421abb426f4bcf7b670754
SDWebImage: 16309af6d214ba3f77a7c6f6fdda888cb313a50a
SnapKit: d612e99e678a2d3b95bf60b0705ed0a35c03484a
SSKeychain: 55cc80f66f5c73da827e3077f02e43528897db41
SSZipArchive: fe6a26b2a54d5a0890f2567b5cc6de5caa600aef
SVGAPlayer: 318b85a78b61292d6ae9dfcd651f3f0d1cdadd86
SZTextView: 094dc6acc9beec537685c545d6e3e0d4975174e1
TABAnimated: 75fece541a774193565697c7a11539d3c6f631b3
TXLiteAVSDK_TRTC: 09552a5bb5571c85c851d8dd858064724639f55e
TYCyclePagerView: 2b051dade0615c70784aa34f40c646feeddb7344
TZImagePickerController: 456f470b5dea97b37226ec7a694994a8663340b2
UMCommon: 72513a01ebca2dead52f2112b4d7c6196dbbe412
UMDevice: dcdf7ec167387837559d149fbc7d793d984faf82
YuMi: 6c5f00f1eccbcea3304feae03cbe659025fdb9cb
YXArtemis_XCFramework: d9a8b9439d7a6c757ed00ada53a6d2dd9b13f9c7
YYCache: 8105b6638f5e849296c71f331ff83891a4942952
YYImage: 1e1b62a9997399593e4b9c4ecfbbabbf1d3f3b54
YYText: 5c461d709e24d55a182d1441c41dc639a18a4849
YYWebImage: 5f7f36aee2ae293f016d418c7d6ba05c4863e928
ZLCollectionViewFlowLayout: c99024652ce9f0c57d33ab53052c9b85e4a936b7
PODFILE CHECKSUM: 7ad0836a1e150b834d6bc44d667cccc19171d570
PODFILE CHECKSUM: 9e7178f1fdbc61a4ba4e3bc2ae826e7e83aff1db
COCOAPODS: 1.16.2

File diff suppressed because it is too large Load Diff

View File

@@ -56,6 +56,11 @@
value = "disable"
isEnabled = "NO">
</EnvironmentVariable>
<EnvironmentVariable
key = "SWIFT_DISABLE_SAFETY_CHECKS"
value = "YES"
isEnabled = "YES">
</EnvironmentVariable>
</EnvironmentVariables>
</LaunchAction>
<ProfileAction

View File

@@ -1,21 +0,0 @@
//
// AppDelegate+ThirdConfig.h
// YUMI
//
// Created by YUMI on 2021/9/13.
//
#import "AppDelegate.h"
NS_ASSUME_NONNULL_BEGIN
@interface AppDelegate (ThirdConfig)
/// 初始化一些第三方配置
- (void)initThirdConfig;
/**
设置广告页
*/
- (void)setupLaunchADView;
@end
NS_ASSUME_NONNULL_END

View File

@@ -1,243 +0,0 @@
//
// AppDelegate+ThirdConfig.m
// YUMI
//
// Created by YUMI on 2021/9/13.
//
#import "AppDelegate+ThirdConfig.h"
///Third
#import <NIMSDK/NIMSDK.h>
#import <ShareSDK/ShareSDK.h>
#import <UserNotifications/UNUserNotificationCenter.h>
#import <UserNotifications/UserNotifications.h>
#import <MOBFoundation/MobSDK+Privacy.h>
///Tool
#import "YUMIConstant.h"
#import "CustomAttachmentDecoder.h"
#import "QEmotionHelper.h"
#import "XPAdvertiseView.h"
#import "XPAdImageTool.h"
#import "YUMIMacroUitls.h"
#import "AdvertiseModel.h"
#import "XPWebViewController.h"
#import "XPRoomViewController.h"
#import "XCCurrentVCStackManager.h"
#import "ClientConfig.h"
#import <UserNotifications/UserNotifications.h>
#import <Bugly/Bugly.h>
#import "BuglyManager.h"
#import <UIKit/UIDevice.h>
#import "YuMi-swift.h"
UIKIT_EXTERN NSString * kYouMiNumberCountKey;
UIKIT_EXTERN NSString * adImageName;
@implementation AppDelegate (ThirdConfig)
///
- (void)initThirdConfig{
[self setLanguage];
[self configShareSDK];
[self configNIMSDK];
[self configBugly];
[self registerNot];
[self initEmojiData];
}
-(void)setLanguage{
UISemanticContentAttribute attribute = UISemanticContentAttributeForceLeftToRight;
if (isMSRTL()) {
attribute = UISemanticContentAttributeForceRightToLeft;
}
[UIView appearance].semanticContentAttribute = attribute;
[UISearchBar appearance].semanticContentAttribute = attribute;
}
-(void)registerNot{
if (@available(iOS 10.0, *)) {
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
[center requestAuthorizationWithOptions:(UNAuthorizationOptionAlert | UNAuthorizationOptionBadge | UNAuthorizationOptionSound) completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (granted) {
[center getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) {
if (settings.authorizationStatus == UNAuthorizationStatusAuthorized){
dispatch_async(dispatch_get_main_queue(), ^{
[[UIApplication sharedApplication] registerForRemoteNotifications];
});
}
}];
}
}];
}
}
/**
Bugly
*/
- (void) configBugly {
// 使 BuglyManager Bugly
#ifdef DEBUG
[[BuglyManager sharedManager] configureWithAppId:@"c937fd00f7" debug:YES];
#else
[[BuglyManager sharedManager] configureWithAppId:@"8627948559" debug:NO];
#endif
}
- (void)configNIMSDK {
// NIMSDK
NSString *appKey = [[ClientConfig shareConfig].configInfo nimKey];
if ([NSString isEmpty:appKey]) {
appKey = KeyWithType(KeyType_NetEase);
}
NIMSDKOption *option = [NIMSDKOption optionWithAppKey:appKey];
#ifdef DEBUG
option.apnsCername = @"pikoDevelopPush";
#else
option.apnsCername = @"newPiko";
#endif
[[NIMSDK sharedSDK] registerWithOption:option];
// NIM SDK
[NIMCustomObject registerCustomDecoder:[[CustomAttachmentDecoder alloc] init]];
[[NIMSDKConfig sharedConfig] setShouldSyncStickTopSessionInfos:YES];
[NIMSDKConfig sharedConfig].shouldConsiderRevokedMessageUnreadCount = YES;
// cdn
[NIMSDKConfig sharedConfig].cdnTrackInterval = 0;
//
[NIMSDKConfig sharedConfig].chatroomMessageReceiveMinInterval = 50;
#ifdef DEBUG
[NIMSDKConfig sharedConfig].enabledHttpsForInfo = NO;
[NIMSDKConfig sharedConfig].enabledHttpsForMessage = NO;
#else
// HTTPS
[NIMSDKConfig sharedConfig].enabledHttpsForInfo = YES;
[NIMSDKConfig sharedConfig].enabledHttpsForMessage = YES;
#endif
}
- (void)configShareSDK {
// [PILineLoginManager registerLine];
[ShareSDK registPlatforms:^(SSDKRegister *platformsRegister) {
///faceBook
// [platformsRegister setupFacebookWithAppkey:@"1266232494209868" appSecret:@"c9b170b383f8be9cdf118823b8632821" displayName:YMLocalizedString(@"AppDelegate_ThirdConfig0")];
[platformsRegister setupLineAuthType:SSDKAuthorizeTypeBoth];
}];
NSString *isUpload = [[NSUserDefaults standardUserDefaults]valueForKey:@"kMobLinkUploadPrivacy"];
if (isUpload == nil){
[MobSDK uploadPrivacyPermissionStatus:YES onResult:nil];
[[NSUserDefaults standardUserDefaults] setValue:@"YES" forKey:@"kMobLinkUploadPrivacy"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
}
#pragma mark -
- (void)initEmojiData {
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSArray * dicArray = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"emoji" ofType:@"plist"]];
NSDictionary * dic = [dicArray firstObject];
NSArray * emojiArray = dic[@"data"];
NSMutableArray * array = [NSMutableArray array];
for (int i = 0; i < emojiArray.count; i++) {
NSDictionary * emotionDic = [emojiArray xpSafeObjectAtIndex:i];
if (!emotionDic) continue;
UIImage * image = [UIImage imageNamed:emotionDic[@"file"]];
QEmotion * info = [[QEmotion alloc] init];
info.displayName = emotionDic[@"tag"];
info.identifier = emotionDic[@"id"];
info.image = image;
[array addObject:info];
}
//
QEmotionHelper *faceManager = [QEmotionHelper sharedEmotionHelper];
faceManager.emotionArray = array;
// emoji
[QEmotionHelper clearEmojiCache];
});
}
#pragma mark - 广
/**
广
*/
- (void)setupLaunchADView {
NSUserDefaults * kUserDefaults = NSUserDefaults.standardUserDefaults;
// 广
NSString *adName = [kUserDefaults stringForKey:adImageName];
NSString *filePath = [XPAdImageTool.shareImageTool getFilePathWithImageName:adName];
BOOL isExist = [XPAdImageTool.shareImageTool isFileExistWithFilePath:filePath];
if (isExist) {//
// if ([kUserDefaults integerForKey:@"adShow"] > 4) {
@kWeakify(self);
AdvertiseModel *info = [XPAdImageTool.shareImageTool getAdInfoFromCacheInMainWith:adName];
XPAdvertiseView *advertiseView = [[XPAdvertiseView alloc] initWithFrame:self.window.bounds];
advertiseView.type = info.type;
advertiseView.fileModel = info.fillVo;
advertiseView.filePath = filePath;
advertiseView.dismissHandler = ^(BOOL shouldJump) {
@kStrongify(self)
if (!shouldJump || info == nil) {
return;
}
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self advertiseJumpHandleWithInfo:info];
});
};
[advertiseView show];
// }
}
}
/// 广
- (void)advertiseJumpHandleWithInfo:(AdvertiseModel *)info {
if (UIApplication.sharedApplication.keyWindow != self.window) {
//
return;
}
switch (info.type) {
case SplashInfoSkipTypeRoom: {
if (![[XPAdImageTool shareImageTool] isImLogin]) {
return; //
}
//
if (info.link.length > 0) {
[XPRoomViewController openRoom:info.link viewController:[XCCurrentVCStackManager shareManager].getCurrentVC];
}
}
break;
case SplashInfoSkipTypeWeb:
case SplashInfoSkipTypeWeb_CP:
case SplashInfoSkipTypeWeb_Custom:
case SplashInfoSkipTypeWeb_WeekStar: {
// H5
if (info.link.length > 0) {
XPWebViewController *webView = [[XPWebViewController alloc] initWithRoomUID:nil];
webView.url = info.link;
[[[XCCurrentVCStackManager shareManager]currentNavigationController] pushViewController:webView animated:YES];
}
}
break;
default:
break;
}
}
@end

View File

@@ -1,20 +1,13 @@
//
// AppDelegate.h
// YUMI
//
// Created by admin on 2023/3/9.
//
#import <UIKit/UIKit.h>
#import <CoreData/CoreData.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@property(nonatomic,strong,readonly)NSManagedObjectContext *managedObjectContext;
@property(nonatomic,strong,readonly)NSManagedObjectModel *managedObjectModel;
@property(nonatomic,strong,readonly)NSPersistentStoreCoordinator *persistentStoreCoordinator;
- (void)saveContext;
- (NSURL *)applicationDocumentsDirectory;
@end

View File

@@ -1,59 +1,21 @@
//
// AppDelegate.m
// YUMI
//
// Created by admin on 2023/3/9.
//
#import "AppDelegate.h"
#import <UMCommon/UMCommon.h>
#import <MobLinkPro/MobLink.h>
#import <MobLinkPro/MLSDKScene.h>
#import "TabbarViewController.h"
#import "BaseNavigationController.h"
#import "AppDelegate+ThirdConfig.h"
#import <NIMSDK/NIMSDK.h>
#import <AppTrackingTransparency/AppTrackingTransparency.h>
#import "ClientConfig.h"
#import <GoogleSignIn/GoogleSignIn.h>
#import <GoogleSignIn/GoogleSignIn.h>
#import "LoginViewController.h"
#import "AccountModel.h"
#import "YuMi-swift.h"
#import "SessionViewController.h"
#import "LoginFullInfoViewController.h"
#import "UIView+VAP.h"
#import "SocialShareManager.h"
UIKIT_EXTERN NSString * const kOpenRoomNotification;
@interface AppDelegate ()<IMLSDKRestoreDelegate>
@interface AppDelegate ()
@end
@implementation AppDelegate
//
void qg_VAP_Logger_handler(VAPLogLevel level, const char* file, int line, const char* func, NSString *module, NSString *format, ...) {
// MP4 log
return;
// if (format.UTF8String == nil) {
// NSLog(@"log包含非utf-8字符");
// return;
// }
// if (level > VAPLogLevelDebug) {
// va_list argList;
// va_start(argList, format);
// NSString* message = [[NSString alloc] initWithFormat:format arguments:argList];
// file = [NSString stringWithUTF8String:file].lastPathComponent.UTF8String;
// NSLog(@"<%@> %s(%@):%s [%@] - %@",@(level), file, @(line), func, module, message);
// va_end(argList);
// }
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
@@ -63,20 +25,7 @@ void qg_VAP_Logger_handler(VAPLogLevel level, const char* file, int line, const
self.window.rootViewController = launchScreenVC;
[self.window makeKeyAndVisible];
[VAPView registerHWDLog:qg_VAP_Logger_handler];
/// sdk
[self initThirdConfig];
[self initUM:application launchOptions:launchOptions];
@kWeakify(self);
[[ClientConfig shareConfig] clientConfig:^{
@kStrongify(self);
dispatch_async(dispatch_get_main_queue(), ^{
[self loadMainPage];
[self setupLaunchADView];
});
}];
if (@available(iOS 15, *)) {
[[UITableView appearance] setSectionHeaderTopPadding:0];
@@ -85,17 +34,33 @@ void qg_VAP_Logger_handler(VAPLogLevel level, const char* file, int line, const
return YES;
}
- (void)initUM:(UIApplication *)application
launchOptions:(NSDictionary *)launchOptions {
//
if ([[NSUserDefaults standardUserDefaults] objectForKey:@"kYouMinumbernnagna"]) {
///
[UMConfigure initWithAppkey:@"6434c6dfd64e686139618269"
channel:@"appstore"];
// MARK: - Helper Methods
- (UIWindow *)getKeyWindow {
if (@available(iOS 13.0, *)) {
for (UIWindowScene *scene in [UIApplication sharedApplication].connectedScenes) {
if (scene.activationState == UISceneActivationStateForegroundActive) {
for (UIWindow *window in scene.windows) {
if (window.isKeyWindow) {
return window;
}
[MobLink setDelegate:self];
}
return scene.windows.firstObject;
}
}
}
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
return [UIApplication sharedApplication].keyWindow;
#pragma clang diagnostic pop
}
- (void)loadMainPage {
AccountModel *accountModel = [[AccountInfoStorage instance] getCurrentAccountInfo];
if (accountModel == nil ||
@@ -104,223 +69,79 @@ void qg_VAP_Logger_handler(VAPLogLevel level, const char* file, int line, const
[self toLoginPage];
}else{
[self toHomeTabbarPage];
}
[[ClientConfig shareConfig] clientInit];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.8 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self checkAndShowSignatureColorGuide];
});
}
}
- (void)checkAndShowSignatureColorGuide {
UIWindow *keyWindow = [self getKeyWindow];
if (!keyWindow) return;
BOOL hasSignatureColor = [EPEmotionColorStorage hasUserSignatureColor];
//#if DEBUG
//
// NSLog(@"[AppDelegate] Debug 模式:显示专属颜色引导页(已有颜色: %@", hasSignatureColor ? @"YES" : @"NO");
//
// EPSignatureColorGuideView *guideView = [[EPSignatureColorGuideView alloc] init];
//
//
// guideView.onColorConfirmed = ^(NSString *hexColor) {
// [EPEmotionColorStorage saveUserSignatureColor:hexColor];
// NSLog(@"[AppDelegate] 用户选择专属颜色: %@", hexColor);
// };
//
//
// if (hasSignatureColor) {
// guideView.onSkipTapped = ^{
// NSLog(@"[AppDelegate] 用户跳过专属颜色选择");
// };
// }
//
//
// [guideView showInWindow:keyWindow showSkipButton:hasSignatureColor];
//
//#else
if (!hasSignatureColor) {
EPSignatureColorGuideView *guideView = [[EPSignatureColorGuideView alloc] init];
guideView.onColorConfirmed = ^(NSString *hexColor) {
[EPEmotionColorStorage saveUserSignatureColor:hexColor];
NSLog(@"[AppDelegate] 用户选择专属颜色: %@", hexColor);
};
[guideView showInWindow:keyWindow];
}
//#endif
}
- (void)toLoginPage {
LoginViewController *lvc = [[LoginViewController alloc] init];
BaseNavigationController * navigationController = [[BaseNavigationController alloc] initWithRootViewController:lvc];
EPLoginViewController *lvc = [[EPLoginViewController alloc] init];
BaseNavigationController *navigationController =
[[BaseNavigationController alloc] initWithRootViewController:lvc];
navigationController.modalPresentationStyle = UIModalPresentationFullScreen;
self.window.rootViewController = navigationController;
}
- (void)toHomeTabbarPage {
TabbarViewController *vc = [[TabbarViewController alloc] init];
BaseNavigationController *navigationController = [[BaseNavigationController alloc] initWithRootViewController:vc];
self.window.rootViewController = navigationController;
}
EPTabBarController *epTabBar = [EPTabBarController create];
[epTabBar refreshTabBarWithIsLogin:YES];
- (void)IMLSDKWillRestoreScene:(MLSDKScene *)scene
Restore:(void (^)(BOOL, RestoreStyle))restoreHandler {
NSString *inviteCode = scene.params[@"inviteCode"];
if (inviteCode != nil && [[AccountInfoStorage instance]getUid].length == 0){
ClientConfig *config = [ClientConfig shareConfig];
config.inviteCode = inviteCode;
UIWindow *window = [self getKeyWindow];
if (window) {
window.rootViewController = epTabBar;
[window makeKeyAndVisible];
}
restoreHandler(YES, MLDefault);
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
NSInteger count = [NIMSDK sharedSDK].conversationManager.allUnreadCount;
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:count];
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
[self getAdvertisingTrackingAuthority];
[[NSNotificationCenter defaultCenter]postNotificationName:@"kAppDidBecomeActive" object:nil];
}
- (void)getAdvertisingTrackingAuthority {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
if (@available(iOS 14, *)) {
ATTrackingManagerAuthorizationStatus status = ATTrackingManager.trackingAuthorizationStatus;
switch (status) {
case ATTrackingManagerAuthorizationStatusDenied:
// NSLog(@"用户拒绝IDFA");
break;
case ATTrackingManagerAuthorizationStatusAuthorized:
// NSLog(@"用户允许IDFA");
break;
case ATTrackingManagerAuthorizationStatusNotDetermined: {
// NSLog(@"用户未做选择或未弹窗IDFA");
//1app
[ATTrackingManager requestTrackingAuthorizationWithCompletionHandler:^(ATTrackingManagerAuthorizationStatus status) {
// NSLog(@"app追踪IDFA权限%lu",(unsigned long)status);
}];
}
break;
default:
break;
}
}
});
}
- (void)application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
// devicetoken
[[NIMSDK sharedSDK] updateApnsToken:deviceToken ];
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler{
NSString *data = userInfo[@"data"];
if(data){
NSDictionary *dataDic = [data mj_JSONObject];
NSString *userId = dataDic[@"uid"];
if(userId){
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter]postNotificationName:kOpenRoomNotification object:nil userInfo:@{@"type":@"kOpenChat",@"uid":userId,@"isNoAttention":@(YES)}];
ClientConfig *config = [ClientConfig shareConfig];
config.pushChatId = userId;
});
return;
}
}
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSString *userId = userInfo[@"uid"];
if(userId){
[[NSNotificationCenter defaultCenter]postNotificationName:kOpenRoomNotification object:nil userInfo:@{@"type":@"kOpenChat",@"uid":userId,@"isNoAttention":@(YES)}];
ClientConfig *config = [ClientConfig shareConfig];
config.pushChatId = userId;
}
});
}
///URL Scheme
-(BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString *,id> *)options{
[[SocialShareManager sharedManager] handleURL:url];
return [GIDSignIn.sharedInstance handleURL:url];
}
//- (void)__oldApplicationOpenURLMethod:(NSURL *)url {
// NSString *text = [url query];
// if(text.length){
// NSMutableDictionary *paramsDict = [NSMutableDictionary dictionary];
// NSArray *paramArray = [text componentsSeparatedByString:@"&"];
// for (NSString *param in paramArray) {
// if (param && param.length) {
// NSArray *parArr = [param componentsSeparatedByString:@"="];
// if (parArr.count == 2) {
// [paramsDict setObject:parArr[1] forKey:parArr[0]];
// }
// }
// }
// if(paramsDict[@"type"] != nil){
// NSInteger type = [paramsDict[@"type"] integerValue];
// if (type == 2) {
// NSString *uid = [NSString stringWithFormat:@"%@",paramsDict[@"uid"]];
// [[NSNotificationCenter defaultCenter]postNotificationName:kOpenRoomNotification object:nil userInfo:@{@"uid":uid}];
// ClientConfig *config = [ClientConfig shareConfig];
// config.roomId = uid;
// }else if(type == 7){
// NSString *uid = [NSString stringWithFormat:@"%@",paramsDict[@"uid"]];
// [[NSNotificationCenter defaultCenter]postNotificationName:kOpenRoomNotification object:nil userInfo:@{@"type":@"kOpenChat",@"uid":uid}];
// ClientConfig *config = [ClientConfig shareConfig];
// config.chatId = uid;
// }else if (type == 8){
// NSString *inviteCode = paramsDict[@"inviteCode"];
// if (inviteCode != nil && [[AccountInfoStorage instance]getUid].length == 0){
// ClientConfig *config = [ClientConfig shareConfig];
// config.inviteCode = inviteCode;
// }
// }
//// return YES;
// }
// }
//}
#pragma mark - Core Data stack
@synthesize managedObjectContext = _managedObjectContext;
@synthesize managedObjectModel = _managedObjectModel;
@synthesize persistentStoreCoordinator = _persistentStoreCoordinator;
-(NSURL *)applicationDocumentsDirectory{
return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}
- (NSManagedObjectModel *)managedObjectModel {
// The managed object model for the application. It is a fatal error for the application not to be able to find and load its model.
if (_managedObjectModel != nil) {
return _managedObjectModel;
}
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"_1_______" withExtension:@"momd"];
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
return _managedObjectModel;
}
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
// The persistent store coordinator for the application. This implementation creates and returns a coordinator, having added the store for the application to it.
if (_persistentStoreCoordinator != nil) {
return _persistentStoreCoordinator;
}
// Create the coordinator and store
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"_1_______.sqlite"];
NSError *error = nil;
NSString *failureReason = @"There was an error creating or loading the application's saved data.";
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
// Report any error we got.
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
dict[NSLocalizedDescriptionKey] = @"Failed to initialize the application's saved data";
dict[NSLocalizedFailureReasonErrorKey] = failureReason;
dict[NSUnderlyingErrorKey] = error;
error = [NSError errorWithDomain:@"YOUR_ERROR_DOMAIN" code:9999 userInfo:dict];
// Replace this with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
// NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
return _persistentStoreCoordinator;
}
- (NSManagedObjectContext *)managedObjectContext {
// Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.)
if (_managedObjectContext != nil) {
return _managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (!coordinator) {
return nil;
}
_managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[_managedObjectContext setPersistentStoreCoordinator:coordinator];
return _managedObjectContext;
}
#pragma mark - Core Data Saving support
- (void)saveContext {
NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
if (managedObjectContext != nil) {
NSError *error = nil;
if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
// NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
}
}
@end

View File

@@ -1,16 +0,0 @@
//
// YYTextAsyncLayer+PITextAsyncLayer.h
// YuMi
//
// Created by duoban on 2023/10/28.
//
#import <YYText/YYTextAsyncLayer.h>
NS_ASSUME_NONNULL_BEGIN
@interface YYTextAsyncLayer (PITextAsyncLayer)
@end
NS_ASSUME_NONNULL_END

View File

@@ -1,26 +0,0 @@
//
// YYTextAsyncLayer+PITextAsyncLayer.m
// YuMi
//
// Created by duoban on 2023/10/28.
//
#import "YYTextAsyncLayer+PITextAsyncLayer.h"
@implementation YYTextAsyncLayer (PITextAsyncLayer)
///iOS17bug退
+(void)load {
Method displayMethod = class_getInstanceMethod(self, @selector(display));
Method swizzingMethod = class_getInstanceMethod(self, @selector(swizzing_display));
method_exchangeImplementations(displayMethod, swizzingMethod);
}
-(void)swizzing_display{
//
if (self.bounds.size.width <= 0 || self.bounds.size.height <= 0) {
self.contents = nil;
return;
} else {
[self swizzing_display];
}
}
@end

View File

@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="32700.99.1234" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="24128" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<device id="retina5_9" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22684"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="24063"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
@@ -16,46 +16,26 @@
<rect key="frame" x="0.0" y="0.0" width="375" height="812"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="pi_app_logo_new_bg.png" translatesAutoresizingMaskIntoConstraints="NO" id="sON-N7-5Wv">
<rect key="frame" x="0.0" y="0.0" width="375" height="355"/>
<constraints>
<constraint firstAttribute="height" constant="355" id="BrK-cy-oiN"/>
</constraints>
</imageView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Meet your exclusive voice~" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="o5T-sv-tDU">
<rect key="frame" x="79.333333333333329" y="312" width="216.66666666666669" height="22"/>
<fontDescription key="fontDescription" type="system" pointSize="18"/>
<color key="textColor" red="0.023529411760000001" green="0.043137254899999998" blue="0.090196078430000007" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="pi_login_new_logo.png" translatesAutoresizingMaskIntoConstraints="NO" id="v2t-MR-31f">
<rect key="frame" x="122.66666666666669" y="140" width="130" height="148"/>
<constraints>
<constraint firstAttribute="width" constant="130" id="mQh-M0-hFI"/>
<constraint firstAttribute="height" constant="148" id="tX3-Va-dub"/>
</constraints>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="ep_splash.png" translatesAutoresizingMaskIntoConstraints="NO" id="sON-N7-5Wv">
<rect key="frame" x="0.0" y="0.0" width="375" height="812"/>
</imageView>
</subviews>
<viewLayoutGuide key="safeArea" id="r4O-Vu-IrR"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="sON-N7-5Wv" firstAttribute="leading" secondItem="r4O-Vu-IrR" secondAttribute="leading" id="CEl-rE-BeK"/>
<constraint firstItem="o5T-sv-tDU" firstAttribute="top" secondItem="v2t-MR-31f" secondAttribute="bottom" constant="24" id="GEv-XM-qev"/>
<constraint firstItem="sON-N7-5Wv" firstAttribute="trailing" secondItem="r4O-Vu-IrR" secondAttribute="trailing" id="MsB-m5-LHI"/>
<constraint firstItem="sON-N7-5Wv" firstAttribute="top" secondItem="Ze5-6b-2t3" secondAttribute="top" id="SM6-2S-etM"/>
<constraint firstItem="v2t-MR-31f" firstAttribute="top" secondItem="Ze5-6b-2t3" secondAttribute="top" constant="140" id="YA3-7E-mLb"/>
<constraint firstItem="o5T-sv-tDU" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="Yej-IY-emP"/>
<constraint firstItem="v2t-MR-31f" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="x8C-D7-WvQ"/>
<constraint firstAttribute="bottom" secondItem="sON-N7-5Wv" secondAttribute="bottom" id="0zO-vt-zzT"/>
<constraint firstItem="sON-N7-5Wv" firstAttribute="trailing" secondItem="r4O-Vu-IrR" secondAttribute="trailing" id="MAy-os-QAw"/>
<constraint firstItem="sON-N7-5Wv" firstAttribute="leading" secondItem="r4O-Vu-IrR" secondAttribute="leading" id="Onc-xX-tha"/>
<constraint firstItem="sON-N7-5Wv" firstAttribute="top" secondItem="Ze5-6b-2t3" secondAttribute="top" id="vhU-0c-IHX"/>
</constraints>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="52.671755725190835" y="374.64788732394368"/>
<point key="canvasLocation" x="52" y="374.6305418719212"/>
</scene>
</scenes>
<resources>
<image name="pi_app_logo_new_bg.png" width="1125" height="273"/>
<image name="pi_login_new_logo.png" width="486" height="96"/>
<image name="ep_splash.png" width="1125" height="2436"/>
</resources>
</document>

101
YuMi/Config/APIConfig.swift Normal file
View File

@@ -0,0 +1,101 @@
// Created by AI on 2025-10-09.
// Copyright © 2025 YuMi. All rights reserved.
import Foundation
@objc class APIConfig: NSObject {
// MARK: - Private Properties
private static let xorKey: UInt8 = 77
private static let releaseEncodedParts: [String] = [
"JTk5PT53YmI=",
"LD0kYw==",
"KD0sPzk0ISQ7KGMuIiA=",
]
// MARK: - Public Methods
@objc static func baseURL() -> String {
#if DEBUG
// TODO: return HttpRequestHelper.getHostUrl()
return getDevBaseURL()
#else
let url = decodeURL(from: releaseEncodedParts)
if url.isEmpty || !url.hasPrefix("http") {
NSLog("[APIConfig] 警告:域名解密失败,使用备用域名")
return backupURL()
}
return url
#endif
}
private static func getDevBaseURL() -> String {
#if DEBUG
let isProduction = UserDefaults.standard.string(forKey: "kIsProductionEnvironment")
if isProduction == "YES" {
return "https://api.epartylive.com"
} else {
return "https://test-api.yourdomain.com"
}
#else
return "https://api.epartylive.com"
#endif
}
@objc static func backupURL() -> String {
return getDevBaseURL()
}
// MARK: - Private Methods
private static func decodeURL(from parts: [String]) -> String {
let decoded = parts.compactMap { part -> String? in
guard let data = Data(base64Encoded: part) else {
NSLog("[APIConfig] Base64 解码失败: \(part)")
return nil
}
let xored = data.map { $0 ^ xorKey }
return String(bytes: xored, encoding: .utf8)
}
let result = decoded.joined()
#if DEBUG
NSLog("[APIConfig] 解密后的域名: \(result)")
#endif
return result
}
}
// MARK: - Debug Helper
#if DEBUG
extension APIConfig {
@objc static func testEncryption() {
print("=== APIConfig 加密测试 ===")
print("Release 域名: \(decodeURL(from: releaseEncodedParts))")
print("当前环境域名: \(baseURL())")
print("备用域名: \(backupURL())")
}
}
#endif

View File

@@ -1,70 +0,0 @@
//
// ClientConfig.h
// YUMI
//
// Created by YUMI on 2021/12/11.
//
#import <Foundation/Foundation.h>
#import "ClientDataModel.h"
NS_ASSUME_NONNULL_BEGIN
@interface ClientConfig : PIBaseModel
+ (instancetype)shareConfig;
///初始化
- (void)clientInit;
/// 获取 UI 配置
- (void)clientConfig:(void(^)(void))finish;
/// iOS第三方登录是否需要绑定手机号
@property (nonatomic,assign) BOOL iOSPhoneBind;
/// 是否开启了糖果树
@property (nonatomic,assign) BOOL openCandyTree;
///配置信息
@property (nonatomic,strong) ClientDataModel *configInfo;
@property (nonatomic, strong) AppUISetting *uiSetting;
///开箱子 大于等级 展示
@property (nonatomic, assign) NSInteger openCandyTreeLimitLevel;
@property(nonatomic,assign) BOOL isTF;
///是否刷新了
@property (nonatomic,assign) BOOL isLoad;
///房间id用于分享房间跳转到房间
@property (nonatomic, copy) NSString *__nullable roomId;
///用户id用于外部h5跳转到聊天页面
@property (nonatomic, copy) NSString *__nullable chatId;
///用户id推送跳转到聊天页面
@property (nonatomic, copy) NSString *__nullable pushChatId;
///邀请码,从外面进来会进入注册页面,并自动填写这个邀请码
@property(nonatomic,copy) NSString *inviteCode;
///表情---
@property (nonatomic, copy) NSString *version;
@property (nonatomic, copy) NSString *zipMd5;
@property (nonatomic, strong) NSURL *zipUrl;
@property(nonatomic, assign) BOOL shouldDisplayCaptcha;
- (UIColor *)bgColor;
- (NSString *)tabName:(NSInteger)tabIndex;
- (NSString *)loadDefaultNormalTabImageName:(NSInteger)tabIndex;
- (NSString *)loadDefaultSelectedTabImageName:(NSInteger)tabIndex;
- (NSString *)loadConfigNormalTabImagePath:(NSInteger)tabIndex;
- (NSString *)loadConfigSelectedTabImagePath:(NSInteger)tabIndex;
@property (nonatomic, copy) NSString *reloadNavigationAreaImageKey;
@property (nonatomic, copy) NSString *reloadViewBackgroundColorKey;
@property (nonatomic, strong) UIImage *navigationAreaBG;
@property (nonatomic, strong) UIImage *tabbarBGImage;
@property (nonatomic, copy) void(^updateTabbarBG)(UIImage *image);
@end
NS_ASSUME_NONNULL_END

View File

@@ -1,274 +0,0 @@
//
// ClientConfig.m
// YUMI
//
// Created by YUMI on 2021/12/11.
//
#import "ClientConfig.h"
#import "Api+Main.h"
/// tool
#import "DESEncrypt.h"
#import "YUMIConstant.h"
#import <MJExtension/MJExtension.h>
#import "XPRoomFaceTool.h"
#import "NSString+Utils.h"
#import "YYUtility.h"
#import "XPWeakTimer.h"
#import "Api+Main.h"
#import "ChatFaceVo.h"
#import "PublicRoomManager.h"
@interface ClientConfig ()
/// 10
@property (nonatomic,assign) int retryCount;
@property (nonatomic, strong) NSMutableArray *normalTabImageSource;
@property (nonatomic, strong) NSMutableArray *selectedTabImageSource;
@property (nonatomic, strong) NetImageView *normalTabImageLoader;
@property (nonatomic, strong) NetImageView *selectedTabImageLoader;
@property (nonatomic, strong) NetImageView *tabbarBGImageLoader;
@property (nonatomic, strong) NetImageView *navigationAreaBGImageLoader;
@property (nonatomic, assign) BOOL isLoading;
@end
@implementation ClientConfig
+ (instancetype)shareConfig {
static dispatch_once_t onceToken;
static ClientConfig * config;
dispatch_once(&onceToken, ^{
config = [[ClientConfig alloc] init];
config.isTF = [ClientConfig isTestFlight];
config.reloadNavigationAreaImageKey = @"今天光线很好";
config.reloadViewBackgroundColorKey = @"年轻人买不起美国买房平均年龄飙升至56岁";
});
return config;
}
+(BOOL)isTestFlight{
NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];
NSString *receiptURLString = [receiptURL path];
BOOL isTestFlight = ([receiptURLString containsString:@"sandboxReceipt"] || [receiptURLString containsString:@"_MASReceipt/receipt"]);
return isTestFlight;
}
- (void)clientInit {
@kWeakify(self);
[Api clientInitConfig:^(BaseModel * _Nullable data, NSInteger code, NSString * _Nullable msg) {
@kStrongify(self);
if (code == 200) {
self.retryCount = 0;
ClientDataModel * model = [ClientDataModel modelWithDictionary:data.data];
self.iOSPhoneBind = model.iosPhoneBind;
//
self.openCandyTree = model.openBoxSwitch;
self.openCandyTreeLimitLevel = model.openBoxSwitchLevelNo;
//
NSString *json = model.faceJson.json;
NSString *deJson = [DESEncrypt decryptUseDES:json key:KeyWithType(KeyType_FacePwdEncode)];
NSDictionary *faceInitData = [deJson toJSONObject];
model.faceInitData = faceInitData;
if (faceInitData) {
[XPRoomFaceTool shareFaceTool].version = [NSString stringWithFormat:@"%@",faceInitData[@"version"]];
[XPRoomFaceTool shareFaceTool].zipMd5 = [[NSString stringWithFormat:@"%@",faceInitData[@"zipMd5"]] uppercaseString];
[XPRoomFaceTool shareFaceTool].zipUrl = [NSString stringWithFormat:@"%@",faceInitData[@"zipUrl"]];
///
[[XPRoomFaceTool shareFaceTool] saveFaceInfoList:faceInitData];
///
[[XPRoomFaceTool shareFaceTool] downFaceData];
}
NSString *trtcAppId = @(model.trtcAppId).stringValue;
NSString *curTtcKey = [[NSUserDefaults standardUserDefaults]valueForKey:@"kTrtcAppId"];
if(curTtcKey == nil){
if(trtcAppId != nil){
[[NSUserDefaults standardUserDefaults]setValue:trtcAppId forKey:@"kTrtcAppId"];
[[NSUserDefaults standardUserDefaults]synchronize];
}
}else{
if(![trtcAppId isEqualToString:curTtcKey]){
if(trtcAppId != nil){
[[NSUserDefaults standardUserDefaults]setValue:trtcAppId forKey:@"kTrtcAppId"];
[[NSUserDefaults standardUserDefaults]synchronize];
}
}
}
//
NSString *serverVer = model.appStoreAuditNoticeVersion;
NSString *shortVer = [YYUtility appVersion];
model.hideNoticeVersion = [NSString versionCompareOldStr:serverVer andNewStr:shortVer];
self.configInfo = model;
[[NSNotificationCenter defaultCenter] postNotificationName:@"reloadAfterLoadConfig" object:nil];
[self requestFaceTabNewList];
} else {
if (self.retryCount < 10) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
self.retryCount+=1;
[self clientInit];
});
}
}
}];
}
- (void)requestFaceTabNewList {
[Api faceTabNewList:^(BaseModel * _Nullable data, NSInteger code, NSString * _Nullable msg) {
if (code == 200) {
[[XPRoomFaceTool shareFaceTool] cacheChatFaces:data.data];
}
}];
}
- (void)clientConfig:(void(^)(void))finish {
@kWeakify(self);
[Api clientConfig:^(BaseModel * _Nullable data, NSInteger code, NSString * _Nullable msg) {
@kStrongify(self);
if (code == 200) {
self.uiSetting = [AppUISetting modelWithJSON:data.data[@"appUiSetting"]];
}
// tab image path
[self prepareCustomUI];
if (finish) {
finish();
}
}];
}
- (void)prepareCustomUI {
NSArray *defaultArray = @[@"", @"", @"", @"", @""];
self.normalTabImageSource = defaultArray.mutableCopy;
self.selectedTabImageSource = defaultArray.mutableCopy;
if (self.uiSetting) {
NSArray *unselectIcons = @[
self.uiSetting.homeUnSelectIcon ?: @"",
self.uiSetting.gameUnSelectIcon ?: @"",
self.uiSetting.dynamicUnSelectIcon ?: @"",
self.uiSetting.msgUnSelectIcon ?: @"",
self.uiSetting.mineUnSelectIcon ?: @""
];
NSArray *selectIcons = @[
self.uiSetting.homeSelectIcon ?: @"",
self.uiSetting.gameSelectIcon ?: @"",
self.uiSetting.dynamicSelectIcon ?: @"",
self.uiSetting.msgSelectIcon ?: @"",
self.uiSetting.mineSelectIcon ?: @""
];
self.normalTabImageSource = unselectIcons.mutableCopy;
self.selectedTabImageSource = selectIcons.mutableCopy;
[self loadNavigationAreaBG];
[self loadTabbarBG];
[self loadBGColor];
} else {
if (self.updateTabbarBG) {
self.updateTabbarBG(kImage(@"tab_bar_bg"));
}
}
}
- (UIImage *)navigationAreaBG {
if (!_navigationAreaBG) {
return kImage(@"home_top_bg");
} else {
return _navigationAreaBG;
}
}
- (void)loadNavigationAreaBG {
if (!_navigationAreaBGImageLoader) {
_navigationAreaBGImageLoader = [[NetImageView alloc] init];
}
@kWeakify(self);
[self.navigationAreaBGImageLoader loadImageWithUrl:self.uiSetting.headIcon
completion:^(UIImage * _Nullable image, NSURL * _Nonnull url) {
@kStrongify(self);
self.navigationAreaBG = image;
[[NSNotificationCenter defaultCenter] postNotificationName:self.reloadNavigationAreaImageKey object:[image resizeTo:CGSizeMake(1125, 420)]];
} fail:^(NSError * _Nonnull error) {}];
}
- (void)loadTabbarBG {
if (!_tabbarBGImageLoader) {
_tabbarBGImageLoader = [[NetImageView alloc] init];
}
@kWeakify(self);
[self.tabbarBGImageLoader loadImageWithUrl:self.uiSetting.navbar
completion:^(UIImage * _Nullable image, NSURL * _Nonnull url) {
@kStrongify(self);
self.tabbarBGImage = image;
if (self.updateTabbarBG) {
self.updateTabbarBG(image);
}
} fail:^(NSError * _Nonnull error) {
@kStrongify(self);
if (self.updateTabbarBG) {
self.updateTabbarBG(kImage(@"tab_bar_bg"));
}
}];
}
- (void)loadBGColor {
[[NSNotificationCenter defaultCenter] postNotificationName:self.reloadNavigationAreaImageKey
object:nil];
}
- (UIColor *)bgColor {
if (self.uiSetting && ![NSString isEmpty:self.uiSetting.backgroundColor]) {
return [DJDKMIMOMColor colorWithHexString:self.uiSetting.backgroundColor];
}
return [DJDKMIMOMColor colorWithHexString:@"#FCF4DF"];
}
- (NSString *)tabName:(NSInteger)tabIndex {
return @[YMLocalizedString(@"TabbarViewController2"),
YMLocalizedString(@"TabbarViewController6"),
YMLocalizedString(@"TabbarViewController3"),
YMLocalizedString(@"TabbarViewController4"),
YMLocalizedString(@"TabbarViewController5")][tabIndex];
}
- (NSString *)loadDefaultNormalTabImageName:(NSInteger)tabIndex {
return @[@"tab_gameHome_normal",
@"tab_gameHome_game_normal",
@"tab_monents_normal",
@"tab_message_normal",
@"tab_mine_normal"][tabIndex];
}
- (NSString *)loadDefaultSelectedTabImageName:(NSInteger)tabIndex {
return @[@"tab_gameHome_selected",
@"tab_gameHome_game_selected",
@"tab_monents_select",
@"tab_message_selected",
@"tab_mine_selected"][tabIndex];
}
- (NSString *)loadConfigNormalTabImagePath:(NSInteger)tabIndex {
return [self.normalTabImageSource xpSafeObjectAtIndex:tabIndex];
}
- (NSString *)loadConfigSelectedTabImagePath:(NSInteger)tabIndex {
return [self.selectedTabImageSource xpSafeObjectAtIndex:tabIndex];
}
- (BOOL)shouldDisplayCaptcha {
return [self.configInfo captchaSwitch];
}
@end

View File

@@ -1,117 +0,0 @@
//
// ClientDataModel.h
// YUMI
//
// Created by YUMI on 2022/3/7.
//
#import <Foundation/Foundation.h>
#import "ClientRedPacketModel.h"
#import "AdvertiseModel.h"
NS_ASSUME_NONNULL_BEGIN
typedef NS_ENUM(NSInteger, FaceLivenessStrategy) {
FaceLivenessStrategy_Pass = 0,
FaceLivenessStrategy_Force = 1,
FaceLivenessStrategy_Guide = 2,
};
@interface FaceJson : PIBaseModel
@property (nonatomic, assign) NSInteger status;
@property (nonatomic, assign) NSInteger id;
@property (nonatomic, assign) NSTimeInterval createTime;
@property (nonatomic, copy) NSString *json;
@property (nonatomic, assign) NSInteger version;
@end
@interface AppUISetting : PIBaseModel
@property (nonatomic, assign) NSInteger settingStatus;
@property (nonatomic, copy) NSString *headIcon;
@property (nonatomic, copy) NSString *navbar;
@property (nonatomic, copy) NSString *backgroundColor;
@property (nonatomic, copy) NSString *homeSelectIcon;
@property (nonatomic, copy) NSString *homeUnSelectIcon;
@property (nonatomic, copy) NSString *gameSelectIcon;
@property (nonatomic, copy) NSString *gameUnSelectIcon;
@property (nonatomic, copy) NSString *dynamicSelectIcon;
@property (nonatomic, copy) NSString *dynamicUnSelectIcon;
@property (nonatomic, copy) NSString *msgSelectIcon;
@property (nonatomic, copy) NSString *msgUnSelectIcon;
@property (nonatomic, copy) NSString *mineSelectIcon;
@property (nonatomic, copy) NSString *mineUnSelectIcon;
@property (nonatomic, copy) NSString *selectBar;
@end
@interface ClientDataModel : PIBaseModel
@property (nonatomic, strong) AppUISetting *appUiSetting;
///首页tag 配置
@property (nonatomic,strong) NSArray<NSString *> *homeTabList;
///房间表情的数据
@property (nonatomic,copy) NSDictionary *faceInitData;
///是否隐藏房间公告
@property (nonatomic,assign) BOOL hideNoticeVersion;
//进入房间拉取N条聊天数据
@property(nonatomic, assign) NSInteger roomMessageCount;
///发现萌新展示等级
@property (nonatomic,assign) NSInteger findNewbieCharmLevel;
///送礼物隐藏座驾动画的值
@property (nonatomic,assign) double hideCarEffectGiftPrice;
//航海等级限制
@property (nonatomic, assign) NSInteger linearlyPoolOpenLevel;
///红包配置
@property (nonatomic, strong) ClientRedPacketModel *redEnvelopeConfig;
///启动图
@property (nonatomic,strong) AdvertiseModel *splashVo;
///官方消息Uid列表
@property (nonatomic, strong) NSArray<NSString *> *officialMsgUids;
///官方账号 小秘书 红包消息
@property (nonatomic,strong) NSArray<NSString *> *officialAccountUids;
@property(nonatomic,copy) NSDictionary *publicChatRoomIdMap; // 公聊大厅房间 IDs已不使用该业务逻辑 -> 又要使用了
///星座礼物顶部是否开启
@property (nonatomic,assign) BOOL twelveStarSwitch;
/// 开房是否需要实名
@property (nonatomic,assign) FaceLivenessStrategy certificationType;
///转赠钻石白名单
@property (nonatomic,strong) NSMutableArray *giveDiamondErbanNoList;
///转赠礼物白名单
@property (nonatomic,strong) NSMutableArray *giveGiftErbanNoList;
///每日转赠钻石总额限制
@property (nonatomic,assign) NSInteger giveDiamondDailyNum;
///转赠钻石单笔最大限额
@property (nonatomic,assign) NSInteger giveDiamondOnceLimitNum;
///转赠钻石财富等级
@property (nonatomic,assign) NSInteger giveDiamondExperLevel;
///转赠礼物财富等级
@property (nonatomic,assign) NSInteger giveGiftExperLevel;
///转赠手续费率
@property (nonatomic,assign) double giveDiamondRate;
@property (nonatomic, assign) BOOL iosPhoneBind;
@property (nonatomic, assign) BOOL openBoxSwitch;
@property (nonatomic, assign) NSInteger openBoxSwitchLevelNo;
@property (nonatomic, strong) FaceJson *faceJson;
@property (nonatomic, assign) NSInteger trtcAppId;
@property (nonatomic, copy) NSString *appStoreAuditNoticeVersion;
@property(nonatomic, assign) BOOL captchaSwitch;
@property (nonatomic, copy) NSString *sudId;
@property (nonatomic, copy) NSString *sudkey;
@property (nonatomic, copy) NSString *nimKey;
@end
NS_ASSUME_NONNULL_END

View File

@@ -1,30 +0,0 @@
//
// ClientDataModel.m
// YUMI
//
// Created by YUMI on 2022/3/7.
//
#import "ClientDataModel.h"
#import "XPAdImageTool.h"
@implementation FaceJson
@end
@implementation AppUISetting
@end
@implementation ClientDataModel
- (void)setSplashVo:(AdvertiseModel *)splashVo {
_splashVo = splashVo;
if (_splashVo) {
[XPAdImageTool.shareImageTool saveAdInfo:splashVo];
}
}
@end

View File

@@ -1,52 +0,0 @@
//
// ClientRedPacketModel.h
// YUMI
//
// Created by YUMI on 2022/8/31.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
//@class
@interface ClientRedPacketModel : PIBaseModel
///红包开关
@property (nonatomic, assign) BOOL open;
///红包推送id
@property (nonatomic, assign) long long pushUserId;
///厅内红包个数最大值
@property (nonatomic, strong) NSNumber *roomRedEnvelopeMaxNum;
///厅内红包数额最小值
@property (nonatomic, strong) NSNumber *roomRedEnvelopeMinAmount;
///厅内红包个数最小值
@property (nonatomic, strong) NSNumber *roomRedEnvelopeMinNum;
///全服红包个数最大值
@property (nonatomic, strong) NSNumber *serverRedEnvelopeMaxNum;
///全服红包数额最小值
@property (nonatomic, strong) NSNumber *serverRedEnvelopeMinAmount;
///全服红包个数最小值
@property (nonatomic, strong) NSNumber *serverRedEnvelopeMinNum;
///厅内红包数额最大值
@property (nonatomic, strong) NSNumber *roomRedEnvelopeMaxAmount;
///全服红包数额最大值
@property (nonatomic, strong) NSNumber *serverRedEnvelopeMaxAmount;
///默认红包位置1厅内 2全服
@property (nonatomic, strong) NSNumber *redEnvelopedPosition;
///默认红包类型1 钻石 2礼物
@property (nonatomic, strong) NSNumber *redEnvelopeType;
///钻石红包比例
@property (nonatomic, strong) NSNumber *exchangeDiamondsRate;
///版本
@property (nonatomic, copy) NSString *serverAppVersion;
//@property (nonatomic, strong) NSArray<> *gold2GiftIds;
@property (nonatomic, strong) NSArray *openRooms;
@property(nonatomic,assign) NSInteger beginSecond;
///红包有效时间
@property(nonatomic,assign) NSInteger endSecond;
@end
NS_ASSUME_NONNULL_END

View File

@@ -1,16 +0,0 @@
//
// ClientRedPacketModel.m
// YUMI
//
// Created by YUMI on 2022/8/31.
//
#import "ClientRedPacketModel.h"
@implementation ClientRedPacketModel
//+ (NSDictionary *)objectClassInArray {
// return @{@"contents":GuildMessageLayoutInfoModel.class};
//}
@end

View File

@@ -1,44 +0,0 @@
//
// AdvertiseModel.h
// YUMI
//
// Created by YUMI on 2022/10/31.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
typedef NS_ENUM(NSInteger, SplashInfoSkipType) {
SplashInfoSkipTypePage = 1,
SplashInfoSkipTypeRoom = 2,
SplashInfoSkipTypeWeb = 3,
SplashInfoSkipTypeWeb_CP = 4,
SplashInfoSkipTypeWeb_WeekStar = 5,
SplashInfoSkipTypeWeb_Custom = 6,
};
@interface AdvertiseFillModel : PIBaseModel
@property(nonatomic, copy) NSString *loverNick;
@property(nonatomic, copy) NSString *loverErbanNo;
@property(nonatomic, copy) NSString *loverAvatar;
@property(nonatomic, copy) NSString *nick;
@property(nonatomic, copy) NSString *erbanNo;
@property(nonatomic, copy) NSString *avatar;
@property(nonatomic, copy) NSString *picUrl;
@property(nonatomic, copy) NSString *giftName;
@property(nonatomic, copy) NSString *giftId;
@end
@interface AdvertiseModel : PIBaseModel
@property (nonatomic, strong) NSString *link;
@property (nonatomic, assign) SplashInfoSkipType type;// 1跳app页面2跳聊天室3跳h5页面,
@property (nonatomic, copy) NSString *pict;
@property(nonatomic, strong) AdvertiseFillModel *fillVo;
@end
NS_ASSUME_NONNULL_END

View File

@@ -1,23 +0,0 @@
//
// AdvertiseModel.m
// YUMI
//
// Created by YUMI on 2022/10/31.
//
#import "AdvertiseModel.h"
@implementation AdvertiseFillModel
@end
@implementation AdvertiseModel
+ (NSDictionary *)objectClassInArray {
return @{
@"fillVo": [AdvertiseFillModel class],
};
}
@end

View File

@@ -1,48 +0,0 @@
//
// YMAdImageTool.h
// YUMI
//
// Created by YUMI on 2022/10/31.
//
#import <Foundation/Foundation.h>
#import "AdvertiseModel.h"
NS_ASSUME_NONNULL_BEGIN
@interface XPAdImageTool : PIBaseModel
+ (instancetype)shareImageTool;
///是否登录成功im
@property (nonatomic,assign)BOOL isImLogin;
//去除广告信息
- (AdvertiseModel *)getAdInfoFromCacheInMainWith:(NSString *)link;
///保存信息
- (void)saveAdInfo:(AdvertiseModel *)adInfo;
/**
* 判断文件是否存在
*/
- (BOOL)isFileExistWithFilePath:(NSString *)filePath;
/**
* 初始化广告页面
*/
- (void)getAdvertisingImage;
/**
* 下载新图片
*/
- (void)downloadAdImageWithUrl:(NSString *)imageUrl imageName:(NSString *)imageName;
/**
* 删除旧图片
*/
- (void)deleteOldImage;
/**
* 根据图片名拼接文件路径
*/
- (NSString *)getFilePathWithImageName:(NSString *)imageName;
@end
NS_ASSUME_NONNULL_END

View File

@@ -1,158 +0,0 @@
//
// YMAdImageTool.m
// YUMI
//
// Created by YUMI on 2022/10/31.
//
#import "XPAdImageTool.h"
#import <YYCache/YYCache.h>
#import "UploadFile.h"
#define CACHENAME @"XPUserCache"
UIKIT_EXTERN NSString * const adImageName;
@interface XPAdImageTool ()
@property (nonatomic, strong) YYCache *yyCache;
///广
@property (nonatomic,strong) AdvertiseModel *infoModel;
@end
static XPAdImageTool* tool;
@implementation XPAdImageTool
+ (instancetype)shareImageTool {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
tool = [[XPAdImageTool alloc] init];
});
return tool;
}
- (instancetype)init
{
self = [super init];
if (self) {
self.yyCache = [YYCache cacheWithName:CACHENAME];
}
return self;
}
//广
- (AdvertiseModel *)getAdInfoFromCacheInMainWith:(NSString *)link {
if (link.length > 0) {
if ([self.yyCache containsObjectForKey:link]) {
return (AdvertiseModel *)[self.yyCache objectForKey:link];
}else {
return nil;
}
}else {
return nil;
}
return nil;
}
///
- (void)saveAdInfo:(AdvertiseModel *)adInfo {
self.infoModel = adInfo;
NSArray *stringArr = [adInfo.pict componentsSeparatedByString:@"/"];
NSString *key = stringArr.lastObject;
[self.yyCache setObject:(id<NSCoding> )adInfo forKey:key withBlock:^{
}];
[self getAdvertisingImage];
}
/**
*
*/
- (BOOL)isFileExistWithFilePath:(NSString *)filePath {
NSFileManager *fileManager = [NSFileManager defaultManager];
BOOL isDirectory = FALSE;
return [fileManager fileExistsAtPath:filePath isDirectory:&isDirectory];
}
/**
* 广
*/
- (void)getAdvertisingImage {
if (self.infoModel.pict.length > 0) {
NSString *imageUrl = self.infoModel.pict;
//
NSArray *stringArr = [imageUrl componentsSeparatedByString:@"/"];
NSString *imageName = stringArr.lastObject;
//
NSString *filePath = [self getFilePathWithImageName:imageName];
BOOL isExist = [self isFileExistWithFilePath:filePath];
if (!isExist){//
[self downloadAdImageWithUrl:imageUrl imageName:imageName];
}
}else {
[self deleteOldImage];
}
}
/**
*
*/
- (void)downloadAdImageWithUrl:(NSString *)imageUrl imageName:(NSString *)imageName {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSString *filePath = [self getFilePathWithImageName:imageName]; //
if ([imageUrl.lowercaseString hasSuffix:@"svga"]) {
@kWeakify(self);
[[UploadFile share] download:imageUrl path:filePath complete:^{
@kStrongify(self);
[self deleteOldImage];
[[NSUserDefaults standardUserDefaults] setValue:imageName forKey:adImageName];
[[NSUserDefaults standardUserDefaults] synchronize];
} failure:^{
@kStrongify(self);
[self deleteOldImage];
}];
} else {
NSString *encode = [imageUrl stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:encode]];
UIImage *image = [UIImage imageWithData:data];
if ([UIImagePNGRepresentation(image) writeToFile:filePath atomically:YES]) {//
[self deleteOldImage];
[[NSUserDefaults standardUserDefaults] setValue:imageName forKey:adImageName];
[[NSUserDefaults standardUserDefaults] synchronize];
}else{
[self deleteOldImage];
}
}
});
}
/**
*
*/
- (void)deleteOldImage {
NSString *imageName = [[NSUserDefaults standardUserDefaults] valueForKey:adImageName];
if (imageName) {
NSString *filePath = [self getFilePathWithImageName:imageName];
NSFileManager *fileManager = [NSFileManager defaultManager];
[fileManager removeItemAtPath:filePath error:nil];
}
}
/**
*
*/
- (NSString *)getFilePathWithImageName:(NSString *)imageName {
if (imageName) {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory,NSUserDomainMask, YES);
NSString *filePath = [[paths xpSafeObjectAtIndex:0] stringByAppendingPathComponent:imageName];
return filePath;
}
return nil;
}
@end

View File

@@ -1,26 +0,0 @@
//
// YMAdvertiseView.h
// YUMI
//
// Created by YUMI on 2022/10/31.
//
#import <UIKit/UIKit.h>
#import "AdvertiseModel.h"
NS_ASSUME_NONNULL_BEGIN
@interface XPAdvertiseView : UIView
/** 显示广告页面方法*/
- (void)show;
/** 图片路径*/
@property (nonatomic, copy) NSString *filePath;
@property(nonatomic, assign) SplashInfoSkipType type;
@property(nonatomic, strong) AdvertiseFillModel *fileModel;
@property (nonatomic, strong) UIImage *adImage;
@property (nonatomic, copy) void(^dismissHandler)(BOOL shouldJump); //闪屏消失回调
@end
NS_ASSUME_NONNULL_END

View File

@@ -1,288 +0,0 @@
//
// YMAdvertiseView.m
// YUMI
//
// Created by YUMI on 2022/10/31.
//
#import "XPAdvertiseView.h"
#import "AppDelegate.h"
//tool
#import <SVGA.h>
#import <sys/sysctl.h>
#import <sys/utsname.h>
#import "YUMIMacroUitls.h"
///Tool
#import "UIImage+Utils.h"
NSString *const adImageName = @"adImageName";
NSString *const adUrl = @"adUrl";
// 广
static int const showtime = 3;
@interface XPAdvertiseView() <SVGAPlayerDelegate>
@property(nonatomic, strong) SVGAImageView *svgaView;
@property (nonatomic, strong) UIImageView *adView;//广
@property (nonatomic, strong) UIButton *countdownButton;//
@property (nonatomic, strong) NSTimer *countTimer;
@property (nonatomic, assign) int count;
@property (nonatomic, strong) UIWindow *window;
@property(nonatomic, strong) NSMutableArray *imageLoaders;
@end
@implementation XPAdvertiseView
#pragma mark - Initialize Methods
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
_adView = [[UIImageView alloc] initWithFrame:frame];
_adView.userInteractionEnabled = YES;
_adView.contentMode = UIViewContentModeScaleAspectFill;
_adView.clipsToBounds = YES;
[self addSubview:_adView];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onTapAdViewAction)];
[_adView addGestureRecognizer:tap];
[self addSubview:self.countdownButton];
[self.countdownButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.trailing.mas_equalTo(-24);
// make.width.mas_equalTo(60);
make.height.mas_equalTo(30);
make.top.mas_equalTo(40);
}];
// //
// if ([self needCountDownBtn]) {
// [self addSubview:self.countdownButton];
// }
}
return self;
}
#pragma mark - Public Methods
- (void)show {
// 1GCD
[self gcdCoundownHander];
UIWindow *keyWindow = [UIApplication sharedApplication].keyWindow;
[self.window.rootViewController.view addSubview:self];
[self.window makeKeyAndVisible];
[keyWindow makeKeyWindow];
}
#pragma mark - Event Response
///
- (void)onTapAdViewAction {
[self dismissWithJumpHandle:YES];
}
///
- (void)onClickSkipButton:(UIButton *)sender {
[self dismissWithJumpHandle:NO];
}
#pragma mark - Privite Method
// GCD
- (void)gcdCoundownHander {
__block int timeout = showtime;
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_source_t _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
dispatch_source_set_timer(_timer, DISPATCH_TIME_NOW, 1.0 * NSEC_PER_SEC, 0); //
dispatch_source_set_event_handler(_timer, ^{
if (timeout <= 0) { //
dispatch_source_cancel(_timer);
dispatch_async(dispatch_get_main_queue(), ^{
[self dismissWithJumpHandle:NO];
});
} else {
dispatch_async(dispatch_get_main_queue(), ^{
if (self.countdownButton) {
[self.countdownButton setTitle:YMLocalizedString(@"XPAdvertiseView0") forState:UIControlStateNormal];
}
});
timeout--;
}
});
dispatch_resume(_timer);
}
// 广
- (void)dismissWithJumpHandle:(BOOL)shouldJump {
if (self.countTimer) {
[self.countTimer invalidate];
self.countTimer = nil;
}
@kWeakify(self)
[UIView animateWithDuration:0.5f animations:^{
@kStrongify(self)
self.window.hidden = YES;
} completion:^(BOOL finished) {
@kStrongify(self)
[self removeFromSuperview];
self.window = nil;
!self.dismissHandler ?: self.dismissHandler(shouldJump);
}];
}
- (NSString *)deviceName {
// Gets a string with the device model
size_t size;
int nR = sysctlbyname("hw.machine", NULL, &size, NULL, 0);
char *machine = (char *)malloc(size);
nR = sysctlbyname("hw.machine", machine, &size, NULL, 0);
NSString *platform = [NSString stringWithCString:machine encoding:NSUTF8StringEncoding];
free(machine);
return platform;
}
- (BOOL)needCountDownBtn {
NSString *platform = [self deviceName];
BOOL needBtn = YES;
if ([platform isEqualToString:@"iPhone6,1"] ||
[platform isEqualToString:@"iPhone6,2"] ||
[platform isEqualToString:@"iPhone7,1"] ||
[platform isEqualToString:@"iPhone7,2"] ||
[platform isEqualToString:@"iPhone8,1"] ||
[platform isEqualToString:@"iPhone8,2"] ||
[platform isEqualToString:@"iPhone8,4"]) {
needBtn = NO;
}
return needBtn;
}
#pragma mark - Setter
- (void)setFilePath:(NSString *)filePath {
_filePath = filePath;
_imageLoaders = @[].mutableCopy;
if (self.type == SplashInfoSkipTypeWeb_CP || self.type == SplashInfoSkipTypeWeb_Custom || self.type == SplashInfoSkipTypeWeb_WeekStar) {
_svgaView = [[SVGAImageView alloc] initWithFrame:CGRectMake(0, 0, KScreenWidth, KScreenHeight)];
_svgaView.delegate = self;
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onTapAdViewAction)];
[_svgaView addGestureRecognizer:tap];
// [self addSubview:_svgaView];
[self insertSubview:_svgaView belowSubview:self.countdownButton];
SVGAParser *p = [[SVGAParser alloc] init];
@kWeakify(self);
[p parseWithURL:[[NSURL alloc] initFileURLWithPath:filePath] completionBlock:^(SVGAVideoEntity * _Nullable videoItem) {
@kStrongify(self);
if (videoItem) {
self.svgaView.autoPlay = YES;
self.svgaView.clearsAfterStop = YES;
self.svgaView.videoItem = videoItem;
if (self.fileModel) {
[self updateSvgaImage:self.fileModel.avatar key:@"avatar"];
[self updateSvgaImage:self.fileModel.picUrl key:@"gift"];
[self updateSvgaImage:self.fileModel.avatar key:@"avatar_1"];
[self updateSvgaImage:self.fileModel.loverAvatar key:@"avatar_2"];
[self updateSvgaText:[NSString stringWithFormat:@"ID: %@", self.fileModel.erbanNo] key:@"id"];
[self updateSvgaText:self.fileModel.giftName key:@"name"];
[self updateSvgaText:[NSString stringWithFormat:@"ID: %@", self.fileModel.erbanNo] key:@"id_1"];
[self updateSvgaText:[NSString stringWithFormat:@"ID: %@", self.fileModel.loverErbanNo] key:@"id_2"];
}
[self.svgaView startAnimation];
}
} failureBlock:^(NSError * _Nullable error) {
@kStrongify(self);
UIImage *image = [UIImage imageWithContentsOfFile:filePath];
self.adView.image = [image cutImage:[UIScreen mainScreen].bounds.size];
}];
} else {
UIImage *image = [UIImage imageWithContentsOfFile:filePath];
self.adView.image = [image cutImage:[UIScreen mainScreen].bounds.size];
}
}
- (void)updateSvgaImage:(NSString *)imagePath key:(NSString *)key {
if (self.svgaView && ![NSString isEmpty:imagePath] && ![NSString isEmpty:key]) {
UIImage *image = [UIImage imageWithColor:[UIColor colorWithWhite:0.9 alpha:0.9] size:CGSizeMake(100, 100)];
[self.svgaView setImage:image
forKey:key];
__block NetImageView *loader = [[NetImageView alloc] init];
@kWeakify(self);
@kWeakify(loader);
[loader loadImageWithUrl:imagePath
completion:^(UIImage * _Nullable image, NSURL * _Nonnull url) {
@kStrongify(self);
@kStrongify(loader);
[self.svgaView setImage:image
forKey:key];
[self.imageLoaders removeObject:loader];
}];
[self.imageLoaders addObject:loader];
}
}
- (void)updateSvgaText:(NSString *)content key:(NSString *)key {
if (self.svgaView && ![NSString isEmpty:content] && ![NSString isEmpty:key]) {
NSAttributedString *string = [[NSAttributedString alloc] initWithString:content
attributes:@{
NSFontAttributeName: kFontMedium(kGetScaleWidth(24)),
NSForegroundColorAttributeName: UIColorFromRGB(0xFDF565)
}];
[self.svgaView setAttributedText:string
forKey:key];
}
}
- (void)setAdImage:(UIImage *)adImage {
_adImage = adImage;
_adView.image = [adImage cutImage:[UIScreen mainScreen].bounds.size];
}
#pragma mark - SVGAPlayerDelegate
#pragma mark - Getter
- (UIWindow *)window {
if (_window == nil) {
_window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds];
_window.windowLevel = UIWindowLevelAlert;
_window.userInteractionEnabled = YES;
_window.rootViewController = [[UIViewController alloc] init];
}
return _window;
}
- (UIButton *)countdownButton {
if (_countdownButton == nil) {
_countdownButton = [UIButton buttonWithType:UIButtonTypeCustom];
[_countdownButton addTarget:self action:@selector(onClickSkipButton:) forControlEvents:UIControlEventTouchUpInside];
[_countdownButton setTitle:YMLocalizedString(@"XPAdvertiseView1") forState:UIControlStateNormal];
_countdownButton.titleLabel.font = [UIFont systemFontOfSize:15];
[_countdownButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
_countdownButton.backgroundColor = [UIColor colorWithRed:38 /255.0 green:38 /255.0 blue:38 /255.0 alpha:0.6];
_countdownButton.layer.cornerRadius = 4;
_countdownButton.contentEdgeInsets = UIEdgeInsetsMake(0, 8, 0, 8);
[_countdownButton sizeToFit];
}
return _countdownButton;
}
@end

View File

@@ -1,9 +1,7 @@
//
// DJDKMIMOMColor.h
// YUMI
//
// Created by YUMI on 2021/9/9.
//
#import <Foundation/Foundation.h>
@@ -13,62 +11,58 @@
NS_ASSUME_NONNULL_BEGIN
@interface DJDKMIMOMColor : NSObject
/// 主题色0x9682FF
+ (UIColor *)appMainColor;
///强调色 #248CFE
+ (UIColor *)appEmphasizeColor;
///强调色1 0xBF36FF
+ (UIColor *)appEmphasizeColor1;
///强调色2 0xFB486A
+ (UIColor *)appEmphasizeColor2;
/* ------页面相关颜色 START------ */
/// view的背景色 0xF3F5FA
+ (UIColor *)appBackgroundColor;
/// cell的背景色 0xFFFFFF
+ (UIColor *)appCellBackgroundColor;
///正文颜色 0x333333
+ (UIColor *)mainTextColor;
/// 二级文字颜色 0x666666
+ (UIColor *)secondTextColor;
///三级文字的颜色 0x999999
+ (UIColor *)textThirdColor;
///分割线的颜色 0xE8E8E8
+ (UIColor *)dividerColor;
/* ------页面相关颜色 END------ */
/* ------Button 相关颜色 START------ */
/// button 可用 渐变色的开始 0xFFA936
+ (UIColor *)confirmButtonGradientStartColor;
/// button 可用 渐变色的中间 #9CB3FF
+ (UIColor *)confirmButtonGradientMiddleColor;
/// button 可用 渐变色的开始 0xFFCB47
+ (UIColor *)confirmButtonGradientEndColor;
/// 确定的按钮文字颜色 #FFFFFF
+ (UIColor *)confirmButtonTextColor;
/// 取消按钮 渐变色的开始 0xF7DDBF
+ (UIColor *)cancelButtonGradientStartColor;
/// 取消按钮 渐变色的结束 0xF7E8C4
+ (UIColor *)cancelButtonGradientEndColor;
/// 取消的按钮文字颜色 0xFFA936
+ (UIColor *)cancelButtonTextColor;
/// 取消按钮单一普通背景色 0xFFCE4E
+ (UIColor *)cancelButtonNormalBgColor;
/// 按钮不可点击背景色 0xD2D5D7
+ (UIColor *)disableButtonColor;
/// 按钮不可点击文字颜色 0xF9F9F9
+ (UIColor *)disableButtonTextColor;
/* ------Button 相关颜色 END------ */
/* ------弹窗相关颜色 START------ */
+ (UIColor *)confirmButtonGradientMiddleColor;
+ (UIColor *)confirmButtonGradientEndColor;
+ (UIColor *)confirmButtonTextColor;
+ (UIColor *)cancelButtonGradientStartColor;
+ (UIColor *)cancelButtonGradientEndColor;
+ (UIColor *)cancelButtonTextColor;
+ (UIColor *)cancelButtonNormalBgColor;
+ (UIColor *)disableButtonColor;
+ (UIColor *)disableButtonTextColor;
+ (UIColor *)alertBackgroundColor;
+ (UIColor *)alertTitleColor;
+ (UIColor *)alertMessageColor;
+ (UIColor *)actionSeparatorColor;
/* ------弹窗相关颜色 END------ */
///tabbar 没有点击的时候颜色 0x333333, 0.4
+ (UIColor *)tabbarNormalColor;
/// tabbar的View的color 0xFFFFFF
+ (UIColor *)tabbarViewColor;
+ (UIColor *)colorWithHexString:(NSString *)hexString;

View File

@@ -1,105 +1,99 @@
//
// DJDKMIMOMColor.m
// YUMI
//
// Created by YUMI on 2021/9/9.
//
#import "DJDKMIMOMColor.h"
@implementation DJDKMIMOMColor
/// 0x9682FF
+ (UIColor *)appMainColor {
return UIColorFromRGB(0x9682FF);
}
/// #248CFE
+ (UIColor *)appEmphasizeColor {
return UIColorFromRGB(0x248CFE);
}
///1 0xBF36FF
+ (UIColor *)appEmphasizeColor1 {
return UIColorFromRGB(0xBF36FF);
}
///2 0xFB486A
+ (UIColor *)appEmphasizeColor2 {
return UIColorFromRGB(0xFB486A);
}
/* ------ START------ */
/// view 0xF3F5FA
+ (UIColor *)appBackgroundColor {
return UIColorFromRGB(0xF3F5FA);
}
/// cell 0xFFFFFF
+ (UIColor *)appCellBackgroundColor {
return UIColorFromRGB(0xFFFFFF);
}
/// 0x333333
+ (UIColor *)mainTextColor {
return UIColorFromRGB(0x161958);
}
/// 0x666666
+ (UIColor *)secondTextColor {
return UIColorFromRGB(0x8A8CAB);
}
/// 0x999999
+ (UIColor *)textThirdColor {
return UIColorFromRGB(0xBABBCD);
}
///线 0xE8E8E8
+ (UIColor *)dividerColor {
return UIColorFromRGB(0xE8E8E8);
}
/* ------ END------ */
/* ------Button START------ */
/// button 0x3CAAFF
+ (UIColor *)confirmButtonGradientStartColor {
return UIColorFromRGB(0x13E2F5);
}
/// button 0xB176FF
+ (UIColor *)confirmButtonGradientEndColor {
return UIColorFromRGB(0xCC66FF);
}
/// #FFFFFF
+ (UIColor *)confirmButtonTextColor {
return UIColorFromRGB(0xFFFFFF);
}
/// 0xF7DDBF
+ (UIColor *)cancelButtonGradientStartColor {
return UIColorFromRGB(0xCEEFFD);
}
/// button #9CB3FF
+ (UIColor *)confirmButtonGradientMiddleColor {
return UIColorFromRGB(0xf9CB3FF);
}
/// 0xF7E8C4
+ (UIColor *)cancelButtonGradientEndColor {
return UIColorFromRGB(0xD2F4F4);
}
/// 0xFFA936
+ (UIColor *)cancelButtonTextColor {
return UIColorFromRGB(0x5FCCE4);
}
/// 0xFFCE4E
+ (UIColor *)cancelButtonNormalBgColor {
return UIColorFromRGB(0xCEEFFD);
}
/// 0xD2D5D7
+ (UIColor *)disableButtonColor {
return UIColorFromRGB(0xCEEFFD);
}
/// 0xF9F9F9
+ (UIColor *)disableButtonTextColor {
return UIColorFromRGB(0xB3B3C3);
}
/* ------Button END------ */
/* ------ START------ */
+ (UIColor *)alertBackgroundColor {
return UIColorFromRGB(0xFFFFFF);
}
@@ -112,13 +106,12 @@
+ (UIColor *)actionSeparatorColor {
return UIColorFromRGB(0xF0F0F0);
}
/* ------ END------ */
///tabbar 0x333333, 0.4
+ (UIColor *)tabbarNormalColor {
return UIColorRGBAlpha(0x333333, 0.4);
}
/// tabbarViewcolor 0xFFFFFF
+ (UIColor *)tabbarViewColor {
return UIColorFromRGB(0xFFFFFF);
}
@@ -130,25 +123,25 @@
NSString *colorString = [[hexString stringByReplacingOccurrencesOfString: @"#" withString: @""] uppercaseString];
CGFloat alpha, red, blue, green;
switch ([colorString length]) {
case 3: // #RGB
case 3:
alpha = 1.0f;
red = [self colorComponentFrom: colorString start: 0 length: 1];
green = [self colorComponentFrom: colorString start: 1 length: 1];
blue = [self colorComponentFrom: colorString start: 2 length: 1];
break;
case 4: // #ARGB
case 4:
alpha = [self colorComponentFrom: colorString start: 0 length: 1];
red = [self colorComponentFrom: colorString start: 1 length: 1];
green = [self colorComponentFrom: colorString start: 2 length: 1];
blue = [self colorComponentFrom: colorString start: 3 length: 1];
break;
case 6: // #RRGGBB
case 6:
alpha = 1.0f;
red = [self colorComponentFrom: colorString start: 0 length: 2];
green = [self colorComponentFrom: colorString start: 2 length: 2];
blue = [self colorComponentFrom: colorString start: 4 length: 2];
break;
case 8: // #AARRGGBB
case 8:
alpha = [self colorComponentFrom: colorString start: 0 length: 2];
red = [self colorComponentFrom: colorString start: 2 length: 2];
green = [self colorComponentFrom: colorString start: 4 length: 2];
@@ -169,7 +162,7 @@
return hexComponent / 255.0;
}
/// #1F1A4E
+ (UIColor *)inputTextColor {
return [self colorWithHexString:@"#1F1A4E"];
}

View File

@@ -1,16 +0,0 @@
//
// EmptyDataView.h
// YuMi
//
// Created by P on 2024/12/23.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface EmptyDataView : UIView
@end
NS_ASSUME_NONNULL_END

View File

@@ -1,20 +0,0 @@
//
// EmptyDataView.m
// YuMi
//
// Created by P on 2024/12/23.
//
#import "EmptyDataView.h"
@implementation EmptyDataView
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
// Drawing code
}
*/
@end

View File

@@ -1,6 +0,0 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -1,6 +0,0 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -1,6 +0,0 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -1,54 +0,0 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "chat_icon_emoji_black_l_normal@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"filename" : "chat_icon_emoji_black_l_normal@2x-1.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "chat_icon_emoji_black_l_normal@3x.png",
"idiom" : "universal",
"scale" : "3x"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"filename" : "chat_icon_emoji_black_l_normal@3x-1.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -1,54 +0,0 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "chat_icon_more_black_l_normal@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"filename" : "chat_icon_more_black_l_normal@2x-1.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "chat_icon_more_black_l_normal@3x.png",
"idiom" : "universal",
"scale" : "3x"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"filename" : "chat_icon_more_black_l_normal@3x-1.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -1,54 +0,0 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "chat_icon_keyboard_black_l_normal@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"filename" : "chat_icon_keyboard_black_l_normal@2x-1.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "chat_icon_keyboard_black_l_normal@3x.png",
"idiom" : "universal",
"scale" : "3x"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"filename" : "chat_icon_keyboard_black_l_normal@3x-1.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -1,54 +0,0 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "chat_icon_voice@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"filename" : "chat_icon_voice_dark@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "chat_icon_voice@3x.png",
"idiom" : "universal",
"scale" : "3x"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"filename" : "chat_icon_voice_dark@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -1,22 +0,0 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "compose_emotion_delete_highlighted.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "compose_emotion_delete_highlighted-1.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -1,52 +0,0 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "white_rect.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"filename" : "white_btn_dark.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 543 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 83 B

View File

@@ -1,52 +0,0 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "white_rect.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"filename" : "white_input_btn_dark.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 542 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 83 B

View File

@@ -1,52 +0,0 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "white_input_press_btn.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"filename" : "white_input_press_btn_dark.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

View File

@@ -1,131 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<PopoEmoticons>
<Catalog ID="default" Title="emoji" Icon="emoj_s_normal.png" IconPressed="emoj_s_pressed.png">
<Emoticon ID="emoticon_emoji_01" Tag="[可爱]" File="emoji_01.png" />
<Emoticon ID="emoticon_emoji_0" Tag="[大笑]" File="emoji_00.png" />
<Emoticon ID="emoticon_emoji_02" Tag="[色]" File="emoji_02.png" />
<Emoticon ID="emoticon_emoji_03" Tag="[嘘]" File="emoji_03.png" />
<Emoticon ID="emoticon_emoji_04" Tag="[亲]" File="emoji_04.png" />
<Emoticon ID="emoticon_emoji_05" Tag="[呆]" File="emoji_05.png" />
<Emoticon ID="emoticon_emoji_06" Tag="[口水]" File="emoji_06.png" />
<Emoticon ID="emoticon_emoji_145" Tag="[汗]" File="emoji_145.png" />
<Emoticon ID="emoticon_emoji_07" Tag="[呲牙]" File="emoji_07.png" />
<Emoticon ID="emoticon_emoji_08" Tag="[鬼脸]" File="emoji_08.png" />
<Emoticon ID="emoticon_emoji_09" Tag="[害羞]" File="emoji_09.png" />
<Emoticon ID="emoticon_emoji_10" Tag="[偷笑]" File="emoji_10.png" />
<Emoticon ID="emoticon_emoji_11" Tag="[调皮]" File="emoji_11.png" />
<Emoticon ID="emoticon_emoji_12" Tag="[可怜]" File="emoji_12.png" />
<Emoticon ID="emoticon_emoji_13" Tag="[敲]" File="emoji_13.png" />
<Emoticon ID="emoticon_emoji_14" Tag="[惊讶]" File="emoji_14.png" />
<Emoticon ID="emoticon_emoji_15" Tag="[流感]" File="emoji_15.png" />
<Emoticon ID="emoticon_emoji_16" Tag="[委屈]" File="emoji_16.png" />
<Emoticon ID="emoticon_emoji_17" Tag="[流泪]" File="emoji_17.png" />
<Emoticon ID="emoticon_emoji_18" Tag="[嚎哭]" File="emoji_18.png" />
<Emoticon ID="emoticon_emoji_19" Tag="[惊恐]" File="emoji_19.png" />
<Emoticon ID="emoticon_emoji_20" Tag="[怒]" File="emoji_20.png" />
<Emoticon ID="emoticon_emoji_21" Tag="[酷]" File="emoji_21.png" />
<Emoticon ID="emoticon_emoji_22" Tag="[不说]" File="emoji_22.png" />
<Emoticon ID="emoticon_emoji_23" Tag="[鄙视]" File="emoji_23.png" />
<Emoticon ID="emoticon_emoji_24" Tag="[阿弥陀佛]" File="emoji_24.png" />
<Emoticon ID="emoticon_emoji_25" Tag="[奸笑]" File="emoji_25.png" />
<Emoticon ID="emoticon_emoji_26" Tag="[睡着]" File="emoji_26.png" />
<Emoticon ID="emoticon_emoji_27" Tag="[口罩]" File="emoji_27.png" />
<Emoticon ID="emoticon_emoji_28" Tag="[努力]" File="emoji_28.png" />
<Emoticon ID="emoticon_emoji_29" Tag="[抠鼻孔]" File="emoji_29.png" />
<Emoticon ID="emoticon_emoji_30" Tag="[疑问]" File="emoji_30.png" />
<Emoticon ID="emoticon_emoji_31" Tag="[怒骂]" File="emoji_31.png" />
<Emoticon ID="emoticon_emoji_32" Tag="[晕]" File="emoji_32.png" />
<Emoticon ID="emoticon_emoji_33" Tag="[呕吐]" File="emoji_33.png" />
<Emoticon ID="emoticon_emoji_160" Tag="[拜一拜]" File="emoji_160.png" />
<Emoticon ID="emoticon_emoji_161" Tag="[惊喜]" File="emoji_161.png" />
<Emoticon ID="emoticon_emoji_162" Tag="[流汗]" File="emoji_162.png" />
<Emoticon ID="emoticon_emoji_163" Tag="[卖萌]" File="emoji_163.png" />
<Emoticon ID="emoticon_emoji_164" Tag="[默契眨眼]" File="emoji_164.png" />
<Emoticon ID="emoticon_emoji_165" Tag="[烧香拜佛]" File="emoji_165.png" />
<Emoticon ID="emoticon_emoji_166" Tag="[晚安]" File="emoji_166.png" />
<Emoticon ID="emoticon_emoji_34" Tag="[强]" File="emoji_34.png" />
<Emoticon ID="emoticon_emoji_35" Tag="[弱]" File="emoji_35.png" />
<Emoticon ID="emoticon_emoji_36" Tag="[OK]" File="emoji_36.png" />
<Emoticon ID="emoticon_emoji_37" Tag="[拳头]" File="emoji_37.png" />
<Emoticon ID="emoticon_emoji_38" Tag="[胜利]" File="emoji_38.png" />
<Emoticon ID="emoticon_emoji_39" Tag="[鼓掌]" File="emoji_39.png" />
<Emoticon ID="emoticon_emoji_200" Tag="[握手]" File="emoji_200.png" />
<Emoticon ID="emoticon_emoji_40" Tag="[发怒]" File="emoji_40.png" />
<Emoticon ID="emoticon_emoji_41" Tag="[骷髅]" File="emoji_41.png" />
<Emoticon ID="emoticon_emoji_42" Tag="[便便]" File="emoji_42.png" />
<Emoticon ID="emoticon_emoji_43" Tag="[火]" File="emoji_43.png" />
<Emoticon ID="emoticon_emoji_44" Tag="[溜]" File="emoji_44.png" />
<Emoticon ID="emoticon_emoji_45" Tag="[爱心]" File="emoji_45.png" />
<Emoticon ID="emoticon_emoji_46" Tag="[心碎]" File="emoji_46.png" />
<Emoticon ID="emoticon_emoji_47" Tag="[钟情]" File="emoji_47.png" />
<Emoticon ID="emoticon_emoji_48" Tag="[唇]" File="emoji_48.png" />
<Emoticon ID="emoticon_emoji_49" Tag="[戒指]" File="emoji_49.png" />
<Emoticon ID="emoticon_emoji_50" Tag="[钻石]" File="emoji_50.png" />
<Emoticon ID="emoticon_emoji_51" Tag="[太阳]" File="emoji_51.png" />
<Emoticon ID="emoticon_emoji_52" Tag="[有时晴]" File="emoji_52.png" />
<Emoticon ID="emoticon_emoji_53" Tag="[多云]" File="emoji_53.png" />
<Emoticon ID="emoticon_emoji_54" Tag="[雷]" File="emoji_54.png" />
<Emoticon ID="emoticon_emoji_55" Tag="[雨]" File="emoji_55.png" />
<Emoticon ID="emoticon_emoji_56" Tag="[雪花]" File="emoji_56.png" />
<Emoticon ID="emoticon_emoji_57" Tag="[爱人]" File="emoji_57.png" />
<Emoticon ID="emoticon_emoji_58" Tag="[帽子]" File="emoji_58.png" />
<Emoticon ID="emoticon_emoji_59" Tag="[皇冠]" File="emoji_59.png" />
<Emoticon ID="emoticon_emoji_60" Tag="[篮球]" File="emoji_60.png" />
<Emoticon ID="emoticon_emoji_61" Tag="[足球]" File="emoji_61.png" />
<Emoticon ID="emoticon_emoji_62" Tag="[垒球]" File="emoji_62.png" />
<Emoticon ID="emoticon_emoji_63" Tag="[网球]" File="emoji_63.png" />
<Emoticon ID="emoticon_emoji_64" Tag="[台球]" File="emoji_64.png" />
<Emoticon ID="emoticon_emoji_65" Tag="[咖啡]" File="emoji_65.png" />
<Emoticon ID="emoticon_emoji_66" Tag="[啤酒]" File="emoji_66.png" />
<Emoticon ID="emoticon_emoji_67" Tag="[干杯]" File="emoji_67.png" />
<Emoticon ID="emoticon_emoji_68" Tag="[柠檬汁]" File="emoji_68.png" />
<Emoticon ID="emoticon_emoji_69" Tag="[餐具]" File="emoji_69.png" />
<Emoticon ID="emoticon_emoji_70" Tag="[汉堡]" File="emoji_70.png" />
<Emoticon ID="emoticon_emoji_71" Tag="[鸡腿]" File="emoji_71.png" />
<Emoticon ID="emoticon_emoji_72" Tag="[面条]" File="emoji_72.png" />
<Emoticon ID="emoticon_emoji_73" Tag="[冰淇淋]" File="emoji_73.png" />
<Emoticon ID="emoticon_emoji_74" Tag="[沙冰]" File="emoji_74.png" />
<Emoticon ID="emoticon_emoji_75" Tag="[生日蛋糕]" File="emoji_75.png" />
<Emoticon ID="emoticon_emoji_76" Tag="[蛋糕]" File="emoji_76.png" />
<Emoticon ID="emoticon_emoji_77" Tag="[糖果]" File="emoji_77.png" />
<Emoticon ID="emoticon_emoji_78" Tag="[葡萄]" File="emoji_78.png" />
<Emoticon ID="emoticon_emoji_79" Tag="[西瓜]" File="emoji_79.png" />
<Emoticon ID="emoticon_emoji_80" Tag="[光碟]" File="emoji_80.png" />
<Emoticon ID="emoticon_emoji_81" Tag="[手机]" File="emoji_81.png" />
<Emoticon ID="emoticon_emoji_82" Tag="[电话]" File="emoji_82.png" />
<Emoticon ID="emoticon_emoji_83" Tag="[电视]" File="emoji_83.png" />
<Emoticon ID="emoticon_emoji_84" Tag="[声音开启]" File="emoji_84.png" />
<Emoticon ID="emoticon_emoji_85" Tag="[声音关闭]" File="emoji_85.png" />
<Emoticon ID="emoticon_emoji_86" Tag="[铃铛]" File="emoji_86.png" />
<Emoticon ID="emoticon_emoji_87" Tag="[锁头]" File="emoji_87.png" />
<Emoticon ID="emoticon_emoji_88" Tag="[放大镜]" File="emoji_88.png" />
<Emoticon ID="emoticon_emoji_89" Tag="[灯泡]" File="emoji_89.png" />
<Emoticon ID="emoticon_emoji_90" Tag="[锤头]" File="emoji_90.png" />
<Emoticon ID="emoticon_emoji_91" Tag="[烟]" File="emoji_91.png" />
<Emoticon ID="emoticon_emoji_92" Tag="[炸弹]" File="emoji_92.png" />
<Emoticon ID="emoticon_emoji_93" Tag="[枪]" File="emoji_93.png" />
<Emoticon ID="emoticon_emoji_94" Tag="[刀]" File="emoji_94.png" />
<Emoticon ID="emoticon_emoji_95" Tag="[药]" File="emoji_95.png" />
<Emoticon ID="emoticon_emoji_96" Tag="[打针]" File="emoji_96.png" />
<Emoticon ID="emoticon_emoji_97" Tag="[钱袋]" File="emoji_97.png" />
<Emoticon ID="emoticon_emoji_98" Tag="[钞票]" File="emoji_98.png" />
<Emoticon ID="emoticon_emoji_99" Tag="[银行卡]" File="emoji_99.png" />
<Emoticon ID="emoticon_emoji_100" Tag="[手柄]" File="emoji_100.png" />
<Emoticon ID="emoticon_emoji_101" Tag="[麻将]" File="emoji_101.png" />
<Emoticon ID="emoticon_emoji_102" Tag="[调色板]" File="emoji_102.png" />
<Emoticon ID="emoticon_emoji_103" Tag="[电影]" File="emoji_103.png" />
<Emoticon ID="emoticon_emoji_104" Tag="[麦克风]" File="emoji_104.png" />
<Emoticon ID="emoticon_emoji_105" Tag="[耳机]" File="emoji_105.png" />
<Emoticon ID="emoticon_emoji_106" Tag="[音乐]" File="emoji_106.png" />
<Emoticon ID="emoticon_emoji_107" Tag="[吉他]" File="emoji_107.png" />
<Emoticon ID="emoticon_emoji_108" Tag="[火箭]" File="emoji_108.png" />
<Emoticon ID="emoticon_emoji_109" Tag="[飞机]" File="emoji_109.png" />
<Emoticon ID="emoticon_emoji_110" Tag="[火车]" File="emoji_110.png" />
<Emoticon ID="emoticon_emoji_111" Tag="[公交]" File="emoji_111.png" />
<Emoticon ID="emoticon_emoji_112" Tag="[轿车]" File="emoji_112.png" />
<Emoticon ID="emoticon_emoji_113" Tag="[出租车]" File="emoji_113.png" />
<Emoticon ID="emoticon_emoji_114" Tag="[警车]" File="emoji_114.png" />
<Emoticon ID="emoticon_emoji_115" Tag="[自行车]" File="emoji_115.png" />
</Catalog>
</PopoEmoticons>
˜

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.1 KiB

Some files were not shown because too many files have changed in this diff Show More