1期开发

This commit is contained in:
zjx 2025-07-22 19:59:14 +08:00
parent 698f1b941d
commit 9f406e7fe0
103 changed files with 2792 additions and 32 deletions

View File

@ -18,6 +18,25 @@
BF02B7EF2E2E4BFD00172177 /* BRRateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF02B7EE2E2E4BFD00172177 /* BRRateModel.swift */; };
BF02B7F12E2E55E300172177 /* BRRateSelectorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF02B7F02E2E55E300172177 /* BRRateSelectorView.swift */; };
BF02B7F32E2E571600172177 /* BRRateSelectorCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF02B7F22E2E571600172177 /* BRRateSelectorCell.swift */; };
BF02B7F52E2F203D00172177 /* BRHomeCategoriesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF02B7F42E2F203D00172177 /* BRHomeCategoriesViewController.swift */; };
BF02B7F82E2F211A00172177 /* BRHomeCategoriesMainCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF02B7F72E2F211A00172177 /* BRHomeCategoriesMainCell.swift */; };
BF02B7FA2E2F225D00172177 /* BRHomeCategoryModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF02B7F92E2F225D00172177 /* BRHomeCategoryModel.swift */; };
BF02B7FC2E2F262F00172177 /* BRGradientView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF02B7FB2E2F262F00172177 /* BRGradientView.swift */; };
BF02B7FF2E2F2F2900172177 /* BRHomeCategoriesCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF02B7FD2E2F2F2900172177 /* BRHomeCategoriesCell.swift */; };
BF02B8022E2F39FE00172177 /* BRCategorieShortViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF02B8012E2F39FE00172177 /* BRCategorieShortViewController.swift */; };
BF02B8042E2F5B4B00172177 /* BRCategorieShortCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF02B8032E2F5B4B00172177 /* BRCategorieShortCell.swift */; };
BF02B8082E2F616E00172177 /* BRFavoritesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF02B8072E2F616E00172177 /* BRFavoritesViewController.swift */; };
BF02B80D2E2F63ED00172177 /* BRFavoritesCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF02B80C2E2F63ED00172177 /* BRFavoritesCell.swift */; };
BF02B80F2E2F6EEA00172177 /* BRFavoritesHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF02B80E2E2F6EEA00172177 /* BRFavoritesHeaderView.swift */; };
BF02B8132E2F83C200172177 /* BRMineViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF02B8122E2F83C200172177 /* BRMineViewController.swift */; };
BF02B8172E2F881200172177 /* BRMineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF02B8162E2F881200172177 /* BRMineItem.swift */; };
BF02B8192E2F8B1100172177 /* BRMineCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF02B8182E2F8B1100172177 /* BRMineCell.swift */; };
BF02B81B2E2F8FDF00172177 /* BRMineUserInfoCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF02B81A2E2F8FDF00172177 /* BRMineUserInfoCell.swift */; };
BF02B81E2E2F99D900172177 /* BRWebView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF02B81D2E2F99D900172177 /* BRWebView.swift */; };
BF02B8202E2F9B1000172177 /* BRWebViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF02B81F2E2F9B1000172177 /* BRWebViewController.swift */; };
BF02B8222E2FAB1600172177 /* BRAboutUsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF02B8212E2FAB1600172177 /* BRAboutUsViewController.swift */; };
BF02B8242E2FAEB500172177 /* BRAboutUsCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF02B8232E2FAEB500172177 /* BRAboutUsCell.swift */; };
BF02B8262E2FB36A00172177 /* BRAboutUsHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF02B8252E2FB36A00172177 /* BRAboutUsHeaderView.swift */; };
BF0DBDD12E0D4E150035F6B4 /* BRTabBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF0DBDD02E0D4E150035F6B4 /* BRTabBar.swift */; };
BF3338E82E15219500B10F76 /* UINavigationBar+BRAdd.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF3338E72E15218F00B10F76 /* UINavigationBar+BRAdd.swift */; };
BF3338EA2E152B8100B10F76 /* BRPlayerCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF3338E92E152B8100B10F76 /* BRPlayerCache.swift */; };
@ -133,6 +152,25 @@
BF02B7EE2E2E4BFD00172177 /* BRRateModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BRRateModel.swift; sourceTree = "<group>"; };
BF02B7F02E2E55E300172177 /* BRRateSelectorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BRRateSelectorView.swift; sourceTree = "<group>"; };
BF02B7F22E2E571600172177 /* BRRateSelectorCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BRRateSelectorCell.swift; sourceTree = "<group>"; };
BF02B7F42E2F203D00172177 /* BRHomeCategoriesViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BRHomeCategoriesViewController.swift; sourceTree = "<group>"; };
BF02B7F72E2F211A00172177 /* BRHomeCategoriesMainCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BRHomeCategoriesMainCell.swift; sourceTree = "<group>"; };
BF02B7F92E2F225D00172177 /* BRHomeCategoryModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BRHomeCategoryModel.swift; sourceTree = "<group>"; };
BF02B7FB2E2F262F00172177 /* BRGradientView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BRGradientView.swift; sourceTree = "<group>"; };
BF02B7FD2E2F2F2900172177 /* BRHomeCategoriesCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BRHomeCategoriesCell.swift; sourceTree = "<group>"; };
BF02B8012E2F39FE00172177 /* BRCategorieShortViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BRCategorieShortViewController.swift; sourceTree = "<group>"; };
BF02B8032E2F5B4B00172177 /* BRCategorieShortCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BRCategorieShortCell.swift; sourceTree = "<group>"; };
BF02B8072E2F616E00172177 /* BRFavoritesViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BRFavoritesViewController.swift; sourceTree = "<group>"; };
BF02B80C2E2F63ED00172177 /* BRFavoritesCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BRFavoritesCell.swift; sourceTree = "<group>"; };
BF02B80E2E2F6EEA00172177 /* BRFavoritesHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BRFavoritesHeaderView.swift; sourceTree = "<group>"; };
BF02B8122E2F83C200172177 /* BRMineViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BRMineViewController.swift; sourceTree = "<group>"; };
BF02B8162E2F881200172177 /* BRMineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BRMineItem.swift; sourceTree = "<group>"; };
BF02B8182E2F8B1100172177 /* BRMineCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BRMineCell.swift; sourceTree = "<group>"; };
BF02B81A2E2F8FDF00172177 /* BRMineUserInfoCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BRMineUserInfoCell.swift; sourceTree = "<group>"; };
BF02B81D2E2F99D900172177 /* BRWebView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BRWebView.swift; sourceTree = "<group>"; };
BF02B81F2E2F9B1000172177 /* BRWebViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BRWebViewController.swift; sourceTree = "<group>"; };
BF02B8212E2FAB1600172177 /* BRAboutUsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BRAboutUsViewController.swift; sourceTree = "<group>"; };
BF02B8232E2FAEB500172177 /* BRAboutUsCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BRAboutUsCell.swift; sourceTree = "<group>"; };
BF02B8252E2FB36A00172177 /* BRAboutUsHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BRAboutUsHeaderView.swift; sourceTree = "<group>"; };
BF0DBDD02E0D4E150035F6B4 /* BRTabBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BRTabBar.swift; sourceTree = "<group>"; };
BF3338E72E15218F00B10F76 /* UINavigationBar+BRAdd.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UINavigationBar+BRAdd.swift"; sourceTree = "<group>"; };
BF3338E92E152B8100B10F76 /* BRPlayerCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BRPlayerCache.swift; sourceTree = "<group>"; };
@ -273,6 +311,89 @@
path = Pods;
sourceTree = "<group>";
};
BF02B7F62E2F20F900172177 /* Categories */ = {
isa = PBXGroup;
children = (
BF02B8032E2F5B4B00172177 /* BRCategorieShortCell.swift */,
BF02B7F72E2F211A00172177 /* BRHomeCategoriesMainCell.swift */,
BF02B7FD2E2F2F2900172177 /* BRHomeCategoriesCell.swift */,
);
path = Categories;
sourceTree = "<group>";
};
BF02B8052E2F612200172177 /* Favorites */ = {
isa = PBXGroup;
children = (
BF02B8062E2F613600172177 /* Controller */,
BF02B80B2E2F63C600172177 /* View */,
);
path = Favorites;
sourceTree = "<group>";
};
BF02B8062E2F613600172177 /* Controller */ = {
isa = PBXGroup;
children = (
BF02B8072E2F616E00172177 /* BRFavoritesViewController.swift */,
);
path = Controller;
sourceTree = "<group>";
};
BF02B80B2E2F63C600172177 /* View */ = {
isa = PBXGroup;
children = (
BF02B80C2E2F63ED00172177 /* BRFavoritesCell.swift */,
BF02B80E2E2F6EEA00172177 /* BRFavoritesHeaderView.swift */,
);
path = View;
sourceTree = "<group>";
};
BF02B8102E2F83A100172177 /* Mine */ = {
isa = PBXGroup;
children = (
BF02B8112E2F83AA00172177 /* Controller */,
BF02B8142E2F87D800172177 /* View */,
BF02B8152E2F87E000172177 /* Model */,
);
path = Mine;
sourceTree = "<group>";
};
BF02B8112E2F83AA00172177 /* Controller */ = {
isa = PBXGroup;
children = (
BF02B8122E2F83C200172177 /* BRMineViewController.swift */,
BF02B8212E2FAB1600172177 /* BRAboutUsViewController.swift */,
);
path = Controller;
sourceTree = "<group>";
};
BF02B8142E2F87D800172177 /* View */ = {
isa = PBXGroup;
children = (
BF02B8182E2F8B1100172177 /* BRMineCell.swift */,
BF02B81A2E2F8FDF00172177 /* BRMineUserInfoCell.swift */,
BF02B8232E2FAEB500172177 /* BRAboutUsCell.swift */,
BF02B8252E2FB36A00172177 /* BRAboutUsHeaderView.swift */,
);
path = View;
sourceTree = "<group>";
};
BF02B8152E2F87E000172177 /* Model */ = {
isa = PBXGroup;
children = (
BF02B8162E2F881200172177 /* BRMineItem.swift */,
);
path = Model;
sourceTree = "<group>";
};
BF02B81C2E2F996B00172177 /* WebView */ = {
isa = PBXGroup;
children = (
BF02B81D2E2F99D900172177 /* BRWebView.swift */,
BF02B81F2E2F9B1000172177 /* BRWebViewController.swift */,
);
path = WebView;
sourceTree = "<group>";
};
BF3338ED2E15566C00B10F76 /* Explore */ = {
isa = PBXGroup;
children = (
@ -357,6 +478,7 @@
children = (
BF692B352E0A8AF200A5C2DA /* Controller */,
BF692B522E0AA8D600A5C2DA /* View */,
BF02B81C2E2F996B00172177 /* WebView */,
BF692B0C2E0A7A9A00A5C2DA /* Extension */,
BF692B052E0A770F00A5C2DA /* Model */,
BF692AFF2E0A748D00A5C2DA /* Define */,
@ -368,6 +490,8 @@
BF692AF52E0A47D400A5C2DA /* Class */ = {
isa = PBXGroup;
children = (
BF02B8102E2F83A100172177 /* Mine */,
BF02B8052E2F612200172177 /* Favorites */,
BF3338ED2E15566C00B10F76 /* Explore */,
BF692B682E0BC78C00A5C2DA /* Home */,
BF692B4A2E0AA84C00A5C2DA /* Player */,
@ -587,6 +711,7 @@
BFC676742E0E93B3006659E5 /* BRTableViewCell.swift */,
BF02B7E62E2E1F0500172177 /* BRPanModalContentView.swift */,
BF02B7EC2E2E390500172177 /* BRScrollView.swift */,
BF02B7FB2E2F262F00172177 /* BRGradientView.swift */,
);
path = View;
sourceTree = "<group>";
@ -621,6 +746,8 @@
BFC6769C2E129794006659E5 /* BRHomeTop10ViewController.swift */,
BFC676B02E137D2F006659E5 /* BRPopularPicksViewController.swift */,
BFC676BB2E138ABB006659E5 /* BRNewReleasesViewController.swift */,
BF02B7F42E2F203D00172177 /* BRHomeCategoriesViewController.swift */,
BF02B8012E2F39FE00172177 /* BRCategorieShortViewController.swift */,
);
path = Controller;
sourceTree = "<group>";
@ -628,6 +755,7 @@
BF692B6C2E0BD4B200A5C2DA /* View */ = {
isa = PBXGroup;
children = (
BF02B7F62E2F20F900172177 /* Categories */,
BFC676BA2E138A9A006659E5 /* NewReleases */,
BFC676AC2E137687006659E5 /* PopularPicks */,
BFC6769E2E129CE5006659E5 /* Top10 */,
@ -666,6 +794,7 @@
BF692B792E0D3BD300A5C2DA /* BRShortModel.swift */,
BF692B7B2E0D3C1300A5C2DA /* BRVideoInfoModel.swift */,
BFC6769A2E1285C5006659E5 /* BRPagerViewTransformer.swift */,
BF02B7F92E2F225D00172177 /* BRHomeCategoryModel.swift */,
);
path = Model;
sourceTree = "<group>";
@ -878,8 +1007,10 @@
BF02B7F32E2E571600172177 /* BRRateSelectorCell.swift in Sources */,
BFC676992E1280E3006659E5 /* BRSpotlightRecommandCell.swift in Sources */,
BFC676A42E129D60006659E5 /* BRHomeTop10Cell.swift in Sources */,
BF02B8262E2FB36A00172177 /* BRAboutUsHeaderView.swift in Sources */,
BF692B3C2E0A8D0200A5C2DA /* BRNavigationController.swift in Sources */,
BFC676B12E137D2F006659E5 /* BRPopularPicksViewController.swift in Sources */,
BF02B7FC2E2F262F00172177 /* BRGradientView.swift in Sources */,
BFC676692E0E34DA006659E5 /* BRUserAPI.swift in Sources */,
BFC676782E0E9553006659E5 /* BRSpotlightMainBaseCell.swift in Sources */,
BFC676732E0E938B006659E5 /* BRTableView.swift in Sources */,
@ -889,8 +1020,12 @@
BF692B132E0A7B9000A5C2DA /* BRUserInfo.swift in Sources */,
BF692B042E0A76D200A5C2DA /* BRLoginManager.swift in Sources */,
BFC6769D2E129794006659E5 /* BRHomeTop10ViewController.swift in Sources */,
BF02B80D2E2F63ED00172177 /* BRFavoritesCell.swift in Sources */,
BF692AEB2E0A475D00A5C2DA /* AppDelegate.swift in Sources */,
BF02B81B2E2F8FDF00172177 /* BRMineUserInfoCell.swift in Sources */,
BF02B8202E2F9B1000172177 /* BRWebViewController.swift in Sources */,
BF692B242E0A825B00A5C2DA /* BRCryptorService.swift in Sources */,
BF02B8242E2FAEB500172177 /* BRAboutUsCell.swift in Sources */,
BF692B342E0A87C800A5C2DA /* UIDevice+BRAdd.swift in Sources */,
BF692B3E2E0A8D2300A5C2DA /* BRTabBarController.swift in Sources */,
BF02B7E12E2DE64200172177 /* BRVideoProgressView.swift in Sources */,
@ -904,6 +1039,8 @@
BF692B7C2E0D3C1300A5C2DA /* BRVideoInfoModel.swift in Sources */,
BFC6766D2E0E3A8D006659E5 /* BRImageView.swift in Sources */,
BF02B7ED2E2E390500172177 /* BRScrollView.swift in Sources */,
BF02B8132E2F83C200172177 /* BRMineViewController.swift in Sources */,
BF02B8222E2FAB1600172177 /* BRAboutUsViewController.swift in Sources */,
BFC6766F2E0E3B5C006659E5 /* UIImageView+BRAdd.swift in Sources */,
BF692B782E0D3A1200A5C2DA /* BRHomeModuleItem.swift in Sources */,
BF692B5A2E0AAADD00A5C2DA /* BRPlayerListCell.swift in Sources */,
@ -919,19 +1056,24 @@
BF692B422E0A8FB500A5C2DA /* UIFont+BRAdd.swift in Sources */,
BF692AEC2E0A475D00A5C2DA /* SceneDelegate.swift in Sources */,
BF692B492E0A9D0E00A5C2DA /* UIView+BRAdd.swift in Sources */,
BF02B7F82E2F211A00172177 /* BRHomeCategoriesMainCell.swift in Sources */,
BF02B8192E2F8B1100172177 /* BRMineCell.swift in Sources */,
BFC676812E122733006659E5 /* BRPlayerProtocol.swift in Sources */,
BFC676BC2E138ABB006659E5 /* BRNewReleasesViewController.swift in Sources */,
BF692B5F2E0B812800A5C2DA /* BRTabBarItemContainer.swift in Sources */,
BF3338EC2E154BFE00B10F76 /* BRPlayerControlView.swift in Sources */,
BF692B652E0BC53900A5C2DA /* CGMutablePath+BRRoundedCorner.swift in Sources */,
BF02B7F52E2F203D00172177 /* BRHomeCategoriesViewController.swift in Sources */,
BFC676752E0E93B3006659E5 /* BRTableViewCell.swift in Sources */,
BF78108B2E0D4EB3007DEEBC /* BRURLPath.swift in Sources */,
BF692B092E0A775500A5C2DA /* BRLoginToken.swift in Sources */,
BF692AFC2E0A6F8000A5C2DA /* BRNetworkTarget.swift in Sources */,
BF02B7FF2E2F2F2900172177 /* BRHomeCategoriesCell.swift in Sources */,
BF692B3A2E0A8C6000A5C2DA /* BRViewController.swift in Sources */,
BFC676BE2E13A8EB006659E5 /* UIScrollView+BRRefresh.swift in Sources */,
BF692B182E0A7D8900A5C2DA /* BRToast.swift in Sources */,
BF692B0E2E0A7AF300A5C2DA /* UserDefaults+BRAdd.swift in Sources */,
BF02B8082E2F616E00172177 /* BRFavoritesViewController.swift in Sources */,
BF3338FD2E1626B000B10F76 /* BRPlayerControlProtocol.swift in Sources */,
BF692B582E0AAA6F00A5C2DA /* UIScreen+BRAdd.swift in Sources */,
BF692B1F2E0A804600A5C2DA /* BRLocalizedManager.swift in Sources */,
@ -948,8 +1090,10 @@
BFC676832E122CC5006659E5 /* BRPlayerViewModel.swift in Sources */,
BF02B7EF2E2E4BFD00172177 /* BRRateModel.swift in Sources */,
BF692B672E0BC6C700A5C2DA /* AppDelegate+BRConfig.swift in Sources */,
BF02B8022E2F39FE00172177 /* BRCategorieShortViewController.swift in Sources */,
BF3338FB2E161CF900B10F76 /* NSNumber+BRAdd.swift in Sources */,
BF692B222E0A820D00A5C2DA /* String+BRAdd.swift in Sources */,
BF02B80F2E2F6EEA00172177 /* BRFavoritesHeaderView.swift in Sources */,
BF692B632E0B9D4800A5C2DA /* BRTabBarItem.swift in Sources */,
BFC6768B2E123690006659E5 /* BRVideoRevolutionManager.swift in Sources */,
BFC6768F2E125D5B006659E5 /* BRSpotlightTopMainCell.swift in Sources */,
@ -957,11 +1101,13 @@
BFC676622E0E2C8E006659E5 /* WMZBannerView.m in Sources */,
BFC676632E0E2C8E006659E5 /* WMZBannerOverLayout.m in Sources */,
BFC676642E0E2C8E006659E5 /* WMZBannerFlowLayout.m in Sources */,
BF02B81E2E2F99D900172177 /* BRWebView.swift in Sources */,
BFC676652E0E2C8E006659E5 /* WMZBannerControl.m in Sources */,
BFC676972E127D3C006659E5 /* BRSpotlightRecommandMainCell.swift in Sources */,
BFC6767F2E121A72006659E5 /* BRSpotlightHotCell.swift in Sources */,
BFC6767D2E0E9809006659E5 /* BRSpotlightHotMainCell.swift in Sources */,
BF02B7EB2E2E388800172177 /* BREpisodeMenuView.swift in Sources */,
BF02B8042E2F5B4B00172177 /* BRCategorieShortCell.swift in Sources */,
BFC676662E0E2C8E006659E5 /* WMZBannerFadeLayout.m in Sources */,
BF02B7E72E2E1F0500172177 /* BRPanModalContentView.swift in Sources */,
BFC676872E122E36006659E5 /* BRVideoDetailModel.swift in Sources */,
@ -975,12 +1121,14 @@
BF02B7E32E2E08BD00172177 /* BRDetailEpButton.swift in Sources */,
BF692B072E0A771C00A5C2DA /* BRModel.swift in Sources */,
BF692B752E0D39D000A5C2DA /* BRListModel.swift in Sources */,
BF02B8172E2F881200172177 /* BRMineItem.swift in Sources */,
BFC676B92E1385FC006659E5 /* BRPopularPicksSmallCell.swift in Sources */,
BF692B512E0AA8C600A5C2DA /* BRPlayerListViewController.swift in Sources */,
BFC676522E0D4EFD006659E5 /* BRHomeViewModel.swift in Sources */,
BFC676A72E12AF04006659E5 /* WaterfallMutiSectionFlowLayout.swift in Sources */,
BF692B2A2E0A84F700A5C2DA /* JXUUID.m in Sources */,
BF692B2B2E0A84F700A5C2DA /* PDKeyChain.m in Sources */,
BF02B7FA2E2F225D00172177 /* BRHomeCategoryModel.swift in Sources */,
BFC6766B2E0E395F006659E5 /* BRHomeHeaderBannerCell.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;

View File

@ -72,8 +72,8 @@ extension BRTabBarController {
private func br_setup() {
let nav1 = createNavigationController(viewController: BRHomeViewController(), title: "首页".localized, image: UIImage(named: "tabbar_icon_01"), selectedImage: UIImage(named: "tabbar_icon_01_selected"))
let nav2 = createNavigationController(viewController: BRExploreViewController(), title: "推荐".localized, image: UIImage(named: "tabbar_icon_02"), selectedImage: UIImage(named: "tabbar_icon_02_selected"))
let nav3 = createNavigationController(viewController: BRViewController(), title: "首页".localized, image: UIImage(named: "tabbar_icon_03"), selectedImage: UIImage(named: "tabbar_icon_03_selected"))
let nav4 = createNavigationController(viewController: BRViewController(), title: "首页".localized, image: UIImage(named: "tabbar_icon_04"), selectedImage: UIImage(named: "tabbar_icon_04_selected"))
let nav3 = createNavigationController(viewController: BRFavoritesViewController(), title: "首页".localized, image: UIImage(named: "tabbar_icon_03"), selectedImage: UIImage(named: "tabbar_icon_03_selected"))
let nav4 = createNavigationController(viewController: BRMineViewController(), title: "首页".localized, image: UIImage(named: "tabbar_icon_04"), selectedImage: UIImage(named: "tabbar_icon_04_selected"))
viewControllers = [nav1, nav2, nav3, nav4]
@ -116,3 +116,11 @@ extension BRTabBarController {
}
}
}
extension BRTabBarController {
func onHomePage() {
self.selectedIndex = 0
}
}

View File

@ -7,6 +7,7 @@
import UIKit
class BRViewController: UIViewController {
private(set) var isViewDidLoad = false
@ -67,7 +68,7 @@ class BRViewController: UIViewController {
extension UIViewController {
func configNavigationBack(_ imageName: String = "nav_back_icon_01") {
func configNavigationBack(_ imageName: String = "nav_back_icon_02") {
let image = UIImage(named: imageName)
let leftBarButtonItem = UIBarButtonItem(image: image, style: .plain ,target: self,action: #selector(handleNavBack))
@ -96,13 +97,15 @@ extension UIViewController {
extension UIViewController {
///
func br_setNavigationNormalStyle(backgroundColor: UIColor = .clear,
isTranslucent: Bool = true,
prefersLargeTitles: Bool = false)
func br_setNavigation(style: BRNavigationBarStyle)
{
self.br_setNavigationBackgroundColor(color: backgroundColor, isTranslucent: isTranslucent)
self.br_setNavigationTitleStyle()
self.navigationController?.navigationBar.prefersLargeTitles = prefersLargeTitles
if style == .light {
self.br_setNavigationBackgroundColor(color: .colorFFFFFF())
self.br_setNavigationTitleStyle(color: .color1C1C1C())
} else {
self.br_setNavigationBackgroundColor(color: .color1C1C1C())
self.br_setNavigationTitleStyle(color: .colorFFFFFF())
}
}
///

View File

@ -7,17 +7,22 @@
import UIKit
//MARK:-------------- --------------
///
let kBROsVersion: String = UIDevice.current.systemVersion
let kBRAPPBundleIdentifier: String = (Bundle.main.infoDictionary!["CFBundleIdentifier"] as? String) ?? "0"
///app
public let kBRAPPVersion: String = (Bundle.main.infoDictionary!["CFBundleShortVersionString"] as? String) ?? "0"
public let kSBAPPBundleVersion: String = (Bundle.main.infoDictionary!["CFBundleVersion"] as? String) ?? "0"
let kBRAPPVersion: String = (Bundle.main.infoDictionary!["CFBundleShortVersionString"] as? String) ?? "0"
let kSBAPPBundleVersion: String = (Bundle.main.infoDictionary!["CFBundleVersion"] as? String) ?? "0"
let kBRAPPBundleName: String = (Bundle.main.infoDictionary!["CFBundleName"] as? String) ?? ""
let kBRAPPName: String = (Bundle.main.infoDictionary!["CFBundleDisplayName"] as? String) ?? ""
public let kBRAPPBundleName: String = (Bundle.main.infoDictionary!["CFBundleName"] as? String) ?? ""
public let kBRAPPName: String = (Bundle.main.infoDictionary!["CFBundleDisplayName"] as? String) ?? ""
//MARK: ------- ----------

View File

@ -74,4 +74,24 @@ extension UIColor {
static func color747474(alpha: CGFloat = 1) -> UIColor {
return UIColor(rgb: 0x747474, alpha: alpha)
}
static func colorF2FEDC(alpha: CGFloat = 1) -> UIColor {
return UIColor(rgb: 0xF2FEDC, alpha: alpha)
}
static func colorFFEFE2(alpha: CGFloat = 1) -> UIColor {
return UIColor(rgb: 0xFFEFE2, alpha: alpha)
}
static func colorDFFDFF(alpha: CGFloat = 1) -> UIColor {
return UIColor(rgb: 0xDFFDFF, alpha: alpha)
}
static func colorFFE9FA(alpha: CGFloat = 1) -> UIColor {
return UIColor(rgb: 0xFFE9FA, alpha: alpha)
}
static func colorB7B7B7(alpha: CGFloat = 1) -> UIColor {
return UIColor(rgb: 0xB7B7B7, alpha: alpha)
}
}

View File

@ -7,6 +7,12 @@
import UIKit
enum BRNavigationBarStyle: Int {
case light = 1
case dark = 2
}
extension UINavigationBar {
static let br_normalTitleFont = UIFont.fontBold(ofSize: 16)

View File

@ -46,4 +46,13 @@ extension UIScreen {
static var customTabBarHeight: CGFloat {
return tabbarSafeBottomMargin + 50
}
///
static var widthRatio: CGFloat {
return UIScreen.width / 375
}
static func getRatioWidth(size: CGFloat) -> CGFloat {
return self.widthRatio * size
}
}

View File

@ -55,4 +55,30 @@ class BRHomeAPI {
}
}
static func requestHomeCategoryList(completer: ((_ list: [BRHomeCategoryModel]?) -> Void)?) {
var param = BRNetworkParameters(path: "/categoryListAppendShortPlay")
param.method = .get
param.parameters = [
"short_play_num" : 4,
]
BRNetwork.request(parameters: param) { (response: BRNetworkResponse<BRListModel<BRHomeCategoryModel>>) in
completer?(response.data?.list)
}
}
static func requestCategoryVideoList(id: String, page: Int, completer: ((_ listModel: BRListModel<BRShortModel>?) -> Void)?) {
var param = BRNetworkParameters(path: "/videoList")
param.method = .get
param.parameters = [
"category_id" : id,
"current_page" : page,
"page_size" : 20
]
BRNetwork.request(parameters: param) { (response: BRNetworkResponse<BRListModel<BRShortModel>>) in
completer?(response.data)
}
}
}

View File

@ -67,6 +67,20 @@ class BRVideoAPI {
}
}
///
static func requestFavoriteList(page: Int, completer: ((_ listModel: BRListModel<BRShortModel>?) -> Void)?) {
var param = BRNetworkParameters(path: "/myCollections")
param.method = .get
param.parameters = [
"current_page" : page,
"page_size" : 20
]
BRNetwork.request(parameters: param) { (response: BRNetworkResponse<BRListModel<BRShortModel>>) in
completer?(response.data)
}
}
///
static func requestExploreVideo(page: Int, revolution: BRShortModel.VideoRevolution? = nil, completer: ((_ listModel: BRListModel<BRShortModel>?) -> Void)?) {
@ -88,6 +102,38 @@ class BRVideoAPI {
completer?(response.data)
}
}
static func requestAddPlayHistory(videoId: String?, shortPlayId: String?) {
guard let shortPlayId = shortPlayId else { return }
var param = BRNetworkParameters(path: "/createHistory")
param.isLoding = false
param.isToast = false
param.parameters = [
"video_id" : videoId ?? "0",
"short_play_id" : shortPlayId
]
BRNetwork.request(parameters: param) { (response: BRNetworkResponse<String>) in
}
}
///
static func requestPlayHistorys(page: Int, pageSize: Int = 20, completer: ((_ listModel: BRListModel<BRShortModel>?) -> Void)?) {
var param = BRNetworkParameters(path: "/myHistorys")
param.method = .get
param.parameters = [
"current_page" : page,
"page_size" : pageSize
]
BRNetwork.request(parameters: param) { (response: BRNetworkResponse<BRListModel<BRShortModel>>) in
completer?(response.data)
}
}
}

View File

@ -0,0 +1,45 @@
//
// BRGradientView.swift
// BeeReel
//
// Created by on 2025/7/22.
//
import UIKit
class BRGradientView: UIView {
override class var layerClass: AnyClass {
return CAGradientLayer.self
}
var br_gradientLayer: CAGradientLayer {
return self.layer as! CAGradientLayer
}
var br_colors: [CGColor]? {
didSet {
br_gradientLayer.colors = br_colors
}
}
var br_startPoint: CGPoint = .zero {
didSet {
br_gradientLayer.startPoint = br_startPoint
}
}
var br_endPoint: CGPoint = .zero {
didSet {
br_gradientLayer.endPoint = br_endPoint
}
}
var br_locations: [NSNumber] = [] {
didSet {
br_gradientLayer.locations = br_locations
}
}
}

View File

@ -34,7 +34,8 @@ class BRImageView: UIImageView {
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
// fatalError("init(coder:) has not been implemented")
super.init(image: nil)
}

View File

@ -19,7 +19,7 @@ class BRTableView: UITableView {
self.contentInsetAdjustmentBehavior = .never
if style == .insetGrouped {
sectionFooterHeight = 12
sectionFooterHeight = 14
sectionHeaderHeight = 0.1
} else if style == .plain {
if #available(iOS 15.0, *) {
@ -32,7 +32,6 @@ class BRTableView: UITableView {
fatalError("init(coder:) has not been implemented")
}
/// insetGrouped https://github.com/QMUI/QMUIDemo_iOS/blob/master/QMUI/QMUIKit/UIKitExtensions/UITableView%2BQMUI.m
override var layoutMargins: UIEdgeInsets {
set {
super.layoutMargins = newValue

View File

@ -0,0 +1,149 @@
//
// BRWebView.swift
// BeeReel
//
// Created by on 2025/7/22.
//
import UIKit
@preconcurrency import WebKit
//MARK:-------------- VPWebViewDelegate --------------
@objc protocol BRWebViewDelegate: NSObjectProtocol {
@objc optional func br_webView(_ webView: BRWebView, shouldStartLoadWith navigationAction: WKNavigationAction) -> Bool
@objc optional func br_webViewDidStartLoad(_ webView: BRWebView)
@objc optional func br_webViewDidFinishLoad(_ webView: BRWebView)
@objc optional func br_webView(_ webView: BRWebView, didFailLoadWithError error: Error)
///
@objc optional func br_webView(webView: BRWebView, didChangeProgress progress: CGFloat)
///
@objc optional func br_webView(webView: BRWebView, didChangeTitle title: String)
///web
@objc optional func br_userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage)
}
class BRWebView: WKWebView {
weak var delegate: BRWebViewDelegate?
private(set) var scriptMessageHandlerArray: [String] = []
deinit {
self.removeObserver(self, forKeyPath: "estimatedProgress")
self.removeObserver(self, forKeyPath: "title")
}
override init(frame: CGRect, configuration: WKWebViewConfiguration) {
super.init(frame: frame, configuration: configuration)
addScriptMessageHandler()
_setupInit()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func _setupInit() {
self.isOpaque = false
self.navigationDelegate = self
self.addObserver(self, forKeyPath: "estimatedProgress", options: .new, context: nil)
self.addObserver(self, forKeyPath: "title", options: .new, context: nil)
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if object as? BRWebView == self {
if keyPath == "estimatedProgress", let progress = change?[NSKeyValueChangeKey.newKey] as? CGFloat {
self.delegate?.br_webView?(webView: self, didChangeProgress: progress)
} else if keyPath == "title", let title = change?[NSKeyValueChangeKey.newKey] as? String {
self.delegate?.br_webView?(webView: self, didChangeTitle: title)
}
}
}
func load(urlStr: String) {
guard let url = URL(string: urlStr) else { return }
let request = URLRequest(url: url, cachePolicy: .returnCacheDataElseLoad, timeoutInterval: 30)
self.load(request)
}
func removeScriptMessageHandler() {
self.scriptMessageHandlerArray.forEach{
configuration.userContentController.removeScriptMessageHandler(forName: $0)
}
}
func addScriptMessageHandler() {
self.scriptMessageHandlerArray.forEach{
configuration.userContentController.add(YYTextWeakProxy(target: self) as! WKScriptMessageHandler, name: $0)
}
}
}
//MARK:-------------- WKNavigationDelegate --------------
extension BRWebView: WKNavigationDelegate {
func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) {
decisionHandler(.allow);
}
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
if let url = navigationAction.request.url,
url.scheme != "http",
url.scheme != "https"
{
UIApplication.shared.open(url)
decisionHandler(.cancel)
return
}
if let result = self.delegate?.br_webView?(self, shouldStartLoadWith: navigationAction) {
if result {
decisionHandler(.allow)
} else {
decisionHandler(.cancel)
}
} else {
decisionHandler(.allow)
}
}
func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
self.delegate?.br_webViewDidStartLoad?(self)
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
self.delegate?.br_webViewDidFinishLoad?(self)
}
func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
self.delegate?.br_webView?(self, didFailLoadWithError: error)
}
func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
self.delegate?.br_webView?(self, didFailLoadWithError: error)
}
}
//MARK:-------------- WKScriptMessageHandler --------------
extension BRWebView: WKScriptMessageHandler {
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
self.delegate?.br_userContentController?(userContentController, didReceive: message)
}
}

View File

@ -0,0 +1,114 @@
//
// BRWebViewController.swift
// BeeReel
//
// Created by on 2025/7/22.
//
import UIKit
import WebKit
class BRWebViewController: BRViewController {
var webUrl: String?
///
var autoTitle = true
var needAutoRefresh = true
private(set) lazy var webView: BRWebView = {
let controller = WKUserContentController()
let config = WKWebViewConfiguration()
config.userContentController = controller
config.preferences.javaScriptEnabled = true
/** JS */
config.preferences.javaScriptCanOpenWindowsAutomatically = true
let webView = BRWebView(frame: self.view.bounds, configuration: config)
webView.delegate = self
return webView
}()
override func viewDidLoad() {
super.viewDidLoad()
_setupUI()
if let url = webUrl {
self.load(webUrl: url)
}
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.setNavigationBarHidden(false, animated: true)
br_setNavigation(style: .light)
}
func load(webUrl: String) {
let str: String = webUrl
guard let url = URL(string: str) else { return }
let request = URLRequest(url: url, timeoutInterval: 30)
self.webView.load(request)
}
func reload() {
self.webView.reload()
}
}
extension BRWebViewController {
private func _setupUI() {
self.view.addSubview(webView)
self.webView.snp.makeConstraints { make in
make.left.equalToSuperview().offset(0)
make.right.equalToSuperview().offset(0)
make.top.equalToSuperview().offset(0)
make.bottom.equalToSuperview().offset(0)
}
}
}
//MARK: -------------- VPWebViewDelegate --------------
extension BRWebViewController: BRWebViewDelegate {
func br_webView(_ webView: BRWebView, shouldStartLoadWith navigationAction: WKNavigationAction) -> Bool {
self.webView.isHidden = false
return true
}
func br_webViewDidStartLoad(_ webView: BRWebView) {
BRHUD.show(containerView: self.view)
}
func br_webView(webView: BRWebView, didChangeTitle title: String) {
if autoTitle {
self.title = title
}
}
func br_webViewDidFinishLoad(_ webView: BRWebView) {
self.webView.isHidden = false
BRHUD.dismiss()
}
func br_webView(_ webView: BRWebView, didFailLoadWithError error: any Error) {
BRHUD.dismiss()
}
func br_userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
// vp_webViewUserContentController(didReceive: message)
}
}

View File

@ -0,0 +1,178 @@
//
// BRFavoritesViewController.swift
// BeeReel
//
// Created by on 2025/7/22.
//
import UIKit
class BRFavoritesViewController: BRViewController {
private lazy var listArr: [BRShortModel] = []
private lazy var page = 1
///
private var playHistoryModel: BRShortModel? {
didSet {
collectionView.reloadData()
}
}
private lazy var titleImageView: UIImageView = {
let imageView = UIImageView(image: UIImage(named: "title_icon_01"))
return imageView
}()
private lazy var collectionViewLayout: UICollectionViewFlowLayout = {
let width = floor((UIScreen.width - 30 - 22) / 3)
let height = 144 / 108 * width
let layout = UICollectionViewFlowLayout()
layout.minimumLineSpacing = 11
layout.minimumInteritemSpacing = 11
layout.sectionInset = .init(top: 0, left: 15, bottom: 0, right: 15)
layout.itemSize = .init(width: width, height: height)
layout.headerReferenceSize = .init(width: UIScreen.width, height: 180)
return layout
}()
private lazy var collectionView: BRCollectionView = {
let collectionView = BRCollectionView(frame: .zero, collectionViewLayout: collectionViewLayout)
collectionView.delegate = self
collectionView.dataSource = self
collectionView.register(BRFavoritesCell.self, forCellWithReuseIdentifier: "cell")
collectionView.register(BRFavoritesHeaderView.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "headerView")
return collectionView
}()
private lazy var addFavoritesButton: UIButton = {
var config = UIButton.Configuration.plain()
config.background.image = UIImage(named: "add_bg_image_01")
config.image = UIImage(named: "add_icon_01")
config.attributedTitle = AttributedString.br_createAttributedString(string: "Expand Your Favorites".localized, color: .colorB7B7B7(), font: .fontMedium(ofSize: 14))
config.imagePadding = 8
let button = UIButton(configuration: config)
button.addTarget(self, action: #selector(handleAddFavoritesButton), for: .touchUpInside)
return button
}()
override func viewDidLoad() {
super.viewDidLoad()
self.edgesForExtendedLayout = [.top, .bottom]
br_setupUI()
requestDataList(page: 1, completer: nil)
requestPlayHistorys()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.setNavigationBarHidden(true, animated: true)
}
}
extension BRFavoritesViewController {
private func br_setupUI() {
view.addSubview(titleImageView)
view.addSubview(collectionView)
view.addSubview(addFavoritesButton)
titleImageView.snp.makeConstraints { make in
make.left.equalToSuperview().offset(15)
make.top.equalToSuperview().offset(UIScreen.statusBarHeight + 20)
}
collectionView.snp.makeConstraints { make in
make.left.right.equalToSuperview()
make.top.equalToSuperview().offset(UIScreen.statusBarHeight + 60)
make.bottom.equalTo(addFavoritesButton.snp.top).offset(-10)
}
addFavoritesButton.snp.makeConstraints { make in
make.left.equalToSuperview().offset(15)
make.centerX.equalToSuperview()
make.bottom.equalToSuperview().offset(-(UIScreen.customTabBarHeight + 10))
make.height.equalTo(48)
}
}
}
extension BRFavoritesViewController {
@objc private func handleAddFavoritesButton() {
BRAppTool.tabBarController?.onHomePage()
}
}
extension BRFavoritesViewController: UICollectionViewDelegate, UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! BRFavoritesCell
cell.model = self.listArr[indexPath.row]
return cell
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.listArr.count
}
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
if kind == UICollectionView.elementKindSectionHeader {
let view = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "headerView", for: indexPath) as! BRFavoritesHeaderView
view.model = self.playHistoryModel
return view
} else {
return UICollectionReusableView()
}
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let model = self.listArr[indexPath.row]
let vc = BRVideoDetailViewController()
vc.shortPlayId = model.short_play_id
self.navigationController?.pushViewController(vc, animated: true)
}
}
extension BRFavoritesViewController {
private func requestDataList(page: Int, completer: (() -> Void)?) {
BRVideoAPI.requestFavoriteList(page: page) { [weak self] listModel in
guard let self = self else { return }
if let list = listModel?.list {
if page == 1 {
self.listArr.removeAll()
}
list.forEach {
$0.is_collect = true
}
self.listArr += list
self.page = page
self.collectionView.reloadData()
}
completer?()
}
}
private func requestPlayHistorys() {
BRVideoAPI.requestPlayHistorys(page: 1, pageSize: 1) { [weak self] listModel in
guard let self = self else { return }
guard let list = listModel?.list else { return }
self.playHistoryModel = list.first
}
}
}

