1期开发
@ -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;
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
||||
///设置导航背景色
|
||||
|
@ -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: ------- 打印信息 ----------
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
45
BeeReel/Base/View/BRGradientView.swift
Normal 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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -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)
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
149
BeeReel/Base/WebView/BRWebView.swift
Normal 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)
|
||||
}
|
||||
|
||||
}
|
114
BeeReel/Base/WebView/BRWebViewController.swift
Normal 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)
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
126
BeeReel/Class/Favorites/View/BRFavoritesCell.swift
Normal 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)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
188
BeeReel/Class/Favorites/View/BRFavoritesHeaderView.swift
Normal 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)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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?()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -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?()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -25,7 +25,7 @@ class BRHomeViewController: BRViewController {
|
||||
BRHomeTop10ViewController(),
|
||||
BRPopularPicksViewController(),
|
||||
BRNewReleasesViewController(),
|
||||
BRViewController()
|
||||
BRHomeCategoriesViewController()
|
||||
]
|
||||
}()
|
||||
|
||||
|
18
BeeReel/Class/Home/Model/BRHomeCategoryModel.swift
Normal 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]?
|
||||
|
||||
|
||||
}
|
@ -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")
|
||||
}
|
||||
}
|
@ -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")
|
||||
}
|
||||
|
||||
}
|
@ -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)
|
||||
|
||||
}
|
||||
}
|
@ -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)
|
||||
|
85
BeeReel/Class/Mine/Controller/BRAboutUsViewController.swift
Normal 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)
|
||||
}
|
||||
|
||||
|
||||
}
|
126
BeeReel/Class/Mine/Controller/BRMineViewController.swift
Normal 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
|
||||
}
|
||||
}
|
||||
|
||||
}
|
37
BeeReel/Class/Mine/Model/BRMineItem.swift
Normal 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")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
47
BeeReel/Class/Mine/View/BRAboutUsCell.swift
Normal 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")
|
||||
}
|
||||
|
||||
}
|
20
BeeReel/Class/Mine/View/BRAboutUsHeaderView.swift
Normal 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
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
56
BeeReel/Class/Mine/View/BRMineCell.swift
Normal 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")
|
||||
}
|
||||
}
|
106
BeeReel/Class/Mine/View/BRMineUserInfoCell.swift
Normal 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)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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) {
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
}()
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
||||
|
@ -70,4 +70,10 @@ extension BRPlayerViewModel {
|
||||
self.delegate?.br_clickRateButton(viewModel: self)
|
||||
}
|
||||
|
||||
///设置进度
|
||||
func seekTo(progress: Float) {
|
||||
self.currentPlayer?.seekTo(progress: progress)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -19,7 +19,9 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||
|
||||
window = UIWindow(windowScene: windowScene)
|
||||
|
||||
window?.rootViewController = BRTabBarController()
|
||||
BRAppTool.tabBarController = BRTabBarController()
|
||||
window?.rootViewController = BRAppTool.tabBarController
|
||||
|
||||
window?.makeKeyAndVisible()
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,7 @@ class BRAppTool {
|
||||
|
||||
static var appDelegate: AppDelegate?
|
||||
static var sceneDelegate: SceneDelegate?
|
||||
static var tabBarController: BRTabBarController?
|
||||
|
||||
static var windowScene: UIWindowScene?
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
22
BeeReel/Sources/Assets.xcassets/icon/Polygon 6.imageset/Contents.json
vendored
Normal 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
|
||||
}
|
||||
}
|
BIN
BeeReel/Sources/Assets.xcassets/icon/Polygon 6.imageset/Polygon 6@2x.png
vendored
Normal file
After Width: | Height: | Size: 671 B |
BIN
BeeReel/Sources/Assets.xcassets/icon/Polygon 6.imageset/Polygon 6@3x.png
vendored
Normal file
After Width: | Height: | Size: 916 B |
22
BeeReel/Sources/Assets.xcassets/icon/add_icon_01.imageset/Contents.json
vendored
Normal 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
|
||||
}
|
||||
}
|
BIN
BeeReel/Sources/Assets.xcassets/icon/add_icon_01.imageset/Frame 1503@2x.png
vendored
Normal file
After Width: | Height: | Size: 240 B |
BIN
BeeReel/Sources/Assets.xcassets/icon/add_icon_01.imageset/Frame 1503@3x.png
vendored
Normal file
After Width: | Height: | Size: 389 B |
22
BeeReel/Sources/Assets.xcassets/icon/arrow_right_icon_01.imageset/Contents.json
vendored
Normal 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
|
||||
}
|
||||
}
|
BIN
BeeReel/Sources/Assets.xcassets/icon/arrow_right_icon_01.imageset/Frame 1492@2x.png
vendored
Normal file
After Width: | Height: | Size: 351 B |
BIN
BeeReel/Sources/Assets.xcassets/icon/arrow_right_icon_01.imageset/Frame 1492@3x.png
vendored
Normal file
After Width: | Height: | Size: 446 B |
22
BeeReel/Sources/Assets.xcassets/icon/arrow_right_icon_02.imageset/Contents.json
vendored
Normal 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
|
||||
}
|
||||
}
|
BIN
BeeReel/Sources/Assets.xcassets/icon/arrow_right_icon_02.imageset/Frame@2x.png
vendored
Normal file
After Width: | Height: | Size: 491 B |
BIN
BeeReel/Sources/Assets.xcassets/icon/arrow_right_icon_02.imageset/Frame@3x.png
vendored
Normal file
After Width: | Height: | Size: 678 B |
22
BeeReel/Sources/Assets.xcassets/icon/categorie_title_icon.imageset/Contents.json
vendored
Normal 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
|
||||
}
|
||||
}
|
BIN
BeeReel/Sources/Assets.xcassets/icon/categorie_title_icon.imageset/Period Drama@2x.png
vendored
Normal file
After Width: | Height: | Size: 3.6 KiB |
BIN
BeeReel/Sources/Assets.xcassets/icon/categorie_title_icon.imageset/Period Drama@3x.png
vendored
Normal file
After Width: | Height: | Size: 5.5 KiB |
BIN
BeeReel/Sources/Assets.xcassets/icon/favorite_icon_04.imageset/Component 2@2x.png
vendored
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
BeeReel/Sources/Assets.xcassets/icon/favorite_icon_04.imageset/Component 2@3x.png
vendored
Normal file
After Width: | Height: | Size: 2.2 KiB |
22
BeeReel/Sources/Assets.xcassets/icon/favorite_icon_04.imageset/Contents.json
vendored
Normal 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
|
||||
}
|
||||
}
|
BIN
BeeReel/Sources/Assets.xcassets/icon/favorite_icon_04_selected.imageset/Component 2@2x.png
vendored
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
BeeReel/Sources/Assets.xcassets/icon/favorite_icon_04_selected.imageset/Component 2@3x.png
vendored
Normal file
After Width: | Height: | Size: 2.2 KiB |
22
BeeReel/Sources/Assets.xcassets/icon/favorite_icon_04_selected.imageset/Contents.json
vendored
Normal 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
|
||||
}
|
||||
}
|
22
BeeReel/Sources/Assets.xcassets/icon/light_icon_02.imageset/Contents.json
vendored
Normal 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
|
||||
}
|
||||
}
|
BIN
BeeReel/Sources/Assets.xcassets/icon/light_icon_02.imageset/Ellipse 114@2x.png
vendored
Normal file
After Width: | Height: | Size: 158 KiB |
BIN
BeeReel/Sources/Assets.xcassets/icon/light_icon_02.imageset/Ellipse 114@3x.png
vendored
Normal file
After Width: | Height: | Size: 265 KiB |
22
BeeReel/Sources/Assets.xcassets/icon/light_icon_03.imageset/Contents.json
vendored
Normal 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
|
||||
}
|
||||
}
|
BIN
BeeReel/Sources/Assets.xcassets/icon/light_icon_03.imageset/顶部bg@2x.png
vendored
Normal file
After Width: | Height: | Size: 289 KiB |
BIN
BeeReel/Sources/Assets.xcassets/icon/light_icon_03.imageset/顶部bg@3x.png
vendored
Normal file
After Width: | Height: | Size: 610 KiB |
22
BeeReel/Sources/Assets.xcassets/icon/mine_item_icon_01.imageset/Contents.json
vendored
Normal 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
|
||||
}
|
||||
}
|
BIN
BeeReel/Sources/Assets.xcassets/icon/mine_item_icon_01.imageset/Privacy Policy@2x.png
vendored
Normal file
After Width: | Height: | Size: 2.0 KiB |
BIN
BeeReel/Sources/Assets.xcassets/icon/mine_item_icon_01.imageset/Privacy Policy@3x.png
vendored
Normal file
After Width: | Height: | Size: 2.9 KiB |
22
BeeReel/Sources/Assets.xcassets/icon/mine_item_icon_02.imageset/Contents.json
vendored
Normal 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
|
||||
}
|
||||
}
|
BIN
BeeReel/Sources/Assets.xcassets/icon/mine_item_icon_02.imageset/Help Center@2x.png
vendored
Normal file
After Width: | Height: | Size: 2.0 KiB |
BIN
BeeReel/Sources/Assets.xcassets/icon/mine_item_icon_02.imageset/Help Center@3x.png
vendored
Normal file
After Width: | Height: | Size: 2.8 KiB |
22
BeeReel/Sources/Assets.xcassets/icon/mine_item_icon_03.imageset/Contents.json
vendored
Normal 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
|
||||
}
|
||||
}
|
BIN
BeeReel/Sources/Assets.xcassets/icon/mine_item_icon_03.imageset/User Agreement@2x.png
vendored
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
BeeReel/Sources/Assets.xcassets/icon/mine_item_icon_03.imageset/User Agreement@3x.png
vendored
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
BeeReel/Sources/Assets.xcassets/icon/mine_item_icon_04.imageset/About Us@2x.png
vendored
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
BeeReel/Sources/Assets.xcassets/icon/mine_item_icon_04.imageset/About Us@3x.png
vendored
Normal file
After Width: | Height: | Size: 3.2 KiB |
22
BeeReel/Sources/Assets.xcassets/icon/mine_item_icon_04.imageset/Contents.json
vendored
Normal 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
|
||||
}
|
||||
}
|
@ -18,5 +18,8 @@
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"template-rendering-intent" : "original"
|
||||
}
|
||||
}
|
||||
|
BIN
BeeReel/Sources/Assets.xcassets/icon/nav_back_icon_02.imageset/Component 46@2x.png
vendored
Normal file
After Width: | Height: | Size: 884 B |
BIN
BeeReel/Sources/Assets.xcassets/icon/nav_back_icon_02.imageset/Component 46@3x.png
vendored
Normal file
After Width: | Height: | Size: 1.3 KiB |
25
BeeReel/Sources/Assets.xcassets/icon/nav_back_icon_02.imageset/Contents.json
vendored
Normal 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"
|
||||
}
|
||||
}
|
22
BeeReel/Sources/Assets.xcassets/icon/play_icon_06.imageset/Contents.json
vendored
Normal 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
|
||||
}
|
||||
}
|
BIN
BeeReel/Sources/Assets.xcassets/icon/play_icon_06.imageset/Polygon 1@2x.png
vendored
Normal file
After Width: | Height: | Size: 583 B |
BIN
BeeReel/Sources/Assets.xcassets/icon/play_icon_06.imageset/Polygon 1@3x.png
vendored
Normal file
After Width: | Height: | Size: 794 B |
22
BeeReel/Sources/Assets.xcassets/icon/stars_icon_01.imageset/Contents.json
vendored
Normal 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
|
||||
}
|
||||
}
|
BIN
BeeReel/Sources/Assets.xcassets/icon/stars_icon_01.imageset/星星@2x.png
vendored
Normal file
After Width: | Height: | Size: 1019 B |
BIN
BeeReel/Sources/Assets.xcassets/icon/stars_icon_01.imageset/星星@3x.png
vendored
Normal file
After Width: | Height: | Size: 1.3 KiB |
22
BeeReel/Sources/Assets.xcassets/icon/title_icon_01.imageset/Contents.json
vendored
Normal 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
|
||||
}
|
||||
}
|
BIN
BeeReel/Sources/Assets.xcassets/icon/title_icon_01.imageset/Favorites@2x.png
vendored
Normal file
After Width: | Height: | Size: 5.0 KiB |
BIN
BeeReel/Sources/Assets.xcassets/icon/title_icon_01.imageset/Favorites@3x.png
vendored
Normal file
After Width: | Height: | Size: 7.6 KiB |
22
BeeReel/Sources/Assets.xcassets/icon/默认头像.imageset/Contents.json
vendored
Normal 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
|
||||
}
|
||||
}
|
BIN
BeeReel/Sources/Assets.xcassets/icon/默认头像.imageset/默认头像@2x.png
vendored
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
BeeReel/Sources/Assets.xcassets/icon/默认头像.imageset/默认头像@3x.png
vendored
Normal file
After Width: | Height: | Size: 21 KiB |
44
BeeReel/Sources/Assets.xcassets/image/add_bg_image_01.imageset/Contents.json
vendored
Normal 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
|
||||
}
|
||||
}
|
BIN
BeeReel/Sources/Assets.xcassets/image/add_bg_image_01.imageset/框@2x.png
vendored
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
BeeReel/Sources/Assets.xcassets/image/add_bg_image_01.imageset/框@3x.png
vendored
Normal file
After Width: | Height: | Size: 2.4 KiB |
44
BeeReel/Sources/Assets.xcassets/image/history_bg_image.imageset/Contents.json
vendored
Normal 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
|
||||
}
|
||||
}
|