View File

@ -0,0 +1,126 @@
//
// BRFavoritesCell.swift
// BeeReel
//
// Created by on 2025/7/22.
//
import UIKit
class BRFavoritesCell: BRCollectionViewCell {
var model: BRShortModel? {
didSet {
coverView.br_setImage(url: model?.image_url)
let epString = NSMutableAttributedString()
let epStr1 = NSMutableAttributedString(string: "EP.##".localizedReplace(text: model?.current_episode ?? ""))
epStr1.yy_color = .colorE3FC37()
epString.append(epStr1)
let epStr2 = NSMutableAttributedString(string: "/" + "EP.##".localizedReplace(text: "\(model?.episode_total ?? 0)"))
epStr2.yy_color = .colorD3D3D3()
epString.append(epStr2)
epLabel.attributedText = epString
favoriteButton.isSelected = model?.is_collect ?? false
}
}
private lazy var coverView: BRImageView = {
let imageView = BRImageView()
return imageView
}()
private lazy var bottomView: UIView = {
let view = UIView()
view.br_addEffectView(style: .light)
return view
}()
private lazy var epLabel: UILabel = {
let label = UILabel()
label.font = .fontRegular(ofSize: 12)
return label
}()
private lazy var favoriteButton: UIButton = {
let button = UIButton(type: .custom)
button.setImage(UIImage(named: "favorite_icon_04"), for: .normal)
button.setImage(UIImage(named: "favorite_icon_04_selected"), for: .selected)
button.setImage(UIImage(named: "favorite_icon_04_selected"), for: [.selected, .highlighted])
button.addTarget(self, action: #selector(handleFavoriteButton), for: .touchUpInside)
return button
}()
deinit {
NotificationCenter.default.removeObserver(self)
}
override init(frame: CGRect) {
super.init(frame: frame)
NotificationCenter.default.addObserver(self, selector: #selector(updateShortFavoriteStateNotification), name: BRVideoAPI.updateShortFavoriteStateNotification, object: nil)
self.contentView.layer.cornerRadius = 8
self.contentView.layer.masksToBounds = true
br_setupUI()
}
@MainActor required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
@objc private func handleFavoriteButton() {
guard let shortPlayId = self.model?.short_play_id else { return }
let isFavorite = !(self.model?.is_collect ?? false)
BRVideoAPI.requestFavorite(isFavorite: isFavorite, shortPlayId: shortPlayId, videoId: model?.short_play_video_id) {
}
}
@objc private func updateShortFavoriteStateNotification(sender: Notification) {
guard let userInfo = sender.userInfo else { return }
guard let shortPlayId = userInfo["id"] as? String else { return }
guard let state = userInfo["state"] as? Bool else { return }
guard shortPlayId == self.model?.short_play_id else { return }
self.model?.is_collect = state;
favoriteButton.isSelected = self.model?.is_collect ?? false
}
}
extension BRFavoritesCell {
private func br_setupUI() {
contentView.addSubview(coverView)
contentView.addSubview(bottomView)
bottomView.addSubview(epLabel)
contentView.addSubview(favoriteButton)
coverView.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
bottomView.snp.makeConstraints { make in
make.left.right.bottom.equalToSuperview()
make.height.equalTo(28)
}
epLabel.snp.makeConstraints { make in
make.left.equalToSuperview().offset(6)
make.centerY.equalToSuperview()
}
favoriteButton.snp.makeConstraints { make in
make.top.equalToSuperview().offset(5)
make.right.equalToSuperview().offset(-5)
}
}
}

View File

@ -0,0 +1,188 @@
//
// BRFavoritesHeaderView.swift
// BeeReel
//
// Created by on 2025/7/22.
//
import UIKit
class BRFavoritesHeaderView: UICollectionReusableView {
var model: BRShortModel? {
didSet {
coverView.br_setImage(url: model?.image_url)
nameLabel.text = model?.name
categoryLabel.text = model?.category?.first
let epString = NSMutableAttributedString()
let epStr1 = NSMutableAttributedString(string: "EP.##".localizedReplace(text: model?.current_episode ?? ""))
epStr1.yy_color = .colorE3FC37()
epString.append(epStr1)
let epStr2 = NSMutableAttributedString(string: "/" + "EP.##".localizedReplace(text: "\(model?.episode_total ?? 0)"))
epStr2.yy_color = .colorFFFFFF()
epString.append(epStr2)
epLabel.attributedText = epString
favoriteButton.isSelected = self.model?.is_collect ?? false
}
}
private lazy var bgView: UIImageView = {
let view = UIImageView(image: UIImage(named: "history_bg_image"))
view.isUserInteractionEnabled = true
return view
}()
private lazy var coverView: BRImageView = {
let imageView = BRImageView()
imageView.layer.cornerRadius = 8
imageView.layer.masksToBounds = true
imageView.isUserInteractionEnabled = true
return imageView
}()
private lazy var playButton: UIButton = {
let button = UIButton(type: .custom)
button.layer.cornerRadius = 10
button.layer.masksToBounds = true
button.backgroundColor = .colorE3FC37()
button.setImage(UIImage(named: "play_icon_06"), for: .normal)
button.addTarget(self, action: #selector(handlePlayButton), for: .touchUpInside)
return button
}()
private lazy var nameLabel: UILabel = {
let label = UILabel()
label.font = .fontMedium(ofSize: 14)
label.textColor = .colorFFFFFF()
label.numberOfLines = 2
return label
}()
private lazy var categoryLabel: UILabel = {
let label = UILabel()
label.font = .fontRegular(ofSize: 12)
label.textColor = .colorF1FF94()
return label
}()
private lazy var epLabel: UILabel = {
let label = UILabel()
label.font = .fontRegular(ofSize: 12)
return label
}()
private lazy var favoriteButton: UIButton = {
let button = UIButton(type: .custom)
button.setImage(UIImage(named: "favorite_icon_04"), for: .normal)
button.setImage(UIImage(named: "favorite_icon_04_selected"), for: .selected)
button.setImage(UIImage(named: "favorite_icon_04_selected"), for: [.selected, .highlighted])
button.addTarget(self, action: #selector(handleFavoriteButton), for: .touchUpInside)
return button
}()
deinit {
NotificationCenter.default.removeObserver(self)
}
override init(frame: CGRect) {
super.init(frame: frame)
NotificationCenter.default.addObserver(self, selector: #selector(updateShortFavoriteStateNotification), name: BRVideoAPI.updateShortFavoriteStateNotification, object: nil)
br_setupUI()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
@objc private func handlePlayButton() {
guard let shortPlayId = self.model?.short_play_id else { return }
let vc = BRVideoDetailViewController()
vc.shortPlayId = shortPlayId
self.viewController?.navigationController?.pushViewController(vc, animated: true)
}
@objc private func handleFavoriteButton() {
guard let shortPlayId = self.model?.short_play_id else { return }
let isFavorite = !(self.model?.is_collect ?? false)
BRVideoAPI.requestFavorite(isFavorite: isFavorite, shortPlayId: shortPlayId, videoId: model?.short_play_video_id) {
}
}
@objc private func updateShortFavoriteStateNotification(sender: Notification) {
guard let userInfo = sender.userInfo else { return }
guard let shortPlayId = userInfo["id"] as? String else { return }
guard let state = userInfo["state"] as? Bool else { return }
guard shortPlayId == self.model?.short_play_id else { return }
self.model?.is_collect = state
favoriteButton.isSelected = self.model?.is_collect ?? false
}
}
extension BRFavoritesHeaderView {
private func br_setupUI() {
addSubview(bgView)
bgView.addSubview(coverView)
coverView.addSubview(favoriteButton)
bgView.addSubview(playButton)
bgView.addSubview(nameLabel)
bgView.addSubview(categoryLabel)
bgView.addSubview(epLabel)
bgView.snp.makeConstraints { make in
make.left.equalToSuperview().offset(15)
make.right.equalToSuperview().offset(-15)
make.top.equalToSuperview()
make.bottom.equalToSuperview().offset(-16)
}
coverView.snp.makeConstraints { make in
make.left.equalToSuperview().offset(10)
make.centerY.equalToSuperview()
make.width.equalTo(109)
make.height.equalTo(144)
}
favoriteButton.snp.makeConstraints { make in
make.top.equalToSuperview().offset(5)
make.right.equalToSuperview().offset(-5)
}
playButton.snp.makeConstraints { make in
make.right.equalToSuperview().offset(-10)
make.bottom.equalToSuperview().offset(-10)
make.height.equalTo(116)
make.width.equalTo(40)
}
nameLabel.snp.makeConstraints { make in
make.left.equalTo(coverView.snp.right).offset(8)
make.top.equalToSuperview().offset(20)
make.right.lessThanOrEqualToSuperview().offset(-78)
}
categoryLabel.snp.makeConstraints { make in
make.left.equalTo(nameLabel)
make.top.equalToSuperview().offset(75)
}
epLabel.snp.makeConstraints { make in
make.left.equalTo(nameLabel)
make.bottom.equalToSuperview().offset(-20)
}
}
}

View File

@ -0,0 +1,173 @@
//
// BRCategorieShortViewController.swift
// BeeReel
//
// Created by on 2025/7/22.
//
import UIKit
class BRCategorieShortViewController: BRViewController {
var categorieId: String?
var page: Int = 1
var dataList: [BRShortModel] = []
private lazy var backButton: UIButton = {
let button = UIButton(type: .custom)
button.setImage(UIImage(named: "nav_back_icon_02"), for: .normal)
button.addTarget(self, action: #selector(handleNavBack), for: .touchUpInside)
return button
}()
private lazy var lightBgImageView: UIImageView = {
let imageView = UIImageView(image: UIImage(named: "light_icon_02"))
return imageView
}()
private lazy var titleImageView: UIImageView = {
let imageView = UIImageView(image: UIImage(named: "categorie_title_icon"))
return imageView
}()
private lazy var starsIconImageView: UIImageView = {
let imageView = UIImageView(image: UIImage(named: "stars_icon_01"))
return imageView
}()
private lazy var collectionViewLayout: UICollectionViewFlowLayout = {
let width = floor((UIScreen.width - 30 - 22) / 3)
let height = 144 / 108 * width
let layout = UICollectionViewFlowLayout()
layout.minimumLineSpacing = 11
layout.minimumInteritemSpacing = 11
layout.sectionInset = .init(top: 0, left: 15, bottom: 0, right: 15)
layout.itemSize = .init(width: width, height: height)
return layout
}()
private lazy var collectionView: BRCollectionView = {
let collectionView = BRCollectionView(frame: .zero, collectionViewLayout: collectionViewLayout)
collectionView.delegate = self
collectionView.dataSource = self
collectionView.contentInset = .init(top: 0, left: 0, bottom: UIScreen.tabbarSafeBottomMargin, right: 0)
collectionView.br_addRefreshHeader { [weak self] in
self?.handleHeaderRefresh(nil)
}
collectionView.br_addRefreshBackFooter(insetBottom: collectionView.contentInset.bottom) { [weak self] in
self?.handleFooterRefresh(nil)
}
collectionView.register(BRCategorieShortCell.self, forCellWithReuseIdentifier: "cell")
return collectionView
}()
override func viewDidLoad() {
super.viewDidLoad()
br_setupUI()
requestDataList(page: 1, completer: nil)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.setNavigationBarHidden(true, animated: true)
}
override func handleHeaderRefresh(_ completer: (() -> Void)?) {
self.requestDataList(page: 1) { [weak self] in
self?.collectionView.br_endHeaderRefreshing()
}
}
override func handleFooterRefresh(_ completer: (() -> Void)?) {
self.requestDataList(page: self.page + 1) { [weak self] in
self?.collectionView.br_endFooterRefreshing()
}
}
}
extension BRCategorieShortViewController {
private func br_setupUI() {
view.addSubview(lightBgImageView)
view.addSubview(backButton)
view.addSubview(titleImageView)
view.addSubview(starsIconImageView)
view.addSubview(collectionView)
lightBgImageView.snp.makeConstraints { make in
make.top.left.right.equalToSuperview()
}
backButton.snp.makeConstraints { make in
make.left.equalToSuperview().offset(15)
make.top.equalToSuperview().offset(UIScreen.statusBarHeight + 10)
}
titleImageView.snp.makeConstraints { make in
make.centerX.equalToSuperview()
make.centerY.equalTo(backButton)
}
starsIconImageView.snp.makeConstraints { make in
make.bottom.equalTo(backButton).offset(-2)
make.left.equalTo(titleImageView.snp.right).offset(28)
}
collectionView.snp.makeConstraints { make in
make.left.right.bottom.equalToSuperview()
make.top.equalToSuperview().offset(UIScreen.navBarHeight + 20)
}
}
}
extension BRCategorieShortViewController: UICollectionViewDelegate, UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! BRCategorieShortCell
cell.model = dataList[indexPath.row]
return cell
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.dataList.count
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let model = dataList[indexPath.row]
let vc = BRVideoDetailViewController()
vc.shortPlayId = model.short_play_id
self.navigationController?.pushViewController(vc, animated: true)
}
}
extension BRCategorieShortViewController {
private func requestDataList(page: Int, completer: (() -> Void)?) {
guard let id = categorieId else { return }
BRHomeAPI.requestCategoryVideoList(id: id, page: page) { [weak self] listModel in
guard let self = self else { return }
if let list = listModel?.list {
if page == 1 {
self.dataList.removeAll()
}
self.dataList += list
self.page = page
self.collectionView.reloadData()
}
completer?()
}
}
}

View File

@ -0,0 +1,97 @@
//
// BRHomeCategoriesViewController.swift
// BeeReel
//
// Created by on 2025/7/22.
//
import UIKit
class BRHomeCategoriesViewController: BRViewController {
private lazy var list: [BRHomeCategoryModel] = []
private lazy var tableView: BRTableView = {
let tableView = BRTableView(frame: .zero, style: .plain)
tableView.delegate = self
tableView.dataSource = self
tableView.separatorStyle = .none
tableView.contentInset = .init(top: 0, left: 0, bottom: UIScreen.customTabBarHeight, right: 0)
tableView.register(BRHomeCategoriesMainCell.self, forCellReuseIdentifier: "cell")
return tableView
}()
private lazy var cellColorArr: [[CGColor]] = [
[UIColor.colorF2FEDC().cgColor, UIColor.colorF2FEDC(alpha: 0).cgColor],
[UIColor.colorFFEFE2().cgColor, UIColor.colorFFEFE2(alpha: 0).cgColor],
[UIColor.colorDFFDFF().cgColor, UIColor.colorDFFDFF(alpha: 0).cgColor],
[UIColor.colorFFE9FA().cgColor, UIColor.colorFFE9FA(alpha: 0).cgColor],
]
override func viewDidLoad() {
super.viewDidLoad()
br_setupUI()
requestListData(completer: nil)
}
override func handleHeaderRefresh(_ completer: (() -> Void)?) {
requestListData {
completer?()
}
}
}
extension BRHomeCategoriesViewController {
private func br_setupUI() {
view.addSubview(tableView)
tableView.snp.makeConstraints { make in
make.left.right.equalToSuperview()
make.top.equalToSuperview().offset(20)
make.bottom.equalToSuperview()
}
}
}
//MARK: -------------- WMZPageProtocol --------------
extension BRHomeCategoriesViewController: WMZPageProtocol {
func getMyScrollView() -> UIScrollView {
return self.tableView
}
}
//MARK: -------------- UITableViewDelegate UITableViewDataSource --------------
extension BRHomeCategoriesViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! BRHomeCategoriesMainCell
cell.model = list[indexPath.row]
cell.bgColors = cellColorArr[indexPath.row % 4]
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return list.count
}
}
extension BRHomeCategoriesViewController {
private func requestListData(completer: (() -> Void)?) {
BRHomeAPI.requestHomeCategoryList { [weak self] list in
guard let self = self else { return }
if let list = list {
self.list = list
self.tableView.reloadData()
}
completer?()
}
}
}

View File

@ -25,7 +25,7 @@ class BRHomeViewController: BRViewController {
BRHomeTop10ViewController(),
BRPopularPicksViewController(),
BRNewReleasesViewController(),
BRViewController()
BRHomeCategoriesViewController()
]
}()

View File

@ -0,0 +1,18 @@
//
// BRHomeCategoryModel.swift
// BeeReel
//
// Created by on 2025/7/22.
//
import UIKit
import SmartCodable
class BRHomeCategoryModel: BRModel, SmartCodable {
var id: String?
var category_name: String?
var short_play_list: [BRShortModel]?
}

View File

@ -0,0 +1,37 @@
//
// BRCategorieShortCell.swift
// BeeReel
//
// Created by on 2025/7/22.
//
import UIKit
class BRCategorieShortCell: BRCollectionViewCell {
var model: BRShortModel? {
didSet {
coverView.br_setImage(url: model?.image_url)
}
}
private lazy var coverView: BRImageView = {
let imageView = BRImageView()
imageView.layer.cornerRadius = 8
imageView.layer.masksToBounds = true
return imageView
}()
override init(frame: CGRect) {
super.init(frame: frame)
contentView.addSubview(coverView)
coverView.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
}
@MainActor required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}

View File

@ -0,0 +1,39 @@
//
// BRHomeCategoriesCell.swift
// BeeReel
//
// Created by on 2025/7/22.
//
import UIKit
class BRHomeCategoriesCell: BRCollectionViewCell {
var model: BRShortModel? {
didSet {
imageView.br_setImage(url: model?.image_url)
}
}
private lazy var imageView: BRImageView = {
let imageView = BRImageView()
imageView.layer.cornerRadius = 6
imageView.layer.masksToBounds = true
return imageView
}()
override init(frame: CGRect) {
super.init(frame: frame)
contentView.addSubview(imageView)
imageView.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
}
@MainActor required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}

View File

@ -0,0 +1,200 @@
//
// BRHomeCategoriesMainCell.swift
// BeeReel
//
// Created by on 2025/7/22.
//
import UIKit
class BRHomeCategoriesMainCell: BRTableViewCell {
var model: BRHomeCategoryModel? {
didSet {
let firstModel = model?.short_play_list?.first
coverImageView.br_setImage(url: firstModel?.image_url)
moreTitleLabel.text = model?.category_name
self.collectionView.reloadData()
}
}
var bgColors: [CGColor] = [] {
didSet {
bgView.br_colors = bgColors
}
}
private let coverWidht = UIScreen.getRatioWidth(size: 100)
private let coverHeight = 48 + UIScreen.getRatioWidth(size: 84)
private lazy var coverImageView: BRImageView = {
let imageView = BRImageView()
imageView.layer.cornerRadius = 10
imageView.layer.masksToBounds = true
imageView.isUserInteractionEnabled = true
let tap = UITapGestureRecognizer(target: self, action: #selector(handleCoverImageView))
imageView.addGestureRecognizer(tap)
return imageView
}()
private lazy var bgView: BRGradientView = {
let view = BRGradientView()
view.br_startPoint = .init(x: 0, y: 0.5)
view.br_endPoint = .init(x: 1, y: 0.5)
view.br_locations = [0, 1]
view.layer.cornerRadius = 10
view.layer.masksToBounds = true
return view
}()
private lazy var collectionViewLayout: UICollectionViewFlowLayout = {
let totalWidth = UIScreen.width - 30 - coverWidht - 12 - 10 - 22
let width = floor(totalWidth / 3)
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
layout.minimumInteritemSpacing = 11
layout.minimumLineSpacing = 11
layout.itemSize = CGSize(width: width, height: coverHeight - 48)
return layout
}()
private lazy var collectionView: BRCollectionView = {
let collectionView = BRCollectionView(frame: .zero, collectionViewLayout: collectionViewLayout)
collectionView.isScrollEnabled = false
collectionView.delegate = self
collectionView.dataSource = self
collectionView.contentInset = .init(top: 0, left: 12, bottom: 0, right: 0)
collectionView.register(BRHomeCategoriesCell.self, forCellWithReuseIdentifier: "cell")
return collectionView
}()
private lazy var moreButton: UIButton = {
let button = UIButton(type: .custom)
button.addTarget(self, action: #selector(handleMoreButton), for: .touchUpInside)
return button
}()
private lazy var moreTitleLabel: UILabel = {
let label = UILabel()
label.font = .fontMedium(ofSize: 14)
label.textColor = .color1C1C1C()
return label
}()
private lazy var moreIconImageView: UIImageView = {
let imageView = UIImageView(image: UIImage(named: "arrow_right_icon_01"))
return imageView
}()
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
br_setupUI()
}
@MainActor required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
@objc private func handleCoverImageView() {
guard let model = self.model?.short_play_list?.first else { return }
let vc = BRVideoDetailViewController()
vc.shortPlayId = model.short_play_id
self.viewController?.navigationController?.pushViewController(vc, animated: true)
}
@objc private func handleMoreButton() {
let vc = BRCategorieShortViewController()
vc.categorieId = self.model?.id
self.viewController?.navigationController?.pushViewController(vc, animated: true)
}
}
extension BRHomeCategoriesMainCell {
private func br_setupUI() {
contentView.addSubview(coverImageView)
contentView.addSubview(bgView)
bgView.addSubview(collectionView)
bgView.addSubview(moreButton)
moreButton.addSubview(moreTitleLabel)
moreButton.addSubview(moreIconImageView)
coverImageView.snp.makeConstraints { make in
make.left.equalToSuperview().offset(15)
make.top.equalToSuperview()
make.bottom.equalToSuperview().offset(-14)
make.height.equalTo(coverHeight)
make.width.equalTo(coverWidht)
}
bgView.snp.makeConstraints { make in
make.left.equalTo(coverImageView.snp.right)
make.top.bottom.equalTo(coverImageView)
make.right.equalToSuperview().offset(-15)
}
collectionView.snp.makeConstraints { make in
make.left.equalToSuperview()
make.right.equalToSuperview()
make.top.equalToSuperview().offset(38)
make.height.equalTo(self.collectionViewLayout.itemSize.height)
}
moreButton.snp.makeConstraints { make in
make.left.equalToSuperview().offset(14)
make.right.equalToSuperview().offset(-10)
make.top.equalToSuperview().offset(2)
make.bottom.equalTo(collectionView.snp.top)
}
moreTitleLabel.snp.makeConstraints { make in
make.centerY.equalToSuperview()
make.left.equalToSuperview()
}
moreIconImageView.snp.makeConstraints { make in
make.right.equalToSuperview()
make.centerY.equalToSuperview()
}
}
}
extension BRHomeCategoriesMainCell: UICollectionViewDelegate, UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! BRHomeCategoriesCell
cell.model = model?.short_play_list?[indexPath.row + 1]
return cell
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
var count = model?.short_play_list?.count ?? 0
if count == 0 {
return 0
} else {
count = count - 1
if count > 3 {
return 3
}
return count
}
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let model = model?.short_play_list?[indexPath.row + 1]
let vc = BRVideoDetailViewController()
vc.shortPlayId = model?.short_play_id
self.viewController?.navigationController?.pushViewController(vc, animated: true)
}
}

View File

@ -77,6 +77,11 @@ class BRSpotlightHotCell: BRCollectionViewCell {
return button
}()
deinit {
NotificationCenter.default.removeObserver(self)
}
override init(frame: CGRect) {
super.init(frame: frame)
NotificationCenter.default.addObserver(self, selector: #selector(updateShortFavoriteStateNotification), name: BRVideoAPI.updateShortFavoriteStateNotification, object: nil)

View File

@ -0,0 +1,85 @@
//
// BRAboutUsViewController.swift
// BeeReel
//
// Created by on 2025/7/22.
//
import UIKit
class BRAboutUsViewController: BRViewController {
private lazy var listArr: [BRMineItem] = {
let arr = [
BRMineItem(type: .web, title: "User Agreement".localized, url: kSBUserAgreementWebUrl),
BRMineItem(type: .web, title: "Privacy Policy".localized, url: kSBPrivacyPolicyWebUrl),
BRMineItem(type: .web, title: "Child Personal Information Protection Rules".localized, url: kSBInformationProtectionWebUrl),
BRMineItem(type: .web, title: "Youth Internet Civility Convention".localized, url: kSBCivizatioConventionWebUrl),
BRMineItem(type: .web, title: "Third-party information sharing list".localized, url: kSBInformationSharingWebUrl),
BRMineItem(type: .web, title: "Explicit List of Personal Information Collection".localized, url: kSBPersoInforDisclosureWebUrl),
]
return arr
}()
private lazy var tableView: BRTableView = {
let tableView = BRTableView(frame: .zero, style: .plain)
tableView.delegate = self
tableView.dataSource = self
tableView.rowHeight = 50
tableView.separatorStyle = .none
tableView.register(BRAboutUsCell.self, forCellReuseIdentifier: "cell")
return tableView
}()
private lazy var headerView: BRAboutUsHeaderView = {
let view = BRAboutUsHeaderView(frame: .init(x: 0, y: 0, width: UIScreen.width, height: 200))
return view
}()
override func viewDidLoad() {
super.viewDidLoad()
self.title = "About Us".localized
self.tableView.tableHeaderView = self.headerView
view.addSubview(self.tableView)
self.tableView.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.setNavigationBarHidden(false, animated: true)
br_setNavigation(style: .light)
}
}
extension BRAboutUsViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return listArr.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! BRAboutUsCell
cell.item = listArr[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let item = listArr[indexPath.row]
guard let webUrl = item.url else { return }
let vc = BRWebViewController()
vc.webUrl = webUrl
self.navigationController?.pushViewController(vc, animated: true)
}
}

View File

@ -0,0 +1,126 @@
//
// BRMineViewController.swift
// BeeReel
//
// Created by on 2025/7/22.
//
import UIKit
class BRMineViewController: BRViewController {
private lazy var listArr: [[BRMineItem]] = {
let arr = [
[
BRMineItem(type: .userInfo),
],
[
BRMineItem(type: .web, icon: UIImage(named: "mine_item_icon_01"), title: "Privacy Policy".localized, url: kSBPrivacyPolicyWebUrl),
BRMineItem(type: .helpCenter, icon: UIImage(named: "mine_item_icon_02"), title: "Help Center".localized, url: ""),
BRMineItem(type: .web, icon: UIImage(named: "mine_item_icon_03"), title: "User Agreement".localized, url: kSBUserAgreementWebUrl),
BRMineItem(type: .aboutUs, icon: UIImage(named: "mine_item_icon_04"), title: "About Us".localized, url: ""),
]
]
return arr
}()
private lazy var lightImageView: UIImageView = {
let imageView = UIImageView(image: UIImage(named: "light_icon_03"))
return imageView
}()
private lazy var tableView: BRTableView = {
let tableView = BRTableView(frame: .zero, style: .insetGrouped)
tableView.delegate = self
tableView.dataSource = self
tableView.contentInset = .init(top: 0, left: 0, bottom: UIScreen.tabbarSafeBottomMargin + 10, right: 0)
tableView.register(BRMineCell.self, forCellReuseIdentifier: "cell")
tableView.register(BRMineUserInfoCell.self, forCellReuseIdentifier: "userInfo")
return tableView
}()
override func viewDidLoad() {
super.viewDidLoad()
self.edgesForExtendedLayout = [.top, .bottom]
br_setupUI()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.setNavigationBarHidden(true, animated: true)
}
}
extension BRMineViewController {
private func br_setupUI() {
view.addSubview(lightImageView)
view.addSubview(tableView)
lightImageView.snp.makeConstraints { make in
make.left.top.equalToSuperview()
}
tableView.snp.makeConstraints { make in
make.left.right.equalToSuperview()
make.bottom.equalToSuperview()
make.top.equalToSuperview().offset(UIScreen.statusBarHeight)
}
}
}
//MARK: -------------- UITableViewDelegate UITableViewDataSource --------------
extension BRMineViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let item = listArr[indexPath.section][indexPath.row]
if item.type == .userInfo {
let cell = tableView.dequeueReusableCell(withIdentifier: "userInfo", for: indexPath) as! BRMineUserInfoCell
cell.userInfo = BRLoginManager.manager.userInfo
return cell
}
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! BRMineCell
cell.item = item
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return listArr[section].count
}
func numberOfSections(in tableView: UITableView) -> Int {
return listArr.count
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 0.1
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let item = listArr[indexPath.section][indexPath.row]
switch item.type {
case .web:
let vc = BRWebViewController()
vc.webUrl = item.url
self.navigationController?.pushViewController(vc, animated: true)
case .aboutUs:
let vc = BRAboutUsViewController()
self.navigationController?.pushViewController(vc, animated: true)
default:
break
}
}
}

View File

@ -0,0 +1,37 @@
//
// BRMineItem.swift
// BeeReel
//
// Created by on 2025/7/22.
//
import UIKit
class BRMineItem: BRModel {
enum ItemType {
case userInfo
case web
case helpCenter
case aboutUs
}
var type: ItemType?
var icon: UIImage?
var title: String?
var url: String?
init(type: ItemType? = nil, icon: UIImage? = nil, title: String? = nil, url: String? = nil) {
self.type = type
self.icon = icon
self.title = title
self.url = url
}
required init() {
fatalError("init() has not been implemented")
}
}

View File

@ -0,0 +1,47 @@
//
// BRAboutUsCell.swift
// BeeReel
//
// Created by on 2025/7/22.
//
import UIKit
class BRAboutUsCell: BRTableViewCell {
var item: BRMineItem? {
didSet {
titleLabel.text = item?.title
}
}
private lazy var titleLabel: UILabel = {
let label = UILabel()
label.font = .fontRegular(ofSize: 14)
label.textColor = .color1C1C1C()
return label
}()
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
contentView.addSubview(titleLabel)
contentView.addSubview(br_indicatorImageView)
titleLabel.snp.makeConstraints { make in
make.left.equalToSuperview().offset(15)
make.centerY.equalToSuperview()
make.right.lessThanOrEqualToSuperview().offset(-70)
}
br_indicatorImageView.snp.makeConstraints { make in
make.centerY.equalToSuperview()
make.right.equalToSuperview().offset(-15)
}
}
@MainActor required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}

View File

@ -0,0 +1,20 @@
//
// BRAboutUsHeaderView.swift
// BeeReel
//
// Created by on 2025/7/22.
//
import UIKit
class BRAboutUsHeaderView: UIView {
/*
// Only override draw() if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
override func draw(_ rect: CGRect) {
// Drawing code
}
*/
}

View File

@ -0,0 +1,56 @@
//
// BRMineCell.swift
// BeeReel
//
// Created by on 2025/7/22.
//
import UIKit
class BRMineCell: BRTableViewCell {
var item: BRMineItem? {
didSet {
imageView?.image = item?.icon
titleLabel.text = item?.title
}
}
private lazy var titleLabel: UILabel = {
let label = UILabel()
label.font = .fontRegular(ofSize: 14)
label.textColor = .color1C1C1C()
return label
}()
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
contentView.backgroundColor = .colorFFFFFF()
contentView.addSubview(titleLabel)
contentView.addSubview(br_indicatorImageView)
imageView?.snp.makeConstraints { make in
make.top.equalToSuperview().offset(10)
make.centerY.equalToSuperview()
make.left.equalToSuperview().offset(10)
make.width.height.equalTo(34)
}
titleLabel.snp.makeConstraints { make in
make.centerY.equalToSuperview()
make.left.equalToSuperview().offset(54)
}
br_indicatorImageView.snp.makeConstraints { make in
make.centerY.equalToSuperview()
make.right.equalToSuperview().offset(-10)
}
}
@MainActor required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}

View File

@ -0,0 +1,106 @@
//
// BRMineUserInfoCell.swift
// BeeReel
//
// Created by on 2025/7/22.
//
import UIKit
class BRMineUserInfoCell: BRTableViewCell {
var userInfo: BRUserInfo? {
didSet {
avatarImageView.br_setImage(url: userInfo?.avator, placeholder: UIImage(named: "默认头像"))
nickLabel.text = userInfo?.family_name?.isEmpty != false ? "Visitor".localized : userInfo?.family_name
idLabel.text = "ID: \(userInfo?.customer_id ?? "")"
}
}
private lazy var avatarBgView: UIView = {
let view = UIView()
view.layer.cornerRadius = 34
view.layer.borderColor = UIColor.color1C1C1C().cgColor
view.layer.borderWidth = 2
return view
}()
private lazy var avatarIconImageView: UIImageView = {
let imageView = UIImageView(image: UIImage(named: "Polygon 6"))
return imageView
}()
private lazy var avatarImageView: BRImageView = {
let imageView = BRImageView()
imageView.layer.cornerRadius = 28
imageView.layer.masksToBounds = true
return imageView
}()
private lazy var nickLabel: UILabel = {
let label = UILabel()
label.font = .fontMedium(ofSize: 18)
label.textColor = .color1C1C1C()
return label
}()
private lazy var idLabel: UILabel = {
let label = UILabel()
label.font = .fontRegular(ofSize: 12)
label.textColor = .color777777()
return label
}()
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
br_setupUI()
}
@MainActor required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
extension BRMineUserInfoCell {
private func br_setupUI() {
contentView.addSubview(avatarBgView)
contentView.addSubview(avatarIconImageView)
avatarBgView.addSubview(avatarImageView)
contentView.addSubview(nickLabel)
contentView.addSubview(idLabel)
avatarBgView.snp.makeConstraints { make in
make.left.equalToSuperview()
make.top.equalToSuperview().offset(39)
make.width.height.equalTo(68)
make.bottom.equalToSuperview().offset(-6)
}
avatarIconImageView.snp.makeConstraints { make in
make.centerX.equalTo(avatarBgView)
make.centerY.equalTo(avatarBgView.snp.top).offset(0)
}
avatarImageView.snp.makeConstraints { make in
make.center.equalToSuperview()
make.width.height.equalTo(56)
}
nickLabel.snp.makeConstraints { make in
make.left.equalTo(avatarBgView.snp.right).offset(10)
make.top.equalTo(avatarBgView).offset(13)
make.right.lessThanOrEqualToSuperview().offset(-100)
}
idLabel.snp.makeConstraints { make in
make.left.equalTo(nickLabel)
make.bottom.equalTo(avatarBgView).offset(-13)
}
}
}

View File

@ -24,6 +24,9 @@ import SJMediaCacheServer
///
@objc optional func br_playerListViewController(_ viewController: BRPlayerListViewController, didChangeIndexPathForVisible indexPath: IndexPath)
///
@objc optional func br_shouldAutoScrollNextEpisode(_ viewController: BRPlayerListViewController) -> Bool
}
@objc protocol BRPlayerListViewControllerDataSource {
@ -295,7 +298,15 @@ extension BRPlayerListViewController: UICollectionViewDelegate, UICollectionView
extension BRPlayerListViewController: BRPlayerViewModelDelegate {
func br_currentVideoPlayFinish(viewModel: BRPlayerViewModel) {
scrollToNextEpisode()
var isScroll = true
if let result = self.delegate?.br_shouldAutoScrollNextEpisode?(self) {
isScroll = result
}
if isScroll {
scrollToNextEpisode()
} else {
viewModel.currentPlayer?.replay()
}
}
func br_switchPlayAndPause(viewModel: BRPlayerViewModel) {

View File

@ -30,6 +30,9 @@ class BRVideoDetailViewController: BRPlayerListViewController {
button.addTarget(self, action: #selector(handleNavBack), for: .touchUpInside)
return button
}()
///
private weak var popUpView: UIView?
override func viewDidLoad() {
super.viewDidLoad()
@ -60,6 +63,11 @@ class BRVideoDetailViewController: BRPlayerListViewController {
guard index < (model.episodeList?.count ?? 0) else { return nil }
return model.episodeList?[index].video_url
}
override func play() {
super.play()
BRVideoAPI.requestAddPlayHistory(videoId: self.viewModel.currentPlayer?.videoInfo?.short_play_video_id, shortPlayId: self.viewModel.currentPlayer?.videoInfo?.short_play_id)
}
}
@ -92,6 +100,8 @@ extension BRVideoDetailViewController {
self?.scrollToItem(indexPath: IndexPath(row: index, section: indexPath.section), animated: false)
}
view.present(in: nil)
self.popUpView = view
}
override func br_clickRateButton(viewModel: BRPlayerViewModel) {
@ -102,6 +112,8 @@ extension BRVideoDetailViewController {
self.viewModel.rateModel = model
}
view.show()
self.popUpView = view
}
}
@ -126,6 +138,14 @@ extension BRVideoDetailViewController: BRPlayerListViewControllerDataSource, BRP
func br_numberOfSections(in viewController: BRPlayerListViewController) -> Int {
return self.detailArr.count
}
func br_shouldAutoScrollNextEpisode(_ viewController: BRPlayerListViewController) -> Bool {
if self.popUpView == nil {
return true
} else {
return false
}
}
}
extension BRVideoDetailViewController {

View File

@ -18,10 +18,9 @@ import UIKit
///
@objc optional var hasLastEpisodeUnlocked: Bool { get set }
///
var duration: Int { get }
///
var currentPosition: Int { get }
var durationTime: TimeInterval { get }
var currentTime: TimeInterval { get }
var rate: Float { get set }
@ -41,6 +40,6 @@ import UIKit
func replay()
///
func seekToTime(toTime: Int)
func seekTo(progress: Float)
}

View File

@ -61,6 +61,9 @@ class BRDetailControlView: BRPlayerControlView {
private lazy var progressView: BRVideoProgressView = {
let view = BRVideoProgressView()
view.insets = .init(top: 18, left: 15, bottom: 0, right: 18)
view.panFinish = { [weak self] progress in
self?.viewModel?.seekTo(progress: Float(progress))
}
return view
}()

View File

@ -36,9 +36,12 @@ class BRPlayerListCell: BRCollectionViewCell, BRPlayerProtocol {
}
}
var duration: Int = 0
var currentPosition: Int = 0
var durationTime: TimeInterval {
return player.duration
}
var currentTime: TimeInterval {
return player.currentTime
}
var rate: Float = 1 {
didSet {
@ -63,11 +66,13 @@ class BRPlayerListCell: BRCollectionViewCell, BRPlayerProtocol {
}
func replay() {
player.replay()
}
func seekToTime(toTime: Int) {
func seekTo(progress: Float) {
let duration = self.durationTime
let time = duration * TimeInterval(progress)
self.player.seek(toTime: time)
}

View File

@ -70,4 +70,10 @@ extension BRPlayerViewModel {
self.delegate?.br_clickRateButton(viewModel: self)
}
///
func seekTo(progress: Float) {
self.currentPlayer?.seekTo(progress: progress)
}
}

View File

@ -19,7 +19,9 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
window = UIWindow(windowScene: windowScene)
window?.rootViewController = BRTabBarController()
BRAppTool.tabBarController = BRTabBarController()
window?.rootViewController = BRAppTool.tabBarController
window?.makeKeyAndVisible()
}

View File

@ -11,6 +11,7 @@ class BRAppTool {
static var appDelegate: AppDelegate?
static var sceneDelegate: SceneDelegate?
static var tabBarController: BRTabBarController?
static var windowScene: UIWindowScene?

View File

@ -123,8 +123,12 @@ class BRPlayer: NSObject {
self.player.stop()
}
func seek(toTime: Int) {
self.player.seek(toTime: TimeInterval(toTime))
func replay() {
player.replay()
}
func seek(toTime: TimeInterval) {
self.player.seek(toTime: toTime)
}
}

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 671 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 916 B

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 240 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 389 B

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 351 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 446 B

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 491 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 678 B

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

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

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 265 KiB

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 289 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 610 KiB

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

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

View File

@ -18,5 +18,8 @@
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"template-rendering-intent" : "original"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 884 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -0,0 +1,25 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "Component 46@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "Component 46@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"template-rendering-intent" : "original"
}
}

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 583 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 794 B

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1019 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View File

@ -0,0 +1,44 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "框@2x.png",
"idiom" : "universal",
"resizing" : {
"cap-insets" : {
"left" : 339,
"right" : 12
},
"center" : {
"mode" : "tile",
"width" : 24
},
"mode" : "3-part-horizontal"
},
"scale" : "2x"
},
{
"filename" : "框@3x.png",
"idiom" : "universal",
"resizing" : {
"cap-insets" : {
"left" : 473,
"right" : 18
},
"center" : {
"mode" : "tile",
"width" : 36
},
"mode" : "3-part-horizontal"
},
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -0,0 +1,44 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "Rectangle 82@2x.png",
"idiom" : "universal",
"resizing" : {
"cap-insets" : {
"left" : 38,
"right" : 255
},
"center" : {
"mode" : "tile",
"width" : 1
},
"mode" : "3-part-horizontal"
},
"scale" : "2x"
},
{
"filename" : "Rectangle 82@3x.png",
"idiom" : "universal",
"resizing" : {
"cap-insets" : {
"left" : 53,
"right" : 371
},
"center" : {
"mode" : "tile",
"width" : 1
},
"mode" : "3-part-horizontal"
},
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

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