Search and setup interface preliminary build

dev
wenlei 1 year ago
parent bbbab43c2e
commit c74e0d9041

@ -24,6 +24,27 @@
774A18102B070A6900F56DF1 /* SongViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 774A180F2B070A6900F56DF1 /* SongViewCell.swift */; };
774A18122B07327C00F56DF1 /* CommentCountButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 774A18112B07327C00F56DF1 /* CommentCountButton.swift */; };
774A18142B07329600F56DF1 /* MultiUserAvatarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 774A18132B07329600F56DF1 /* MultiUserAvatarView.swift */; };
7751D3502B42ABBF00F1F2BD /* SettingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7751D34F2B42ABBF00F1F2BD /* SettingViewController.swift */; };
7751D3522B42AC2B00F1F2BD /* SettingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7751D3512B42AC2B00F1F2BD /* SettingView.swift */; };
7751D3542B42AE0E00F1F2BD /* SettingViewMdel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7751D3532B42AE0E00F1F2BD /* SettingViewMdel.swift */; };
7751D3562B42AE4600F1F2BD /* Setting.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7751D3552B42AE4600F1F2BD /* Setting.swift */; };
7751D3582B42B5A200F1F2BD /* EditInfoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7751D3572B42B5A200F1F2BD /* EditInfoViewController.swift */; };
7751D35A2B42B5BD00F1F2BD /* EditInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7751D3592B42B5BD00F1F2BD /* EditInfoView.swift */; };
7751D35C2B42B5E900F1F2BD /* EditInfoViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7751D35B2B42B5E900F1F2BD /* EditInfoViewModel.swift */; };
7751D35E2B42B61100F1F2BD /* PersonInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7751D35D2B42B61100F1F2BD /* PersonInfo.swift */; };
7751D3602B42BA3D00F1F2BD /* EditNameController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7751D35F2B42BA3D00F1F2BD /* EditNameController.swift */; };
7751D3622B42BC0C00F1F2BD /* AccountViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7751D3612B42BC0C00F1F2BD /* AccountViewController.swift */; };
7751D3642B42BC2E00F1F2BD /* AccountViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7751D3632B42BC2E00F1F2BD /* AccountViewModel.swift */; };
7751D3662B42BE7F00F1F2BD /* FeedbackViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7751D3652B42BE7F00F1F2BD /* FeedbackViewController.swift */; };
7751D3682B42E96200F1F2BD /* ThanksViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7751D3672B42E96200F1F2BD /* ThanksViewController.swift */; };
7751D36A2B42ED6C00F1F2BD /* TimingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7751D3692B42ED6C00F1F2BD /* TimingViewController.swift */; };
7751D36C2B439F0000F1F2BD /* AboutViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7751D36B2B439F0000F1F2BD /* AboutViewController.swift */; };
7751D36E2B43A03E00F1F2BD /* PrivacyViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7751D36D2B43A03E00F1F2BD /* PrivacyViewController.swift */; };
7751D3702B43A4FC00F1F2BD /* CacheViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7751D36F2B43A4FC00F1F2BD /* CacheViewController.swift */; };
7751D3722B43B9ED00F1F2BD /* Search.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7751D3712B43B9ED00F1F2BD /* Search.swift */; };
7751D3742B43C9FA00F1F2BD /* MusicStyleViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7751D3732B43C9FA00F1F2BD /* MusicStyleViewController.swift */; };
7751D3762B43E8D200F1F2BD /* MusicStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7751D3752B43E8D200F1F2BD /* MusicStyle.swift */; };
7751D3782B43EA1200F1F2BD /* SearchResultsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7751D3772B43EA1200F1F2BD /* SearchResultsController.swift */; };
778B8A212AF8E36D0034AFD4 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 778B8A202AF8E36D0034AFD4 /* AppDelegate.swift */; };
778B8A232AF8E36D0034AFD4 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 778B8A222AF8E36D0034AFD4 /* SceneDelegate.swift */; };
778B8A282AF8E36D0034AFD4 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 778B8A262AF8E36D0034AFD4 /* Main.storyboard */; };
@ -101,6 +122,12 @@
77FA0B4C2B0EF8BB00404C5E /* LoginViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77FA0B4B2B0EF8BB00404C5E /* LoginViewModel.swift */; };
77FA0B4E2B0EF8C700404C5E /* PhoneCodeViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77FA0B4D2B0EF8C700404C5E /* PhoneCodeViewModel.swift */; };
77FA0B502B0EFEF400404C5E /* PhoneCodeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77FA0B4F2B0EFEF400404C5E /* PhoneCodeView.swift */; };
77FA0B522B0F3BC700404C5E /* MineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77FA0B512B0F3BC700404C5E /* MineView.swift */; };
77FA0B542B0F447400404C5E /* Mine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77FA0B532B0F447400404C5E /* Mine.swift */; };
77FA0B562B0F4ABF00404C5E /* MineSingleController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77FA0B552B0F4ABF00404C5E /* MineSingleController.swift */; };
77FA0B582B0F4C0800404C5E /* MineSingleViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77FA0B572B0F4C0800404C5E /* MineSingleViewModel.swift */; };
77FA0B5A2B147EC900404C5E /* CommentViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77FA0B592B147EC900404C5E /* CommentViewController.swift */; };
77FA0B5C2B147EE800404C5E /* CommentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77FA0B5B2B147EE800404C5E /* CommentView.swift */; };
77FAF7622B07434A00FC2CA1 /* AudioMoreActionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77FAF7612B07434A00FC2CA1 /* AudioMoreActionController.swift */; };
77FAF7642B075FEB00FC2CA1 /* JournalDetailViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77FAF7632B075FEB00FC2CA1 /* JournalDetailViewModel.swift */; };
B570F70B7040469E9D729E7E /* Pods_IndieMusic.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3BA421D41748C113CCE36A32 /* Pods_IndieMusic.framework */; };
@ -144,6 +171,27 @@
774A180F2B070A6900F56DF1 /* SongViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SongViewCell.swift; sourceTree = "<group>"; };
774A18112B07327C00F56DF1 /* CommentCountButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommentCountButton.swift; sourceTree = "<group>"; };
774A18132B07329600F56DF1 /* MultiUserAvatarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultiUserAvatarView.swift; sourceTree = "<group>"; };
7751D34F2B42ABBF00F1F2BD /* SettingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingViewController.swift; sourceTree = "<group>"; };
7751D3512B42AC2B00F1F2BD /* SettingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingView.swift; sourceTree = "<group>"; };
7751D3532B42AE0E00F1F2BD /* SettingViewMdel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingViewMdel.swift; sourceTree = "<group>"; };
7751D3552B42AE4600F1F2BD /* Setting.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Setting.swift; sourceTree = "<group>"; };
7751D3572B42B5A200F1F2BD /* EditInfoViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditInfoViewController.swift; sourceTree = "<group>"; };
7751D3592B42B5BD00F1F2BD /* EditInfoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditInfoView.swift; sourceTree = "<group>"; };
7751D35B2B42B5E900F1F2BD /* EditInfoViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditInfoViewModel.swift; sourceTree = "<group>"; };
7751D35D2B42B61100F1F2BD /* PersonInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PersonInfo.swift; sourceTree = "<group>"; };
7751D35F2B42BA3D00F1F2BD /* EditNameController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditNameController.swift; sourceTree = "<group>"; };
7751D3612B42BC0C00F1F2BD /* AccountViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountViewController.swift; sourceTree = "<group>"; };
7751D3632B42BC2E00F1F2BD /* AccountViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountViewModel.swift; sourceTree = "<group>"; };
7751D3652B42BE7F00F1F2BD /* FeedbackViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedbackViewController.swift; sourceTree = "<group>"; };
7751D3672B42E96200F1F2BD /* ThanksViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThanksViewController.swift; sourceTree = "<group>"; };
7751D3692B42ED6C00F1F2BD /* TimingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimingViewController.swift; sourceTree = "<group>"; };
7751D36B2B439F0000F1F2BD /* AboutViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutViewController.swift; sourceTree = "<group>"; };
7751D36D2B43A03E00F1F2BD /* PrivacyViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrivacyViewController.swift; sourceTree = "<group>"; };
7751D36F2B43A4FC00F1F2BD /* CacheViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CacheViewController.swift; sourceTree = "<group>"; };
7751D3712B43B9ED00F1F2BD /* Search.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Search.swift; sourceTree = "<group>"; };
7751D3732B43C9FA00F1F2BD /* MusicStyleViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MusicStyleViewController.swift; sourceTree = "<group>"; };
7751D3752B43E8D200F1F2BD /* MusicStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MusicStyle.swift; sourceTree = "<group>"; };
7751D3772B43EA1200F1F2BD /* SearchResultsController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchResultsController.swift; sourceTree = "<group>"; };
778B8A1D2AF8E36D0034AFD4 /* IndieMusic.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = IndieMusic.app; sourceTree = BUILT_PRODUCTS_DIR; };
778B8A202AF8E36D0034AFD4 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
778B8A222AF8E36D0034AFD4 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
@ -225,6 +273,12 @@
77FA0B4B2B0EF8BB00404C5E /* LoginViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginViewModel.swift; sourceTree = "<group>"; };
77FA0B4D2B0EF8C700404C5E /* PhoneCodeViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhoneCodeViewModel.swift; sourceTree = "<group>"; };
77FA0B4F2B0EFEF400404C5E /* PhoneCodeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhoneCodeView.swift; sourceTree = "<group>"; };
77FA0B512B0F3BC700404C5E /* MineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MineView.swift; sourceTree = "<group>"; };
77FA0B532B0F447400404C5E /* Mine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Mine.swift; sourceTree = "<group>"; };
77FA0B552B0F4ABF00404C5E /* MineSingleController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MineSingleController.swift; sourceTree = "<group>"; };
77FA0B572B0F4C0800404C5E /* MineSingleViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MineSingleViewModel.swift; sourceTree = "<group>"; };
77FA0B592B147EC900404C5E /* CommentViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommentViewController.swift; sourceTree = "<group>"; };
77FA0B5B2B147EE800404C5E /* CommentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommentView.swift; sourceTree = "<group>"; tabWidth = 14; };
77FAF7612B07434A00FC2CA1 /* AudioMoreActionController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioMoreActionController.swift; sourceTree = "<group>"; };
77FAF7632B075FEB00FC2CA1 /* JournalDetailViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JournalDetailViewModel.swift; sourceTree = "<group>"; };
A90C808FB1B74BB851FB67CB /* Pods-IndieMusic-IndieMusicUITests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-IndieMusic-IndieMusicUITests.debug.xcconfig"; path = "Target Support Files/Pods-IndieMusic-IndieMusicUITests/Pods-IndieMusic-IndieMusicUITests.debug.xcconfig"; sourceTree = "<group>"; };
@ -284,6 +338,8 @@
77FA0B2F2B0C4D5A00404C5E /* ShareActionController.swift */,
77FA0B332B0C50BA00404C5E /* ShareActionViewModel.swift */,
77FA0B312B0C4E8E00404C5E /* ShareActionView.swift */,
77FA0B592B147EC900404C5E /* CommentViewController.swift */,
77FA0B5B2B147EE800404C5E /* CommentView.swift */,
);
path = JournalDetail;
sourceTree = "<group>";
@ -434,6 +490,11 @@
77FA0B2D2B0C485D00404C5E /* AudioMoreAction.swift */,
77FA0B352B0C50D800404C5E /* Share.swift */,
77FA0B3D2B0C573600404C5E /* Filter.swift */,
77FA0B532B0F447400404C5E /* Mine.swift */,
7751D3552B42AE4600F1F2BD /* Setting.swift */,
7751D35D2B42B61100F1F2BD /* PersonInfo.swift */,
7751D3712B43B9ED00F1F2BD /* Search.swift */,
7751D3752B43E8D200F1F2BD /* MusicStyle.swift */,
);
path = Models;
sourceTree = "<group>";
@ -520,6 +581,9 @@
children = (
778B8A742AF8ECE50034AFD4 /* MineViewModel.swift */,
778B8A752AF8ECE50034AFD4 /* MineViewController.swift */,
77FA0B512B0F3BC700404C5E /* MineView.swift */,
77FA0B552B0F4ABF00404C5E /* MineSingleController.swift */,
77FA0B572B0F4C0800404C5E /* MineSingleViewModel.swift */,
);
path = Mine;
sourceTree = "<group>";
@ -545,6 +609,21 @@
778B8A7B2AF8ECE50034AFD4 /* Setting */ = {
isa = PBXGroup;
children = (
7751D34F2B42ABBF00F1F2BD /* SettingViewController.swift */,
7751D3512B42AC2B00F1F2BD /* SettingView.swift */,
7751D3532B42AE0E00F1F2BD /* SettingViewMdel.swift */,
7751D3572B42B5A200F1F2BD /* EditInfoViewController.swift */,
7751D3592B42B5BD00F1F2BD /* EditInfoView.swift */,
7751D35B2B42B5E900F1F2BD /* EditInfoViewModel.swift */,
7751D35F2B42BA3D00F1F2BD /* EditNameController.swift */,
7751D3612B42BC0C00F1F2BD /* AccountViewController.swift */,
7751D3632B42BC2E00F1F2BD /* AccountViewModel.swift */,
7751D3652B42BE7F00F1F2BD /* FeedbackViewController.swift */,
7751D3672B42E96200F1F2BD /* ThanksViewController.swift */,
7751D3692B42ED6C00F1F2BD /* TimingViewController.swift */,
7751D36D2B43A03E00F1F2BD /* PrivacyViewController.swift */,
7751D36B2B439F0000F1F2BD /* AboutViewController.swift */,
7751D36F2B43A4FC00F1F2BD /* CacheViewController.swift */,
);
path = Setting;
sourceTree = "<group>";
@ -554,6 +633,8 @@
children = (
778B8A7D2AF8ECE50034AFD4 /* SearchViewController.swift */,
778B8A7E2AF8ECE50034AFD4 /* SearchViewModel.swift */,
7751D3732B43C9FA00F1F2BD /* MusicStyleViewController.swift */,
7751D3772B43EA1200F1F2BD /* SearchResultsController.swift */,
);
path = Search;
sourceTree = "<group>";
@ -830,7 +911,11 @@
buildActionMask = 2147483647;
files = (
77FA0B422B0DFAA000404C5E /* LoginViewController.swift in Sources */,
7751D3702B43A4FC00F1F2BD /* CacheViewController.swift in Sources */,
7751D3642B42BC2E00F1F2BD /* AccountViewModel.swift in Sources */,
778B8A5D2AF8EC610034AFD4 /* Application.swift in Sources */,
7751D3622B42BC0C00F1F2BD /* AccountViewController.swift in Sources */,
7751D3542B42AE0E00F1F2BD /* SettingViewMdel.swift in Sources */,
774399A62AFE036A006F8EEA /* PlayerView.swift in Sources */,
778B8A5F2AF8ECAB0034AFD4 /* Navigator.swift in Sources */,
77FA0B302B0C4D5A00404C5E /* ShareActionController.swift in Sources */,
@ -838,21 +923,29 @@
778B8AAE2AF8ED0E0034AFD4 /* TextView.swift in Sources */,
778B8A9B2AF8ECFC0034AFD4 /* AuthManager.swift in Sources */,
778B8AAF2AF8ED0E0034AFD4 /* UIColor+IndieMusic.swift in Sources */,
7751D3722B43B9ED00F1F2BD /* Search.swift in Sources */,
774A18072B06045200F56DF1 /* HomeView.swift in Sources */,
77FAF7642B075FEB00FC2CA1 /* JournalDetailViewModel.swift in Sources */,
778B8AB12AF8ED1B0034AFD4 /* Configs.swift in Sources */,
77FA0B482B0DFB0E00404C5E /* EditBindPhoneViewController.swift in Sources */,
7751D35C2B42B5E900F1F2BD /* EditInfoViewModel.swift in Sources */,
7751D3602B42BA3D00F1F2BD /* EditNameController.swift in Sources */,
778B8A212AF8E36D0034AFD4 /* AppDelegate.swift in Sources */,
778B8AC32AF8ED280034AFD4 /* TabViewController.swift in Sources */,
77FAF7622B07434A00FC2CA1 /* AudioMoreActionController.swift in Sources */,
774A18122B07327C00F56DF1 /* CommentCountButton.swift in Sources */,
7751D36C2B439F0000F1F2BD /* AboutViewController.swift in Sources */,
77FA0B2C2B0C480B00404C5E /* AudioMoreActionViewModel.swift in Sources */,
778B8AC22AF8ED280034AFD4 /* TableViewController.swift in Sources */,
77FA0B562B0F4ABF00404C5E /* MineSingleController.swift in Sources */,
778B8A9D2AF8ECFC0034AFD4 /* LibsManager.swift in Sources */,
77FA0B4C2B0EF8BB00404C5E /* LoginViewModel.swift in Sources */,
778B8A832AF8ECE50034AFD4 /* HomeViewController.swift in Sources */,
778B8ABE2AF8ED280034AFD4 /* ViewModel.swift in Sources */,
77FA0B322B0C4E8E00404C5E /* ShareActionView.swift in Sources */,
7751D3782B43EA1200F1F2BD /* SearchResultsController.swift in Sources */,
7751D35A2B42B5BD00F1F2BD /* EditInfoView.swift in Sources */,
7751D35E2B42B61100F1F2BD /* PersonInfo.swift in Sources */,
774399A82AFE28BA006F8EEA /* BlurEffectView.swift in Sources */,
778B8A852AF8ECE50034AFD4 /* SearchViewController.swift in Sources */,
774A17F52B045F1C00F56DF1 /* Player.swift in Sources */,
@ -863,9 +956,11 @@
774A18092B06120000F56DF1 /* Home.swift in Sources */,
778B8ABF2AF8ED280034AFD4 /* NavigationController.swift in Sources */,
774399AA2AFE3170006F8EEA /* PaddingLabel.swift in Sources */,
7751D3502B42ABBF00F1F2BD /* SettingViewController.swift in Sources */,
77FA0B4E2B0EF8C700404C5E /* PhoneCodeViewModel.swift in Sources */,
778B8A822AF8ECE50034AFD4 /* HomeViewModel.swift in Sources */,
778B8AAD2AF8ED0E0034AFD4 /* RxMJRefresh.swift in Sources */,
7751D3742B43C9FA00F1F2BD /* MusicStyleViewController.swift in Sources */,
778B8A922AF8ECF20034AFD4 /* AudioTrack.swift in Sources */,
778B8A862AF8ECE50034AFD4 /* SearchViewModel.swift in Sources */,
778B8A802AF8ECE50034AFD4 /* MineViewController.swift in Sources */,
@ -877,24 +972,33 @@
778B8A8E2AF8ECF20034AFD4 /* Artist.swift in Sources */,
774A17F32B0459C900F56DF1 /* PlayerViewModel.swift in Sources */,
778B8A6D2AF8ECD30034AFD4 /* Observable+Operators.swift in Sources */,
77FA0B542B0F447400404C5E /* Mine.swift in Sources */,
778B8ABB2AF8ED280034AFD4 /* WebViewController.swift in Sources */,
774A17F72B04932100F56DF1 /* SegmentControl.swift in Sources */,
77FA0B282B0B3E1E00404C5E /* Journal.swift in Sources */,
77FA0B5A2B147EC900404C5E /* CommentViewController.swift in Sources */,
77FA0B402B0D8E9300404C5E /* LayoutableButton.swift in Sources */,
778B8A712AF8ECD30034AFD4 /* Api.swift in Sources */,
77FA0B582B0F4C0800404C5E /* MineSingleViewModel.swift in Sources */,
77FA0B342B0C50BA00404C5E /* ShareActionViewModel.swift in Sources */,
7751D3562B42AE4600F1F2BD /* Setting.swift in Sources */,
77FA0B502B0EFEF400404C5E /* PhoneCodeView.swift in Sources */,
778B8A812AF8ECE50034AFD4 /* HomeTabBarViewModel.swift in Sources */,
77FA0B4A2B0EE8F000404C5E /* PhoneCodeController.swift in Sources */,
778B8AC02AF8ED280034AFD4 /* ViewController.swift in Sources */,
774399A02AFA1968006F8EEA /* PlayerTabBar.swift in Sources */,
77FA0B3C2B0C55E500404C5E /* FilterView.swift in Sources */,
77FA0B5C2B147EE800404C5E /* CommentView.swift in Sources */,
778B8A902AF8ECF20034AFD4 /* Token.swift in Sources */,
778B8A6B2AF8ECD30034AFD4 /* IndieMusicAPI.swift in Sources */,
7751D36E2B43A03E00F1F2BD /* PrivacyViewController.swift in Sources */,
7751D3582B42B5A200F1F2BD /* EditInfoViewController.swift in Sources */,
774A180B2B06F8B900F56DF1 /* JournalDetailController.swift in Sources */,
7751D3522B42AC2B00F1F2BD /* SettingView.swift in Sources */,
77FA0B362B0C50D800404C5E /* Share.swift in Sources */,
778B8A622AF8ECC20034AFD4 /* ErrorTracker.swift in Sources */,
774A18102B070A6900F56DF1 /* SongViewCell.swift in Sources */,
7751D3762B43E8D200F1F2BD /* MusicStyle.swift in Sources */,
778B8AA92AF8ED0E0034AFD4 /* UIImage+IndieMusic.swift in Sources */,
778B8A7F2AF8ECE50034AFD4 /* MineViewModel.swift in Sources */,
778B8A9A2AF8ECFC0034AFD4 /* AudioManager.swift in Sources */,
@ -902,17 +1006,21 @@
778B8A842AF8ECE50034AFD4 /* HomeTabBarController.swift in Sources */,
77FA0B3A2B0C55D900404C5E /* FilterViewModel.swift in Sources */,
778B8A9E2AF8ECFC0034AFD4 /* ThemeManager.swift in Sources */,
7751D3682B42E96200F1F2BD /* ThanksViewController.swift in Sources */,
778B8A702AF8ECD30034AFD4 /* ErrorResponse.swift in Sources */,
77FA0B2A2B0B5F0D00404C5E /* AudioMoreActionView.swift in Sources */,
778B8A6C2AF8ECD30034AFD4 /* Networking.swift in Sources */,
77FA0B2E2B0C485D00404C5E /* AudioMoreAction.swift in Sources */,
778B8AAC2AF8ED0E0034AFD4 /* UIViewController+Rx.swift in Sources */,
778B8A8D2AF8ECF20034AFD4 /* APIImage.swift in Sources */,
7751D36A2B42ED6C00F1F2BD /* TimingViewController.swift in Sources */,
77FA0B462B0DFAFD00404C5E /* BindPhoneViewController.swift in Sources */,
77FA0B382B0C54C700404C5E /* FilterViewController.swift in Sources */,
77FA0B522B0F3BC700404C5E /* MineView.swift in Sources */,
778B8A6E2AF8ECD30034AFD4 /* RestApi.swift in Sources */,
778B8ABC2AF8ED280034AFD4 /* PresentationController.swift in Sources */,
77FA0B3E2B0C573600404C5E /* Filter.swift in Sources */,
7751D3662B42BE7F00F1F2BD /* FeedbackViewController.swift in Sources */,
774A18142B07329600F56DF1 /* MultiUserAvatarView.swift in Sources */,
778B8AAA2AF8ED0E0034AFD4 /* AVPlayer.swift in Sources */,
77FA0B442B0DFABD00404C5E /* LoginView.swift in Sources */,

@ -36,24 +36,15 @@ class NavigationController: UINavigationController {
setup()
if #available(iOS 13.0, *) {
let appearance = UINavigationBarAppearance()
appearance.backgroundColor = .white
appearance.titleTextAttributes = [.foregroundColor: UIColor.black]
appearance.largeTitleTextAttributes = [.foregroundColor: UIColor.black]
UINavigationBar.appearance().tintColor = UIColor(red: 0.25, green: 0.25, blue: 0.25, alpha: 1.00)
UINavigationBar.appearance().standardAppearance = appearance
UINavigationBar.appearance().compactAppearance = appearance
UINavigationBar.appearance().scrollEdgeAppearance = appearance
} else {
navigationBar.barTintColor = UIColor(red: 0.25, green: 0.25, blue: 0.25, alpha: 1.00)
}
//
// self.navigationBar.prefersLargeTitles = false
// self.navigationController.
let appearance = UINavigationBarAppearance()
appearance.backgroundColor = .white
appearance.titleTextAttributes = [.foregroundColor: UIColor.black]
appearance.largeTitleTextAttributes = [.foregroundColor: UIColor.black]
UINavigationBar.appearance().tintColor = UIColor(red: 0.25, green: 0.25, blue: 0.25, alpha: 1.00)
UINavigationBar.appearance().standardAppearance = appearance
UINavigationBar.appearance().compactAppearance = appearance
UINavigationBar.appearance().scrollEdgeAppearance = appearance
}

@ -119,7 +119,7 @@ class ViewController: UIViewController {
// self.navigationItem.leftBarButtonItems = [spacer, backBarButton]
view.backgroundColor = .white
navigationItem.leftBarButtonItem = backBarButton
// navigationItem.leftBarButtonItem = backBarButton
updateUI()
}

@ -0,0 +1,54 @@
//
// Mine.swift
// IndieMusic
//
// Created by WenLei on 2023/11/23.
//
import Foundation
import RxDataSources
struct Mine: Codable {
let title: String
let detail: String
}
struct MineSection {
var items: [Mine]
}
extension MineSection: SectionModelType {
typealias Item = Mine
init(original: MineSection, items: [Item]) {
self = original
self.items = items
}
}
struct MineSingle {
let cover: String
let title: String
let detail: String
}
struct MineSingleSection {
var items: [MineSingle]
}
extension MineSingleSection: SectionModelType {
typealias Item = MineSingle
init(original: MineSingleSection, items: [Item]) {
self = original
self.items = items
}
}

@ -0,0 +1,30 @@
//
// MusicStyle.swift
// IndieMusic
//
// Created by WenLei on 2024/1/2.
//
import Foundation
import RxDataSources
struct MusicStyle: Codable {
let title: String
let subTitle: String
let backgroundImage: String
}
struct MusicStyleSection {
var items: [MusicStyle]
}
extension MusicStyleSection: SectionModelType {
typealias Item = MusicStyle
init(original: MusicStyleSection, items: [Item]) {
self = original
self.items = items
}
}

@ -0,0 +1,17 @@
//
// PersonInfo.swift
// IndieMusic
//
// Created by WenLei on 2024/1/1.
//
import Foundation
struct PersonInfo {
let avator: String
let name: String
let slogn: String
let day: String
let sex: String
}

@ -0,0 +1,47 @@
//
// Search.swift
// IndieMusic
//
// Created by WenLei on 2024/1/2.
//
import Foundation
import RxDataSources
enum SearchType {
case single
case journal
}
extension SearchType {
var description: String {
switch self {
case .single:
return "单曲"
case .journal:
return "期刊"
}
}
}
struct Search: Codable {
let title: String
let subTitle: String
let backgroundImage: String
}
struct SearchSection {
var items: [Search]
}
extension SearchSection: SectionModelType {
typealias Item = Search
init(original: SearchSection, items: [Item]) {
self = original
self.items = items
}
}

@ -0,0 +1,48 @@
//
// Setting.swift
// IndieMusic
//
// Created by WenLei on 2024/1/1.
//
import Foundation
import RxDataSources
struct Setting: Codable {
let title: String
let detail: String
let arrowIcon: String
}
enum SettingType {
case editInfo(Setting)
case account(Setting)
case privacy(Setting)
case timing(Setting)
case cache(Setting)
case permission(Setting)
case feedback(Setting)
case about(Setting)
case contributors(Setting)
case version(Setting)
case setting(Setting)
}
struct SettingSection {
var items: [SettingType]
}
extension SettingSection: SectionModelType {
typealias Item = SettingType
init(original: SettingSection, items: [Item]) {
self = original
self.items = items
}
}

@ -71,6 +71,7 @@ class HomeTabBarController: UITabBarController, Navigatable {
var customeTabBar: UITabBar = {
let tabBar = UITabBar.init()
tabBar.isTranslucent = false
return tabBar
}()

@ -44,8 +44,8 @@ class HomeViewController: TableViewController {
let login = LoginViewController.init(viewModel: viewModel, navigator: navigator)
self.navigationController?.pushViewController(login, animated: true)
// let login = LoginViewController.init(viewModel: viewModel, navigator: navigator)
// self.navigationController?.pushViewController(login, animated: true)
}
override func makeUI() {

@ -0,0 +1,224 @@
//
// CommentViewCell.swift
// IndieMusic
//
// Created by WenLei on 2023/11/27.
//
import UIKit
class CommentHeaderView: UIView {
var titleLabel: UILabel = {
let titleLabel = UILabel.init()
return titleLabel
}()
var segmentControl: SegmentControl = {
let segmentControl = SegmentControl.init()
segmentControl.items = ["热门", "最新"]
return segmentControl
}()
override init(frame: CGRect) {
super.init(frame: frame)
makeUI()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func makeUI() {
addSubview(titleLabel)
addSubview(segmentControl)
}
override func layoutSubviews() {
super.layoutSubviews()
titleLabel.snp.makeConstraints { make in
make.left.equalTo(self).offset(18)
make.centerY.equalTo(self)
}
segmentControl.snp.makeConstraints { make in
make.right.equalTo(self).offset(0)
make.centerY.equalTo(self)
}
}
}
class CommentViewCell: UITableViewCell {
var avatarView: UIImageView = {
let avatarView = UIImageView.init()
return avatarView
}()
var nameLabel: UILabel = {
let nameLabel = UILabel.init()
return nameLabel
}()
var dateLabel: UILabel = {
let dateLabel = UILabel.init()
return dateLabel
}()
var likeButton: UIButton = {
let likeButton = UIButton.init()
return likeButton
}()
var commentLabel: UILabel = {
let commentLabel = UILabel.init()
return commentLabel
}()
var subCommentView: UIView = {
let subCommentView = UIView.init()
return subCommentView
}()
var subAvatarView: UIImageView = {
let subAvatarView = UIImageView.init()
return subAvatarView
}()
var subCommentLabel: UILabel = {
let subCommentLabel = UILabel.init()
return subCommentLabel
}()
var moreButton: UIButton = {
let moreButton = UIButton.init()
return moreButton
}()
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
makeUI()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func makeUI() {
contentView.addSubview(avatarView)
contentView.addSubview(nameLabel)
contentView.addSubview(dateLabel)
contentView.addSubview(likeButton)
contentView.addSubview(commentLabel)
contentView.addSubview(subCommentView)
subCommentView.addSubview(subAvatarView)
subCommentView.addSubview(subCommentLabel)
subCommentView.addSubview(moreButton)
}
override func layoutSubviews() {
super.layoutSubviews()
avatarView.snp.makeConstraints { make in
make.left.equalTo(contentView).offset(18)
make.top.equalTo(contentView).offset(12)
make.size.equalTo(CGSize.init(width: 40, height: 40))
}
moreButton.snp.makeConstraints { make in
make.right.equalTo(contentView).offset(18)
make.centerY.equalTo(avatarView)
}
nameLabel.snp.makeConstraints { make in
make.top.equalTo(avatarView)
make.left.equalTo(avatarView.snp.right).offset(14)
make.right.equalTo(moreButton.snp.left).offset(-10)
}
dateLabel.snp.makeConstraints { make in
make.left.equalTo(avatarView.snp.right).offset(14)
make.top.equalTo(nameLabel.snp.bottom).offset(2)
}
commentLabel.snp.makeConstraints { make in
make.left.equalTo(avatarView.snp.right).offset(14)
make.right.equalTo(contentView).offset(-18)
make.top.equalTo(dateLabel.snp.bottom).offset(10)
}
subCommentView.snp.makeConstraints { make in
make.left.equalTo(avatarView.snp.right).offset(14)
make.right.equalTo(contentView).offset(-18)
make.top.equalTo(commentLabel.snp.bottom).offset(15)
make.bottom.equalTo(contentView).offset(-12)
}
subAvatarView.snp.makeConstraints { make in
make.left.equalTo(subCommentView)
make.top.equalTo(subCommentView)
make.size.equalTo(CGSize.init(width: 20, height: 20))
}
subCommentLabel.snp.makeConstraints { make in
make.left.equalTo(subAvatarView.snp.right).offset(5)
make.right.equalTo(subCommentView)
make.top.equalTo(subCommentView)
}
moreButton.snp.makeConstraints { make in
make.top.equalTo(subCommentLabel.snp.bottom).offset(12)
make.bottom.equalTo(subCommentView)
make.left.equalTo(subCommentView)
}
}
}

@ -0,0 +1,53 @@
//
// CommentViewController.swift
// IndieMusic
//
// Created by WenLei on 2023/11/27.
//
import UIKit
import RxSwift
import RxCocoa
import RxDataSources
class CommentViewController: ViewController {
var tableView: UITableView = {
let tableView = UITableView.init()
return tableView
}()
override func viewDidLoad() {
super.viewDidLoad()
}
override func makeUI() {
super.makeUI()
view.addSubview(tableView)
}
override func bindViewModel() {
super.bindViewModel()
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
tableView.snp.makeConstraints { make in
make.edges.equalTo(view)
}
}
}

@ -231,7 +231,6 @@ class JournalDetailHeaderView: UIView {
}
contentLabel.snp.remakeConstraints { make in
make.left.equalTo(containerView.snp.left).offset(18)
make.right.equalTo(containerView.snp.right).offset(-18)
make.top.equalTo(authorLabel.snp.bottom).offset(15)

@ -0,0 +1,66 @@
//
// MineSingleController.swift
// IndieMusic
//
// Created by WenLei on 2023/11/23.
//
import UIKit
import RxSwift
import RxCocoa
import RxDataSources
class MineSingleController: TableViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func makeUI() {
super.makeUI()
}
override func bindViewModel() {
super.bindViewModel()
guard let viewModel = viewModel as? MineSingleViewModel else { return }
let input = MineSingleViewModel.Input.init(viewWillAppear: rx.viewWillAppear,
selection: tableView.rx.itemSelected.asDriver())
let output = viewModel.transform(input: input)
let dataSource = MineSingleController.dataSource()
output.items.bind(to: tableView.rx.items(dataSource: dataSource)).disposed(by: rx.disposeBag)
output.itemSelected.subscribe { sectionItem in
}.disposed(by: rx.disposeBag)
}
}
extension MineSingleController {
static func dataSource() -> RxTableViewSectionedReloadDataSource<MineSingleSection> {
return RxTableViewSectionedReloadDataSource<MineSingleSection>(
configureCell: { dataSource, tableView, indexPath, item in
let cell: SongViewCell = tableView.dequeueReusableCell(withIdentifier: "SongViewCell", for: indexPath) as! SongViewCell
// cell.titleLabel.text = "123"
// cell.detailLabel.text = "321"
return cell
}
)
}
}

@ -0,0 +1,54 @@
//
// MineSingleViewModel.swift
// IndieMusic
//
// Created by WenLei on 2023/11/23.
//
import Foundation
import RxSwift
import RxCocoa
import RxDataSources
class MineSingleViewModel: ViewModel, ViewModelType {
struct Input {
let viewWillAppear: ControlEvent<Bool>
let selection: Driver<IndexPath>
}
struct Output {
let items: BehaviorRelay<[MineSingleSection]>
let selection: Driver<IndexPath>
let itemSelected: PublishSubject<MineSingle>
}
let itemSelected = PublishSubject<MineSingle>()
let items = BehaviorRelay<[MineSingleSection]>.init(value: [])
func transform(input: Input) -> Output {
input.viewWillAppear.subscribe { (_) in
}.disposed(by: rx.disposeBag)
let mine = MineSingle.init(cover: "", title: "", detail: "")
items.accept([MineSingleSection.init(items: [mine, mine, mine])])
input.selection.drive { indexPath in
guard let sectionItem = self.items.value.first?.items[indexPath.row] else { return }
self.itemSelected.onNext(sectionItem)
}.disposed(by: rx.disposeBag)
return Output.init(items: items,
selection: input.selection,
itemSelected: itemSelected)
}
}

@ -0,0 +1,355 @@
//
// MineView.swift
// IndieMusic
//
// Created by WenLei on 2023/11/23.
//
import UIKit
class MineHeaderView: UIView {
lazy var iconView: UIImageView = {
let iconView = UIImageView.init()
iconView.layer.cornerRadius = 32
iconView.backgroundColor = .red
return iconView
}()
lazy var nameButton: UIButton = {
let nameButton = UIButton.init()
nameButton.titleLabel?.font = UIFont.systemFont(ofSize: 20, weight: .medium)
nameButton.setTitle("立即登录", for: .normal)
return nameButton
}()
lazy var tipsLabel: UILabel = {
let tipsLabel = UILabel.init()
tipsLabel.font = UIFont.systemFont(ofSize: 12)
tipsLabel.text = "独立 不独于世"
tipsLabel.textColor = .init(hex: 0x000000, alpha: 0.6)
return tipsLabel
}()
var mineMenuView: MineMenuView = {
let mineMenuView = MineMenuView.init()
return mineMenuView
}()
var lineView: UIView = {
let lineView = UIView.init()
lineView.backgroundColor = .separator()
return lineView
}()
override init(frame: CGRect) {
super.init(frame: frame)
makeUI()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func makeUI() {
backgroundColor = .white
addSubview(iconView)
addSubview(nameButton)
addSubview(tipsLabel)
addSubview(mineMenuView)
addSubview(lineView)
}
override func layoutSubviews() {
super.layoutSubviews()
iconView.snp.makeConstraints { make in
make.left.equalTo(self).offset(18)
make.top.equalTo(self).offset(11)
make.size.equalTo(CGSize.init(width: 64, height: 64))
}
nameButton.snp.makeConstraints { make in
make.left.equalTo(iconView.snp.right).offset(18)
make.top.equalTo(iconView).offset(4)
}
tipsLabel.snp.makeConstraints { make in
make.left.equalTo(iconView.snp.right).offset(18)
make.top.equalTo(nameButton.snp.bottom).offset(6)
make.right.equalTo(self).offset(-18)
}
mineMenuView.snp.makeConstraints { make in
make.left.equalTo(self)
make.right.equalTo(self)
make.top.equalTo(iconView.snp.bottom).offset(16)
make.height.equalTo(74)
}
lineView.snp.makeConstraints { make in
make.left.equalTo(self).offset(18)
make.right.equalTo(self).offset(-18)
make.height.equalTo(1)
make.top.equalTo(mineMenuView.snp.bottom).offset(18)
}
}
}
class MineMenuView: UIView {
lazy var followingView: MineMenuSubView = {
let followingView = MineMenuSubView.init()
followingView.titleLabel.text = "关注"
followingView.detailLabel.text = "123"
return followingView
}()
lazy var followersView: MineMenuSubView = {
let followersView = MineMenuSubView.init()
followersView.titleLabel.text = "粉丝"
followersView.detailLabel.text = "123"
return followersView
}()
lazy var likeView: MineMenuSubView = {
let likeView = MineMenuSubView.init()
likeView.titleLabel.text = "获赞"
likeView.detailLabel.text = "123"
return likeView
}()
lazy var commentView: MineMenuSubView = {
let commentView = MineMenuSubView.init()
commentView.titleLabel.text = "评论"
commentView.detailLabel.text = "123"
return commentView
}()
override init(frame: CGRect) {
super.init(frame: frame)
makeUI()
backgroundColor = .white
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func makeUI() {
addSubview(followingView)
addSubview(followersView)
addSubview(likeView)
addSubview(commentView)
}
override func layoutSubviews() {
super.layoutSubviews()
let width = self.bounds.width / 4
followingView.snp.remakeConstraints { make in
make.left.equalTo(self)
make.top.equalTo(self)
make.bottom.equalTo(self)
make.width.equalTo(width)
}
followersView.snp.remakeConstraints { make in
make.left.equalTo(followingView.snp.right)
make.top.equalTo(self)
make.bottom.equalTo(self)
make.width.equalTo(width)
}
likeView.snp.remakeConstraints { make in
make.left.equalTo(followersView.snp.right)
make.top.equalTo(self)
make.bottom.equalTo(self)
make.width.equalTo(width)
}
commentView.snp.remakeConstraints { make in
make.left.equalTo(likeView.snp.right)
make.top.equalTo(self)
make.bottom.equalTo(self)
make.width.equalTo(width)
make.right.equalTo(self)
}
}
}
class MineMenuSubView: UIView {
lazy var titleLabel: UILabel = {
let titleLabel = UILabel.init()
titleLabel.font = UIFont.systemFont(ofSize: 12)
titleLabel.textAlignment = .center
titleLabel.textColor = .init(hex: 0x000000, alpha: 0.6)
return titleLabel
}()
lazy var detailLabel: UILabel = {
let detailLabel = UILabel.init()
detailLabel.font = UIFont.systemFont(ofSize: 20, weight: .medium)
detailLabel.textAlignment = .center
return detailLabel
}()
override init(frame: CGRect) {
super.init(frame: frame)
makeUI()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func makeUI() {
addSubview(detailLabel)
addSubview(titleLabel)
}
override func layoutSubviews() {
super.layoutSubviews()
detailLabel.snp.makeConstraints { make in
make.top.equalTo(self).offset(14)
make.left.equalTo(self)
make.right.equalTo(self)
}
titleLabel.snp.makeConstraints { make in
make.top.equalTo(detailLabel.snp.bottom).offset(3)
make.left.equalTo(self)
make.right.equalTo(self)
make.bottom.equalTo(self).offset(-16)
}
}
}
class MineViewCell: UITableViewCell {
lazy var coverView: UIImageView = {
let coverView = UIImageView.init()
coverView.layer.cornerRadius = 3
coverView.layer.masksToBounds = true
coverView.backgroundColor = .red
return coverView
}()
lazy var titleLabel: UILabel = {
let titleLabel = UILabel.init()
titleLabel.font = UIFont.systemFont(ofSize: 15, weight: .medium)
return titleLabel
}()
lazy var detailLabel: UILabel = {
let detailLabel = UILabel.init()
detailLabel.font = UIFont.systemFont(ofSize: 12)
detailLabel.textColor = .init(hex: 0x000000, alpha: 0.6)
return detailLabel
}()
lazy var playButton: UIButton = {
let playButton = UIButton.init()
playButton.setImage(UIImage.init(named: "mine_play_btn"), for: .normal)
playButton.setImage(UIImage.init(named: ""), for: .selected)
playButton.setContentHuggingPriority(.required, for: .horizontal)
playButton.setContentCompressionResistancePriority(.required, for: .horizontal)
return playButton
}()
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
makeUI()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func makeUI () {
contentView.addSubview(coverView)
contentView.addSubview(titleLabel)
contentView.addSubview(detailLabel)
contentView.addSubview(playButton)
coverView.snp.makeConstraints { make in
make.left.equalTo(contentView).offset(18)
make.top.equalTo(contentView).offset(18)
make.bottom.equalTo(contentView).offset(-18)
make.size.equalTo(CGSize.init(width: 64, height: 64))
}
playButton.snp.makeConstraints { make in
make.right.equalTo(contentView).offset(-18)
make.centerY.equalTo(contentView)
}
titleLabel.snp.makeConstraints { make in
make.left.equalTo(coverView.snp.right).offset(15)
make.top.equalTo(coverView).offset(10)
make.right.equalTo(playButton.snp.left).offset(-10).priority(.low)
}
detailLabel.snp.makeConstraints { make in
make.left.equalTo(coverView.snp.right).offset(15)
make.top.equalTo(titleLabel.snp.bottom).offset(10)
make.right.equalTo(playButton.snp.left).offset(-6).priority(.low)
}
}
override var frame:CGRect{
didSet {
let inset: CGFloat = 18.0
var newFrame = frame
newFrame.origin.x += inset
newFrame.size.width -= 2*inset
super.frame = newFrame
}
}
}

@ -6,19 +6,76 @@
//
import UIKit
import RxSwift
import RxCocoa
import RxDataSources
class MineViewController: TableViewController {
let headerView: MineHeaderView = {
let headerView = MineHeaderView.init(frame: CGRect.init(x: 0, y: 0, width: BaseDimensions.screenWidth, height: 201))
return headerView
}()
class MineViewController: ViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func makeUI() {
super.makeUI()
view.backgroundColor = .blue
tableView.tableHeaderView = headerView
tableView.separatorColor = .clear
tableView.register(MineViewCell.self, forCellReuseIdentifier: "MineViewCell")
}
override func bindViewModel() {
super.bindViewModel()
guard let viewModel = viewModel as? MineViewModel else { return }
let input = MineViewModel.Input.init(viewWillAppear: rx.viewWillAppear,
selection: tableView.rx.itemSelected.asDriver())
let output = viewModel.transform(input: input)
let dataSource = MineViewController.dataSource()
output.items.bind(to: tableView.rx.items(dataSource: dataSource)).disposed(by: rx.disposeBag)
output.itemSelected.subscribe { sectionItem in
}.disposed(by: rx.disposeBag)
}
}
extension MineViewController {
static func dataSource() -> RxTableViewSectionedReloadDataSource<MineSection> {
return RxTableViewSectionedReloadDataSource<MineSection>(
configureCell: { dataSource, tableView, indexPath, item in
let cell: MineViewCell = tableView.dequeueReusableCell(withIdentifier: "MineViewCell", for: indexPath) as! MineViewCell
cell.titleLabel.text = "123"
cell.detailLabel.text = "321"
return cell
}
)
}
}

@ -6,20 +6,49 @@
//
import Foundation
import RxSwift
import RxCocoa
import RxDataSources
class MineViewModel: ViewModel, ViewModelType {
struct Input {
let viewWillAppear: ControlEvent<Bool>
let selection: Driver<IndexPath>
}
struct Output {
let items: BehaviorRelay<[MineSection]>
let selection: Driver<IndexPath>
let itemSelected: PublishSubject<Mine>
}
let itemSelected = PublishSubject<Mine>()
let items = BehaviorRelay<[MineSection]>.init(value: [])
func transform(input: Input) -> Output {
input.viewWillAppear.subscribe { (_) in
}.disposed(by: rx.disposeBag)
let mine = Mine.init(title: "ttt", detail: "123")
items.accept([MineSection.init(items: [mine, mine, mine])])
input.selection.drive { indexPath in
guard let sectionItem = self.items.value.first?.items[indexPath.row] else { return }
self.itemSelected.onNext(sectionItem)
}.disposed(by: rx.disposeBag)
return Output()
return Output.init(items: items,
selection: input.selection,
itemSelected: itemSelected)
}
}

@ -0,0 +1,320 @@
//
// MusicStyleViewController.swift
// IndieMusic
//
// Created by WenLei on 2024/1/2.
//
import UIKit
import RxSwift
import RxCocoa
import RxDataSources
class MusicStyleViewController: ViewController {
let collectionView: UICollectionView = {
let collectionView = UICollectionView.init()
return collectionView
}()
lazy var headerView: MusicStyleHeaderView = {
let headerView = MusicStyleHeaderView.init()
headerView.backgroundColor = .red
return headerView
}()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func makeUI() {
super.makeUI()
}
override func bindViewModel() {
super.bindViewModel()
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
}
func updateText(text: String) {
updateHeader()
}
func updateHeader() {
collectionView.collectionViewLayout.invalidateLayout()
}
}
extension MusicStyleViewController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
// section header
let width = collectionView.bounds.width
headerView.frame = CGRect(x: 0, y: 0, width: width, height: 1000)
headerView.layoutIfNeeded()
let size = headerView.systemLayoutSizeFitting(CGSize(width: width, height: UIView.layoutFittingCompressedSize.height),
withHorizontalFittingPriority: .required,
verticalFittingPriority: .fittingSizeLevel)
return CGSize(width: collectionView.bounds.width, height: size.height)
}
static func dataSource() -> RxCollectionViewSectionedReloadDataSource<MusicStyleSection> {
return RxCollectionViewSectionedReloadDataSource<MusicStyleSection>(
configureCell: { dataSource, collectionView, indexPath, item in
// cell
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MusicStyleCellView", for: indexPath)
// cell
return cell
}
)
}
}
class MusicStyleHeaderView: UIView {
let titleImageView: UIImageView = {
let titleImageView = UIImageView.init()
return titleImageView
}()
let containerView: UIView = {
let containerView = UIView.init()
containerView.layer.cornerRadius = 8
containerView.layer.masksToBounds = true
containerView.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
return containerView
}()
let styleLabel: UILabel = {
let styleLabel = UILabel.init()
styleLabel.font = UIFont.systemFont(ofSize: 24, weight: .medium)
styleLabel.textColor = .init(hex: 0x000000, alpha: 1)
return styleLabel
}()
let subStyleLabel: UILabel = {
let subStyleLabel = UILabel.init()
subStyleLabel.font = UIFont.systemFont(ofSize: 14)
subStyleLabel.textColor = .init(hex: 0x000000, alpha: 0.6)
return subStyleLabel
}()
let contentLabel: UILabel = {
let contentLabel = UILabel.init()
contentLabel.font = UIFont.systemFont(ofSize: 15)
contentLabel.textColor = .init(hex: 0x000000, alpha: 0.6)
return contentLabel
}()
var dropButton: UIButton = {
let dropButton = UIButton.init()
dropButton.setTitle("展开", for: .normal)
dropButton.setTitle("收起", for: .selected)
dropButton.setTitleColor(.init(hex: 0x000000, alpha: 0.6), for: .normal)
dropButton.setImage(UIImage.init(named: "journal_drop_up"), for: .normal)
dropButton.setImage(UIImage.init(named: "journal_drop_up"), for: .selected)
return dropButton
}()
var gradientLayer: CAGradientLayer = {
let gradientLayer = CAGradientLayer.init()
gradientLayer.colors = [UIColor.init(hex: 0xFFFFFF, alpha: 0).cgColor,
UIColor.init(hex: 0xFFFFFF, alpha: 0.8).cgColor]
gradientLayer.locations = [0.0, 0.9]
gradientLayer.startPoint = CGPoint.init(x: 0 , y: 0)
gradientLayer.endPoint = CGPoint.init(x: 0, y: 1)
return gradientLayer
}()
var isExpand = false {
didSet {
switch isExpand {
case true:
dropButton.isSelected = true
contentLabel.numberOfLines = 0
// contentLabel.lineBreakMode = .byClipping
gradientLayer.isHidden = true
case false:
dropButton.isSelected = false
contentLabel.numberOfLines = 4
// contentLabel.lineBreakMode = .byClipping
gradientLayer.isHidden = false
}
}
}
override init(frame: CGRect) {
super.init(frame: frame)
makeUI()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func makeUI() {
addSubview(titleImageView)
addSubview(containerView)
containerView.addSubview(styleLabel)
containerView.addSubview(subStyleLabel)
containerView.addSubview(contentLabel)
}
override func layoutSubviews() {
super.layoutSubviews()
titleImageView.snp.makeConstraints { make in
make.left.equalTo(self)
make.right.equalTo(self)
make.top.equalTo(self)
make.height.equalTo(294)
}
containerView.snp.makeConstraints { make in
make.left.equalTo(self)
make.right.equalTo(self)
make.top.equalTo(self).offset(BaseDimensions.topHeight + 59)
make.bottom.equalTo(self)
}
styleLabel.snp.makeConstraints { make in
make.left.equalTo(containerView).offset(18)
make.top.equalTo(containerView).offset(24)
}
subStyleLabel.snp.makeConstraints { make in
make.left.equalTo(styleLabel.snp.right).offset(11)
make.centerY.equalTo(styleLabel)
}
contentLabel.snp.makeConstraints { make in
make.left.equalTo(containerView).offset(18)
make.right.equalTo(containerView).offset(-18)
make.top.equalTo(styleLabel.snp.bottom).offset(15)
}
dropButton.snp.remakeConstraints { make in
make.left.equalTo(containerView).offset(18)
make.top.equalTo(contentLabel.snp.bottom).offset(16)
make.bottom.equalTo(containerView.snp.bottom).offset(-35)
}
gradientLayer.frame = self.contentLabel.bounds
}
}
class MusicStyleCellView: UICollectionViewCell {
let titleImageView: UIImageView = {
let titleImageView = UIImageView.init()
titleImageView.layer.cornerRadius = 8
titleImageView.layer.masksToBounds = true
return titleImageView
}()
let volLabel: UILabel = {
let volLabel = UILabel.init()
volLabel.font = UIFont.systemFont(ofSize: 12)
volLabel.textColor = .init(hex: 0x000000, alpha: 0.4)
return volLabel
}()
let titleLabel: UILabel = {
let titleLabel = UILabel.init()
titleLabel.font = UIFont.systemFont(ofSize: 14, weight: .medium)
return titleLabel
}()
override init(frame: CGRect) {
super.init(frame: frame)
makeUI()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func makeUI() {
contentView.addSubview(titleImageView)
contentView.addSubview(volLabel)
contentView.addSubview(titleLabel)
titleImageView.snp.makeConstraints { make in
make.left.equalTo(contentView)
make.right.equalTo(contentView)
make.top.equalTo(contentView)
make.height.equalTo(100)
}
volLabel.snp.makeConstraints { make in
make.left.equalTo(contentView)
make.top.equalTo(titleImageView.snp.bottom).offset(9)
make.right.equalTo(contentView)
}
titleLabel.snp.makeConstraints { make in
make.left.equalTo(contentView)
make.right.equalTo(contentView)
make.top.equalTo(volLabel.snp.bottom).offset(2)
}
}
}

@ -0,0 +1,288 @@
//
// SearchResultsController.swift
// IndieMusic
//
// Created by WenLei on 2024/1/2.
//
import UIKit
import RxSwift
import RxCocoa
import RxDataSources
class SearchResultsController: ViewController {
let searchTopBar: SearchTopBar = {
let searchTopBar = SearchTopBar.init()
return searchTopBar
}()
let searchNoDataView: SearchNoDataView = {
let searchNoDataView = SearchNoDataView.init()
return searchNoDataView
}()
let searchResultsView: SearchResultsView = {
let searchResultsView = SearchResultsView.init()
return searchResultsView
}()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func makeUI() {
super.makeUI()
view.addSubview(searchTopBar)
view.addSubview(searchNoDataView)
view.addSubview(searchResultsView)
}
override func bindViewModel() {
super.bindViewModel()
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
searchTopBar.snp.makeConstraints { make in
make.left.equalTo(view)
make.right.equalTo(view)
make.top.equalTo(view).offset(BaseDimensions.statusBarHeight + 15)
make.height.equalTo(40)
}
searchNoDataView.snp.makeConstraints { make in
make.centerX.equalTo(view)
make.top.equalTo(searchTopBar.snp.bottom).offset(45)
}
searchResultsView.snp.makeConstraints { make in
make.left.equalTo(view)
make.right.equalTo(view)
make.top.equalTo(searchTopBar.snp.bottom).offset(24)
make.bottom.equalTo(view)
}
}
}
class SearchTopBar: UIView {
let searchControl: SearchControl = {
let searchControl = SearchControl.init()
return searchControl
}()
let cancelButton: UIButton = {
let cancelButton = UIButton.init()
cancelButton.titleLabel?.font = UIFont.systemFont(ofSize: 17, weight: .medium)
cancelButton.setTitle("取消", for: .normal)
return cancelButton
}()
override init(frame: CGRect) {
super.init(frame: frame)
makeUI()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func makeUI() {
addSubview(searchControl)
addSubview(cancelButton)
}
override func layoutSubviews() {
super.layoutSubviews()
cancelButton.snp.makeConstraints { make in
make.right.equalTo(self).offset(-18)
make.centerY.equalTo(self)
}
searchControl.snp.makeConstraints { make in
make.left.equalTo(self).offset(18)
make.centerY.equalTo(self)
make.right.equalTo(cancelButton.snp.left).offset(-12)
}
}
}
class SearchNoDataView: UIView {
let titleLabel: UILabel = {
let titleLabel = UILabel.init()
titleLabel.font = UIFont.systemFont(ofSize: 15)
titleLabel.textColor = .init(hex: 0x000000, alpha: 0.6)
titleLabel.text = "暂无搜索内容"
return titleLabel
}()
override init(frame: CGRect) {
super.init(frame: frame)
makeUI()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func makeUI() {
addSubview(titleLabel)
}
override func layoutSubviews() {
super.layoutSubviews()
titleLabel.snp.makeConstraints { make in
make.center.equalTo(self)
}
}
}
class SearchResultsView: UIView {
lazy var segmentControl: SegmentControl = {
let segmentControl = SegmentControl.init()
segmentControl.items = ["单曲", "期刊"]
segmentControl.font = UIFont.systemFont(ofSize: 15)
segmentControl.selectedFont = UIFont.systemFont(ofSize: 15)
return segmentControl
}()
let tableView: UITableView = {
let tableView = UITableView.init()
return tableView
}()
let collectionView: UICollectionView = {
let collectionView = UICollectionView.init()
collectionView.isHidden = true
return collectionView
}()
var currentSearchType: SearchType = .single {
didSet {
switch currentSearchType {
case .single:
collectionView.isHidden = true
tableView.isHidden = false
case .journal:
collectionView.isHidden = false
tableView.isHidden = true
}
}
}
override init(frame: CGRect) {
super.init(frame: frame)
makeUI()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func makeUI() {
addSubview(segmentControl)
addSubview(tableView)
addSubview(collectionView)
}
override func layoutSubviews() {
super.layoutSubviews()
segmentControl.snp.makeConstraints { make in
make.left.equalTo(self).offset(18)
make.top.equalTo(self).offset(0)
}
tableView.snp.makeConstraints { make in
make.left.equalTo(self)
make.right.equalTo(self)
make.top.equalTo(segmentControl.snp.bottom).offset(24)
make.bottom.equalTo(self)
}
collectionView.snp.makeConstraints { make in
make.left.equalTo(self)
make.right.equalTo(self)
make.top.equalTo(segmentControl.snp.bottom).offset(24)
make.bottom.equalTo(self)
}
}
}
extension SearchResultsView {
static func dataSource() -> RxCollectionViewSectionedReloadDataSource<MusicStyleSection> {
return RxCollectionViewSectionedReloadDataSource<MusicStyleSection>(
configureCell: { dataSource, collectionView, indexPath, item in
// cell
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MusicStyleCellView", for: indexPath)
// cell
return cell
}
)
}
}
extension SearchResultsView {
//TODO
static func dataSource() -> RxTableViewSectionedReloadDataSource<JournalSection> {
return RxTableViewSectionedReloadDataSource<JournalSection>(
configureCell: { dataSource, tableView, indexPath, item in
let cell: SongViewCell = tableView.dequeueReusableCell(withIdentifier: "SongViewCell", for: indexPath) as! SongViewCell
cell.audio = item
return cell
}
)
}
}

@ -6,8 +6,27 @@
//
import UIKit
import RxSwift
import RxCocoa
import RxDataSources
class SearchViewController: ViewController, UIScrollViewDelegate {
let collectionView: UICollectionView = {
let layout = UICollectionViewFlowLayout()
layout.itemSize = CGSize(width: (BaseDimensions.screenWidth - 18 * 2 - 15) / 2, height: 88)
let collectionView = UICollectionView.init(frame: CGRect.zero, collectionViewLayout: layout)
collectionView.register(SearchHeaderView.self, forSupplementaryViewOfKind: "UICollectionElementKindSectionHeader", withReuseIdentifier: "SearchHeaderView")
if let layout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout {
layout.headerReferenceSize = CGSize(width: collectionView.frame.width, height: 128) // header
}
return collectionView
}()
class SearchViewController: ViewController {
override func viewDidLoad() {
super.viewDidLoad()
@ -16,4 +35,204 @@ class SearchViewController: ViewController {
}
override func makeUI() {
super.makeUI()
collectionView.rx.setDelegate(self)
view.addSubview(collectionView)
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
collectionView.snp.makeConstraints { make in
make.edges.equalTo(view)
}
}
}
extension SearchViewController {
static func dataSource() -> RxCollectionViewSectionedReloadDataSource<SearchSection> {
return RxCollectionViewSectionedReloadDataSource<SearchSection>(
configureCell: { dataSource, collectionView, indexPath, item in
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "SearchViewCell", for: indexPath)
return cell
},
configureSupplementaryView: { dataSource, collectionView, kind, indexPath in
guard kind == UICollectionView.elementKindSectionHeader else {
return UICollectionReusableView()
}
let section = dataSource[indexPath.section]
let resuableView = collectionView.dequeueReusableSupplementaryView(ofKind: "UICollectionElementKindSectionHeader", withReuseIdentifier: "SearchHeaderView", for: indexPath) as! SearchHeaderView
return resuableView
}
)
}
}
class SearchViewCell: UICollectionViewCell {
let backgroudnView: UIImageView = {
let backgroudnView = UIImageView.init()
backgroudnView.layer.cornerRadius = 8
backgroudnView.layer.masksToBounds = true
return backgroudnView
}()
let titleLabel: UILabel = {
let titleLabel = UILabel.init()
titleLabel.font = UIFont.systemFont(ofSize: 17)
titleLabel.textColor = .init(hex: 0xFFFFFF, alpha: 1)
return titleLabel
}()
let subTitleLabel: UILabel = {
let subTitleLabel = UILabel.init()
subTitleLabel.font = UIFont.systemFont(ofSize: 14)
subTitleLabel.textColor = .init(hex: 0xFFFFFF, alpha: 0.6)
return subTitleLabel
}()
override init(frame: CGRect) {
super.init(frame: frame)
makeUI()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func makeUI() {
contentView.addSubview(backgroudnView)
contentView.addSubview(titleLabel)
contentView.addSubview(subTitleLabel)
backgroudnView.snp.makeConstraints { make in
make.edges.equalTo(self)
}
titleLabel.snp.makeConstraints { make in
make.top.equalTo(backgroudnView).offset(13)
make.left.equalTo(backgroudnView).offset(17)
make.right.equalTo(backgroudnView).offset(-17)
}
subTitleLabel.snp.makeConstraints { make in
make.left.equalTo(backgroudnView).offset(17)
make.right.equalTo(backgroudnView).offset(-17)
make.top.equalTo(titleLabel.snp.bottom).offset(5)
}
}
}
class SearchHeaderView: UICollectionReusableView {
let titleLabel: UILabel = {
let titleLabel = UILabel.init()
titleLabel.font = UIFont.systemFont(ofSize: 28)
titleLabel.text = "搜索"
return titleLabel
}()
let searchControl: SearchControl = {
let searchControl = SearchControl.init()
return searchControl
}()
override init(frame: CGRect) {
super.init(frame: frame)
makeUI()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func makeUI() {
addSubview(titleLabel)
addSubview(searchControl)
}
override func layoutSubviews() {
super.layoutSubviews()
titleLabel.snp.makeConstraints { make in
make.left.equalTo(self).offset(18)
make.top.equalTo(self).offset(18)
}
searchControl.snp.makeConstraints { make in
make.left.equalTo(self).offset(18)
make.right.equalTo(self).offset(-18)
make.top.equalTo(titleLabel.snp.bottom).offset(12)
make.height.equalTo(40)
make.bottom.equalTo(self).offset(-9)
}
}
}
class SearchControl: UIControl {
let iconView: UIImageView = {
let iconView = UIImageView.init()
iconView.image = UIImage.init(named: "search_bar_icon")
return iconView
}()
let textField: UITextField = {
let textField = UITextField.init()
textField.font = UIFont.systemFont(ofSize: 15)
textField.placeholder = "输入期刊/歌曲名"
return textField
}()
override init(frame: CGRect) {
super.init(frame: frame)
makeUI()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func makeUI() {
addSubview(iconView)
addSubview(textField)
}
override func layoutSubviews() {
super.layoutSubviews()
iconView.snp.makeConstraints { make in
make.left.equalTo(self).offset(15)
make.centerY.equalTo(self)
}
textField.snp.makeConstraints { make in
make.right.equalTo(self).offset(-15)
make.left.equalTo(iconView.snp.right).offset(6)
make.centerY.equalTo(self)
}
}
}

@ -0,0 +1,163 @@
//
// AboutViewController.swift
// IndieMusic
//
// Created by WenLei on 2024/1/2.
//
import UIKit
import RxSwift
import RxCocoa
import RxDataSources
class AboutViewController: TableViewController {
let headerView: EditInfoHeaderView = {
let headerView = EditInfoHeaderView.init(frame: CGRect.init(x: 0, y: 0, width: BaseDimensions.screenWidth, height: 191))
return headerView
}()
let abloutFooterView: AbloutFooterView = {
let abloutFooterView = AbloutFooterView.init()
return abloutFooterView
}()
override func viewDidLoad() {
super.viewDidLoad()
}
override func makeUI() {
super.makeUI()
view.backgroundColor = .blue
tableView.register(MineViewCell.self, forCellReuseIdentifier: "SettingViewCell")
tableView.tableHeaderView = headerView
view.addSubview(abloutFooterView)
}
override func bindViewModel() {
super.bindViewModel()
guard let viewModel = viewModel as? MineViewModel else { return }
let input = MineViewModel.Input.init(viewWillAppear: rx.viewWillAppear,
selection: tableView.rx.itemSelected.asDriver())
let output = viewModel.transform(input: input)
let dataSource = MineViewController.dataSource()
output.items.bind(to: tableView.rx.items(dataSource: dataSource)).disposed(by: rx.disposeBag)
output.itemSelected.subscribe { sectionItem in
}.disposed(by: rx.disposeBag)
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
abloutFooterView.snp.makeConstraints { make in
make.bottom.equalTo(view).offset(-BaseDimensions.bottomHeight)
make.left.equalTo(view)
make.right.equalTo(view)
}
}
}
extension AboutViewController {
static func dataSource() -> RxTableViewSectionedReloadDataSource<MineSection> {
return RxTableViewSectionedReloadDataSource<MineSection>(
configureCell: { dataSource, tableView, indexPath, item in
let cell: MineViewCell = tableView.dequeueReusableCell(withIdentifier: "SettingViewCell", for: indexPath) as! MineViewCell
cell.titleLabel.text = "123"
cell.detailLabel.text = "321"
return cell
}
)
}
}
class AbloutFooterView: UIView, UITextViewDelegate {
let textView: UITextView = {
let textView = UITextView.init()
textView.addAttributed(attributedes: [("服务条款 ", [NSAttributedString.Key.foregroundColor: UIColor.primary(), NSAttributedString.Key.link: URL.init(string: Configs.App.aggrementUrl) ?? ""]),
(" 版权声明 ", [NSAttributedString.Key.foregroundColor: UIColor.primary(), NSAttributedString.Key.link: URL.init(string: Configs.App.aggrementUrl) ?? ""]),
(" 许可协议", [NSAttributedString.Key.foregroundColor: UIColor.primary(), NSAttributedString.Key.link: URL.init(string: Configs.App.aggrementUrl) ?? ""])
])
return textView
}()
override init(frame: CGRect) {
super.init(frame: frame)
makeUI()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func makeUI() {
addSubview(textView)
}
override func layoutSubviews() {
super.layoutSubviews()
textView.snp.makeConstraints { make in
make.edges.equalTo(self).offset(18)
}
}
func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool {
switch URL.scheme {
case Configs.App.aggrementUrl:
return false
// case Configs.App.aggrementUrl:
// break
// case Configs.App.aggrementUrl:
// break
default:
return true
}
}
@available(iOS 17.0, *)
func textView(_ textView: UITextView, menuConfigurationFor textItem: UITextItem, defaultMenu: UIMenu) -> UITextItem.MenuConfiguration? {
if case .link(let url) = textItem.content {
print("menu \(url)")
return nil
}
return .init(menu: defaultMenu)
}
}

@ -0,0 +1,19 @@
//
// AccountViewController.swift
// IndieMusic
//
// Created by WenLei on 2024/1/1.
//
import UIKit
class AccountViewController: TableViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
}

@ -0,0 +1,78 @@
//
// AccountViewModel.swift
// IndieMusic
//
// Created by WenLei on 2024/1/1.
//
import Foundation
import RxSwift
import RxCocoa
import RxDataSources
class AccountViewModel: ViewModel, ViewModelType {
struct Input {
let viewWillAppear: ControlEvent<Bool>
let selection: Driver<IndexPath>
}
struct Output {
let items: BehaviorRelay<[SettingSection]>
let selection: Driver<IndexPath>
let itemSelected: PublishSubject<Setting>
}
let itemSelected = PublishSubject<Setting>()
let items = BehaviorRelay<[SettingSection]>.init(value: [])
func transform(input: Input) -> Output {
input.viewWillAppear.subscribe { (_) in
}.disposed(by: rx.disposeBag)
let phone = Setting.init(title: "手机号", detail: "去绑定", arrowIcon: "setting_arrow")
let wechatBinding = Setting.init(title: "绑定微信", detail: "", arrowIcon: "setting_arrow")
let privacy = Setting.init(title: "注销账户", detail: "", arrowIcon: "setting_arrow")
//TODO
items.accept([SettingSection.init(items: [.setting(phone), .setting(wechatBinding), .setting(privacy)])])
input.selection.drive { indexPath in
guard let sectionItem = self.items.value.first?.items[indexPath.row] else { return }
switch sectionItem {
case .about(let setting):
// case .account(let setting):
// case .privacy(let setting):
// case .timing(let setting):
// case .cache(let setting):
// case .permission(let setting):
// case .feedback(let setting):
// case .about(let setting):
// case .contributors(let setting):
// case .version(let setting):
self.itemSelected.onNext(setting)
default: break
}
}.disposed(by: rx.disposeBag)
return Output.init(items: items,
selection: input.selection,
itemSelected: itemSelected)
}
}

@ -0,0 +1,176 @@
//
// CacheViewController.swift
// IndieMusic
//
// Created by WenLei on 2024/1/2.
//
import UIKit
class CacheViewController: TableViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
}
class CacheViewCell: UITableViewCell {
let titleLabel: UILabel = {
let titleLabel = UILabel.init()
titleLabel.font = UIFont.systemFont(ofSize: 12)
titleLabel.textColor = .init(hex: 0x000000)
return titleLabel
}()
let detaileLabel: UILabel = {
let detaileLabel = UILabel.init()
detaileLabel.font = .systemFont(ofSize: 18)
return detaileLabel
}()
let actionButton: UIButton = {
let actionButton = UIButton.init()
return actionButton
}()
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
makeUI()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func makeUI() {
contentView.addSubview(titleLabel)
contentView.addSubview(detaileLabel)
contentView.addSubview(actionButton)
actionButton.snp.makeConstraints { make in
make.right.equalTo(contentView).offset(-18)
make.centerY.equalTo(contentView)
}
titleLabel.snp.makeConstraints { make in
make.left.equalTo(contentView).offset(18)
make.top.equalTo(contentView).offset(18)
}
detaileLabel.snp.makeConstraints { make in
make.left.equalTo(titleLabel)
make.top.equalTo(titleLabel.snp.bottom).offset(1)
make.right.equalTo(actionButton.snp.left).offset(-18)
}
}
}
class CacheHeaderView: UIView {
private var progressLayer = CAShapeLayer()
private var trackLayer = CAShapeLayer()
let titleLabel: UILabel = {
let titleLabel = UILabel.init()
return titleLabel
}()
let contentLabel: UILabel = {
let contentLabel = UILabel.init()
return contentLabel
}()
let tipsLabel: UILabel = {
let tipsLabel = UILabel.init()
return tipsLabel
}()
override init(frame: CGRect) {
super.init(frame: frame)
createCircularPath()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
createCircularPath()
}
func makeUI() {
addSubview(titleLabel)
addSubview(contentLabel)
addSubview(tipsLabel)
}
override func layoutSubviews() {
super.layoutSubviews()
titleLabel.snp.makeConstraints { make in
make.centerX.equalTo(self)
make.top.equalTo(self).offset(52)
}
contentLabel.snp.makeConstraints { make in
make.centerX.equalTo(self)
make.left.equalTo(self).offset(10)
make.right.equalTo(self).offset(-10)
make.top.equalTo(titleLabel.snp.bottom).offset(8)
}
tipsLabel.snp.makeConstraints { make in
make.centerX.equalTo(self)
make.top.equalTo(contentLabel.snp.bottom).offset(3)
}
}
private func createCircularPath() {
self.backgroundColor = .clear
self.layer.cornerRadius = self.frame.size.width / 2
let circlePath = UIBezierPath(arcCenter: CGPoint(x: frame.size.width / 2, y: frame.size.height / 2), radius: (frame.size.width - 1.5) / 2, startAngle: CGFloat(-0.5 * .pi), endAngle: CGFloat(1.5 * .pi), clockwise: false)
trackLayer.path = circlePath.cgPath
trackLayer.fillColor = UIColor.clear.cgColor
trackLayer.strokeColor = UIColor.lightGray.cgColor
trackLayer.lineWidth = 5.0
trackLayer.strokeEnd = 1.0
layer.addSublayer(trackLayer)
progressLayer.path = circlePath.cgPath
progressLayer.fillColor = UIColor.clear.cgColor
progressLayer.strokeColor = UIColor.red.cgColor
progressLayer.lineWidth = 5.0
progressLayer.strokeEnd = 0.0
layer.addSublayer(progressLayer)
}
func setProgress(to progressConstant: CGFloat) {
progressLayer.strokeEnd = progressConstant
}
}

@ -0,0 +1,60 @@
//
// EditInfoView.swift
// IndieMusic
//
// Created by WenLei on 2024/1/1.
//
import UIKit
class EditInfoHeaderView: UIView {
let avatorView: UIImageView = {
let avatorView = UIImageView.init()
avatorView.layer.cornerRadius = 45
avatorView.layer.masksToBounds = true
return avatorView
}()
let tipsLabel: UILabel = {
let tipsLabel = UILabel.init()
tipsLabel.font = UIFont.systemFont(ofSize: 15)
tipsLabel.text = "点击更换头像"
tipsLabel.textColor = .tertiaryText()
return tipsLabel
}()
override init(frame: CGRect) {
super.init(frame: frame)
makeUI()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func makeUI() {
addSubview(avatorView)
addSubview(tipsLabel)
}
override func layoutSubviews() {
super.layoutSubviews()
avatorView.snp.makeConstraints { make in
make.centerX.equalTo(self)
make.top.equalTo(self).offset(31)
make.size.equalTo(CGSize.init(width: 90, height: 90))
}
tipsLabel.snp.makeConstraints { make in
make.centerX.equalTo(self)
make.top.equalTo(avatorView.snp.bottom).offset(15)
}
}
}

@ -0,0 +1,76 @@
//
// EditInfoViewController.swift
// IndieMusic
//
// Created by WenLei on 2024/1/1.
//
import UIKit
import RxSwift
import RxCocoa
import RxDataSources
class EditInfoViewController: TableViewController {
let headerView: EditInfoHeaderView = {
let headerView = EditInfoHeaderView.init(frame: CGRect.init(x: 0, y: 0, width: BaseDimensions.screenWidth, height: 191))
return headerView
}()
override func viewDidLoad() {
super.viewDidLoad()
}
override func makeUI() {
super.makeUI()
view.backgroundColor = .blue
tableView.register(MineViewCell.self, forCellReuseIdentifier: "SettingViewCell")
tableView.tableHeaderView = headerView
}
override func bindViewModel() {
super.bindViewModel()
guard let viewModel = viewModel as? MineViewModel else { return }
let input = MineViewModel.Input.init(viewWillAppear: rx.viewWillAppear,
selection: tableView.rx.itemSelected.asDriver())
let output = viewModel.transform(input: input)
let dataSource = MineViewController.dataSource()
output.items.bind(to: tableView.rx.items(dataSource: dataSource)).disposed(by: rx.disposeBag)
output.itemSelected.subscribe { sectionItem in
}.disposed(by: rx.disposeBag)
}
}
extension EditInfoViewController {
static func dataSource() -> RxTableViewSectionedReloadDataSource<MineSection> {
return RxTableViewSectionedReloadDataSource<MineSection>(
configureCell: { dataSource, tableView, indexPath, item in
let cell: MineViewCell = tableView.dequeueReusableCell(withIdentifier: "SettingViewCell", for: indexPath) as! MineViewCell
cell.titleLabel.text = "123"
cell.detailLabel.text = "321"
return cell
}
)
}
}

@ -0,0 +1,79 @@
//
// EditInfoViewModel.swift
// IndieMusic
//
// Created by WenLei on 2024/1/1.
//
import Foundation
import RxSwift
import RxCocoa
import RxDataSources
class EditInfoViewModel: ViewModel, ViewModelType {
struct Input {
let viewWillAppear: ControlEvent<Bool>
let selection: Driver<IndexPath>
}
struct Output {
let items: BehaviorRelay<[SettingSection]>
let selection: Driver<IndexPath>
let itemSelected: PublishSubject<Setting>
}
let itemSelected = PublishSubject<Setting>()
let items = BehaviorRelay<[SettingSection]>.init(value: [])
func transform(input: Input) -> Output {
input.viewWillAppear.subscribe { (_) in
}.disposed(by: rx.disposeBag)
let name = Setting.init(title: "用户名", detail: "", arrowIcon: "")
let slogn = Setting.init(title: "签名", detail: "", arrowIcon: "")
let birthDay = Setting.init(title: "生日", detail: "", arrowIcon: "")
let sex = Setting.init(title: "性别", detail: "", arrowIcon: "")
items.accept([SettingSection.init(items: [.setting(name), .setting(slogn), .setting(birthDay), .setting(sex)])])
input.selection.drive { indexPath in
guard let sectionItem = self.items.value.first?.items[indexPath.row] else { return }
switch sectionItem {
case .about(let setting):
// case .account(let setting):
// case .privacy(let setting):
// case .timing(let setting):
// case .cache(let setting):
// case .permission(let setting):
// case .feedback(let setting):
// case .about(let setting):
// case .contributors(let setting):
// case .version(let setting):
self.itemSelected.onNext(setting)
default: break
}
}.disposed(by: rx.disposeBag)
return Output.init(items: items,
selection: input.selection,
itemSelected: itemSelected)
}
}

@ -0,0 +1,80 @@
//
// EditNameController.swift
// IndieMusic
//
// Created by WenLei on 2024/1/1.
//
import UIKit
class EditNameController: ViewController {
let editNameTextField: EditNameTextField = {
let editNameTextField = EditNameTextField.init(frame: CGRect.init(x: 0, y: 0, width: BaseDimensions.screenWidth, height: 52))
return editNameTextField
}()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func makeUI() {
super.makeUI()
view.addSubview(editNameTextField)
}
}
class EditNameTextField: UIView {
let textFieldView: UITextField = {
let textFieldView = UITextField.init()
return textFieldView
}()
let countTipsLabel: UILabel = {
let countTipsLabel = UILabel.init()
countTipsLabel.font = UIFont.systemFont(ofSize: 15)
return countTipsLabel
}()
override init(frame: CGRect) {
super.init(frame: frame)
makeUI()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func makeUI() {
addSubview(textFieldView)
addSubview(countTipsLabel)
}
override func layoutSubviews() {
super.layoutSubviews()
countTipsLabel.snp.makeConstraints { make in
make.right.equalTo(self).offset(-18)
make.centerY.equalTo(self)
}
textFieldView.snp.makeConstraints { make in
make.left.equalTo(self).offset(18)
make.right.equalTo(countTipsLabel.snp.left).offset(-18)
make.centerY.equalTo(self)
}
}
}

@ -0,0 +1,329 @@
//
// FeedbackViewController.swift
// IndieMusic
//
// Created by WenLei on 2024/1/1.
//
import UIKit
class FeedbackViewController: ViewController {
let feedbackTypeView: FeedbackTypeView = {
let feedbackTypeView = FeedbackTypeView.init()
return feedbackTypeView
}()
let feedbackDetailView: FeedbackDetailView = {
let feedbackDetailView = FeedbackDetailView.init()
return feedbackDetailView
}()
let feedbackContactView: FeedbackContactView = {
let feedbackContactView = FeedbackContactView.init()
return feedbackContactView
}()
let confirmButton: UIButton = {
let confirmButton = UIButton.init()
confirmButton.setTitle("提交", for: .normal)
confirmButton.titleLabel?.font = UIFont.systemFont(ofSize: 15)
confirmButton.backgroundColor = .init(hex: 0x000000)
return confirmButton
}()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func makeUI() {
super.makeUI()
view.addSubview(feedbackTypeView)
view.addSubview(feedbackDetailView)
view.addSubview(feedbackContactView)
view.addSubview(confirmButton)
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
feedbackTypeView.snp.makeConstraints { make in
make.left.equalTo(view)
make.right.equalTo(view)
make.top.equalTo(view)
}
feedbackDetailView.snp.makeConstraints { make in
make.left.equalTo(view)
make.right.equalTo(view)
make.top.equalTo(feedbackTypeView.snp.bottom)
}
feedbackContactView.snp.makeConstraints { make in
make.left.equalTo(view)
make.right.equalTo(view)
make.top.equalTo(feedbackDetailView.snp.bottom)
}
confirmButton.snp.makeConstraints { make in
make.left.equalTo(view)
make.right.equalTo(view)
make.top.equalTo(feedbackContactView.snp.bottom).offset(30)
make.height.equalTo(44)
}
}
}
class FeedbackTypeView: UIView {
let titleLabel: UILabel = {
let titleLabel = UILabel.init()
return titleLabel
}()
let feedbackTypeControl: FeedbackTypeControl = {
let feedbackTypeControl = FeedbackTypeControl.init()
return feedbackTypeControl
}()
override init(frame: CGRect) {
super.init(frame: frame)
makeUI()
}
func makeUI() {
addSubview(titleLabel)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
}
}
class FeedbackTypeControl: UIControl {
let titleLabel: UILabel = {
let titleLabel = UILabel.init()
titleLabel.font = UIFont.systemFont(ofSize: 15)
return titleLabel
}()
let detailLabel: UILabel = {
let detailLabel = UILabel.init()
detailLabel.font = .systemFont(ofSize: 15)
return detailLabel
}()
let arrowView: UIImageView = {
let arrowView = UIImageView .init()
arrowView.image = UIImage.init(named: "")
return arrowView
}()
override init(frame: CGRect) {
super.init(frame: frame)
makeUI()
}
func makeUI() {
addSubview(titleLabel)
addSubview(detailLabel)
addSubview(arrowView)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
arrowView.snp.makeConstraints { make in
make.right.equalTo(self)
make.centerY.equalTo(self)
}
detailLabel.snp.makeConstraints { make in
make.right.equalTo(arrowView.snp.left).offset(-18)
make.centerY.equalTo(self)
}
titleLabel.snp.makeConstraints { make in
make.left.equalTo(self).offset(18)
make.top.equalTo(self).offset(12)
make.width.equalTo(100)
}
}
}
class FeedbackDetailView: UIView {
let titleLabel: UILabel = {
let titleLabel = UILabel.init()
titleLabel.font = UIFont.systemFont(ofSize: 15)
return titleLabel
}()
let feedbackDetailSubView: FeedbackDetailSubView = {
let feedbackDetailSubView = FeedbackDetailSubView.init()
return feedbackDetailSubView
}()
override init(frame: CGRect) {
super.init(frame: frame)
makeUI()
}
func makeUI() {
addSubview(titleLabel)
addSubview(feedbackDetailSubView)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
}
}
class FeedbackDetailSubView: UIView {
let textView: UITextView = {
let textView = UITextView.init()
return textView
}()
let countLabel: UILabel = {
let countLabel = UILabel.init()
countLabel.font = UIFont.systemFont(ofSize: 14)
return countLabel
}()
// TODO:
override init(frame: CGRect) {
super.init(frame: frame)
makeUI()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func makeUI() {
addSubview(textView)
addSubview(countLabel)
}
override func layoutSubviews() {
super.layoutSubviews()
textView.snp.makeConstraints { make in
make.left.equalTo(self)
make.right.equalTo(self)
make.top.equalTo(self)
}
countLabel.snp.makeConstraints { make in
make.right.equalTo(self).offset(-12)
make.top.equalTo(textView.snp.bottom).offset(20)
}
}
}
class FeedbackContactView: UIView {
let titleLabel: UILabel = {
let titleLabel = UILabel.init()
titleLabel.font = UIFont.systemFont(ofSize: 15)
return titleLabel
}()
let textFieldView: UITextField = {
let textFieldView = UITextField.init()
textFieldView.font = UIFont.systemFont(ofSize: 15)
textFieldView.placeholder = "手机/邮箱"
return textFieldView
}()
override init(frame: CGRect) {
super.init(frame: frame)
makeUI()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func makeUI() {
addSubview(titleLabel)
addSubview(textFieldView)
}
override func layoutSubviews() {
super.layoutSubviews()
titleLabel.snp.makeConstraints { make in
make.left.equalTo(self).offset(18)
make.top.equalTo(self).offset(12)
}
textFieldView.snp.makeConstraints { make in
make.left.equalTo(self).offset(18)
make.right.equalTo(self).offset(-18)
make.top.equalTo(titleLabel.snp.bottom).offset(9)
make.height.equalTo(45)
}
}
}

@ -0,0 +1,23 @@
//
// PrivacyViewController.swift
// IndieMusic
//
// Created by WenLei on 2024/1/2.
//
import UIKit
class PrivacyViewController: TableViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
override func makeUI() {
super.makeUI()
}
}

@ -0,0 +1,111 @@
//
// SettingView.swift
// IndieMusic
//
// Created by WenLei on 2024/1/1.
//
import UIKit
class SettingViewCell: UITableViewCell {
let titleLabel: UILabel = {
let titleLabel = UILabel.init()
titleLabel.font = .systemFont(ofSize: 15)
return titleLabel
}()
let detailLabel: UILabel = {
let detailLabel = UILabel.init()
detailLabel.font = UIFont.systemFont(ofSize: 15)
detailLabel.textColor = .secondaryText()
return detailLabel
}()
let arrowView: UIImageView = {
let arrowView = UIImageView.init()
arrowView.image = UIImage.init(named: "setting_arrow")
return arrowView
}()
let switchButton: UISwitch = {
let switchButton = UISwitch.init()
switchButton.isHidden = true
return switchButton
}()
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func makeUI() {
contentView.addSubview(titleLabel)
contentView.addSubview(detailLabel)
contentView.addSubview(arrowView)
contentView.addSubview(switchButton)
arrowView.snp.makeConstraints { make in
make.right.equalTo(contentView).offset(-18)
make.centerY.equalTo(contentView)
}
detailLabel.snp.makeConstraints { make in
make.right.equalTo(arrowView.snp.left).offset(2)
make.centerY.equalTo(contentView)
}
titleLabel.snp.makeConstraints { make in
make.left.equalTo(contentView).offset(18)
make.centerY.equalTo(contentView)
make.right.equalTo(detailLabel.snp.left).offset(-18)
}
switchButton.snp.makeConstraints { make in
make.right.equalTo(arrowView.snp.left).offset(2)
make.centerY.equalTo(contentView)
}
}
}
class SettingViewFooterView: UIView {
let logoutButton: UIButton = {
let logoutButton = UIButton.init()
logoutButton.titleLabel?.font = UIFont.systemFont(ofSize: 15)
logoutButton.setTitle("退出登录", for: .normal)
return logoutButton
}()
override init(frame: CGRect) {
super.init(frame: frame)
addSubview(logoutButton)
logoutButton.snp.makeConstraints { make in
make.edges.equalTo(self)
}
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}

@ -0,0 +1,77 @@
//
// SettingViewController.swift
// IndieMusic
//
// Created by WenLei on 2024/1/1.
//
import UIKit
import RxSwift
import RxCocoa
import RxDataSources
class SettingViewController: TableViewController {
let footerView: SettingViewFooterView = {
let footerView = SettingViewFooterView.init(frame: CGRect.init(x: 0, y: 0, width: BaseDimensions.screenWidth, height: 52))
return footerView
}()
override func viewDidLoad() {
super.viewDidLoad()
}
override func makeUI() {
super.makeUI()
view.backgroundColor = .blue
tableView.register(MineViewCell.self, forCellReuseIdentifier: "SettingViewCell")
tableView.tableFooterView = footerView
}
override func bindViewModel() {
super.bindViewModel()
guard let viewModel = viewModel as? MineViewModel else { return }
let input = MineViewModel.Input.init(viewWillAppear: rx.viewWillAppear,
selection: tableView.rx.itemSelected.asDriver())
let output = viewModel.transform(input: input)
let dataSource = MineViewController.dataSource()
output.items.bind(to: tableView.rx.items(dataSource: dataSource)).disposed(by: rx.disposeBag)
output.itemSelected.subscribe { sectionItem in
}.disposed(by: rx.disposeBag)
}
}
extension SettingViewController {
static func dataSource() -> RxTableViewSectionedReloadDataSource<MineSection> {
return RxTableViewSectionedReloadDataSource<MineSection>(
configureCell: { dataSource, tableView, indexPath, item in
let cell: MineViewCell = tableView.dequeueReusableCell(withIdentifier: "SettingViewCell", for: indexPath) as! MineViewCell
cell.titleLabel.text = "123"
cell.detailLabel.text = "321"
return cell
}
)
}
}

@ -0,0 +1,89 @@
//
// SettingViewMdel.swift
// IndieMusic
//
// Created by WenLei on 2024/1/1.
//
import Foundation
import RxSwift
import RxCocoa
import RxDataSources
class SettingViewMdel: ViewModel, ViewModelType {
struct Input {
let viewWillAppear: ControlEvent<Bool>
let selection: Driver<IndexPath>
}
struct Output {
let items: BehaviorRelay<[SettingSection]>
let selection: Driver<IndexPath>
let itemSelected: PublishSubject<Setting>
}
let itemSelected = PublishSubject<Setting>()
let items = BehaviorRelay<[SettingSection]>.init(value: [])
func transform(input: Input) -> Output {
input.viewWillAppear.subscribe { (_) in
}.disposed(by: rx.disposeBag)
let editInfo = Setting.init(title: "编辑资料", detail: "", arrowIcon: "setting_arrow")
let account = Setting.init(title: "账户与安全", detail: "", arrowIcon: "setting_arrow")
let privacy = Setting.init(title: "消息和隐私设置", detail: "", arrowIcon: "setting_arrow")
let timing = Setting.init(title: "定时关闭", detail: "", arrowIcon: "setting_arrow")
let cache = Setting.init(title: "清理缓存", detail: "", arrowIcon: "setting_arrow")
let permission = Setting.init(title: "个人信息与权限", detail: "", arrowIcon: "setting_arrow")
let feedback = Setting.init(title: "意见反馈", detail: "", arrowIcon: "setting_arrow")
let about = Setting.init(title: "关于雀乐", detail: "", arrowIcon: "setting_arrow")
let contributors = Setting.init(title: "贡献者名单", detail: "", arrowIcon: "setting_arrow")
let version = Setting.init(title: "检查版本", detail: "", arrowIcon: "setting_arrow")
items.accept([SettingSection.init(items: [.editInfo(editInfo), .account(account), .privacy(privacy)])])
input.selection.drive { indexPath in
guard let sectionItem = self.items.value.first?.items[indexPath.row] else { return }
switch sectionItem {
case .about(let setting):
// case .account(let setting):
// case .privacy(let setting):
// case .timing(let setting):
// case .cache(let setting):
// case .permission(let setting):
// case .feedback(let setting):
// case .about(let setting):
// case .contributors(let setting):
// case .version(let setting):
self.itemSelected.onNext(setting)
default: break
}
}.disposed(by: rx.disposeBag)
return Output.init(items: items,
selection: input.selection,
itemSelected: itemSelected)
}
}

@ -0,0 +1,114 @@
//
// ThanksViewController.swift
// IndieMusic
//
// Created by WenLei on 2024/1/1.
//
import UIKit
class ThanksViewController: ViewController {
let headerView: ThanksHeaderView = {
let headerView = ThanksHeaderView.init()
return headerView
}()
let collectionView: UICollectionView = {
let collectionView = UICollectionView.init()
return collectionView
}()
let confirmButton: UIButton = {
let confirmButton = UIButton.init()
confirmButton.setTitle("成为贡献者", for: .normal)
confirmButton.titleLabel?.font = UIFont.systemFont(ofSize: 15)
confirmButton.backgroundColor = .init(hex: 0xAD3030)
return confirmButton
}()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func makeUI() {
super.makeUI()
view.addSubview(collectionView)
view.addSubview(confirmButton)
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
collectionView.snp.makeConstraints { make in
make.edges.equalTo(view)
}
confirmButton.snp.makeConstraints { make in
make.centerX.equalTo(view)
make.bottom.equalTo(view).offset(-BaseDimensions.bottomHeight - 10)
}
}
}
class ThanksHeaderView: UIView {
let titleImageView: UIImageView = {
let titleImageView = UIImageView.init(image: UIImage.init(named: ""))
return titleImageView
}()
let titleLabel: UILabel = {
let titleLabel = UILabel.init()
titleLabel.text = "这些年里,我们依旧在那些得到与失去中彳亍前行,虽然各有各的人生困苦,却不及此刻重逢的欢愉。值得欣慰的是,总有人正年轻、总有人在歌唱、总有人怀揣梦想、总有人奔赴向前、总有那些音乐陪伴着我们。感谢所有曾经在黑夜中给予我们孤独的灵魂以安抚的声音,在内心荒漠的世界里。"
return titleLabel
}()
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func makeUI() {
addSubview(titleImageView)
addSubview(titleLabel)
}
override func layoutSubviews() {
super.layoutSubviews()
titleImageView.snp.makeConstraints { make in
make.left.equalTo(self)
make.right.equalTo(self)
make.top.equalTo(self)
make.height.equalTo(100)//TODO
}
titleLabel.snp.makeConstraints { make in
make.left.equalTo(self).offset(25)
make.right.equalTo(self).offset(-25)
make.top.equalTo(titleImageView.snp.bottom).offset(10)//TODO
}
}
}

@ -0,0 +1,89 @@
//
// TimingViewController.swift
// IndieMusic
//
// Created by WenLei on 2024/1/1.
//
import UIKit
class TimingViewController: ViewController {
let titleLabel: UILabel = {
let titleLabel = UILabel.init()
titleLabel.font = UIFont.systemFont(ofSize: 15)
return titleLabel
}()
let switchControl: UIControl = {
let switchControl = UIControl.init()
return switchControl
}()
let collectionView: UICollectionView = {
let collectionView = UICollectionView.init()
return collectionView
}()
let button: UIButton = {
let button = UIButton.init()
button.setTitle("自定义", for: .normal)
button.titleLabel?.font = UIFont.systemFont(ofSize: 15)
return button
}()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func makeUI() {
super.makeUI()
view.addSubview(titleLabel)
view.addSubview(switchControl)
view.addSubview(collectionView)
view.addSubview(button)
}
override func bindViewModel() {
super.bindViewModel()
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
switchControl.snp.makeConstraints { make in
make.right.equalTo(view).offset(-18)
make.top.equalTo(view).offset(19)
}
titleLabel.snp.makeConstraints { make in
make.left.equalTo(view).offset(18)
make.top.equalTo(view).offset(24)
}
collectionView.snp.makeConstraints { make in
make.left.equalTo(view)
make.right.equalTo(view)
make.top.equalTo(view).offset(80)
}
button.snp.makeConstraints { make in
make.centerX.equalTo(view)
make.top.equalTo(collectionView.snp.bottom).offset(30)
}
}
}

@ -1,4 +0,0 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M20 12.5H3" stroke="#37373D" style="stroke:#37373D;stroke:color(display-p3 0.2157 0.2157 0.2392);stroke-opacity:1;" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M11.5 21L3 12.5L11.5 4" stroke="#37373D" style="stroke:#37373D;stroke:color(display-p3 0.2157 0.2157 0.2392);stroke-opacity:1;" stroke-width="1.5" stroke-linecap="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 477 B

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

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

@ -0,0 +1,5 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="12" cy="12" r="10" stroke="#C4C4CC" style="stroke:#C4C4CC;stroke:color(display-p3 0.7680 0.7680 0.8000);stroke-opacity:1;" stroke-width="1.5"/>
<rect x="8.5" y="8" width="2" height="8" rx="0.3" fill="#17171A" style="fill:#17171A;fill:color(display-p3 0.0902 0.0902 0.1020);fill-opacity:1;"/>
<rect x="13.5" y="8" width="2" height="8" rx="0.3" fill="#17171A" style="fill:#17171A;fill:color(display-p3 0.0902 0.0902 0.1020);fill-opacity:1;"/>
</svg>

After

Width:  |  Height:  |  Size: 556 B

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

@ -1,7 +1,7 @@
{
"images" : [
{
"filename" : "nav_back_btn.svg",
"filename" : "search_icon.svg",
"idiom" : "universal",
"scale" : "1x"
},

@ -0,0 +1,4 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M16.3549 18.0967L19.2581 20.9999" stroke="#17171A" style="stroke:#17171A;stroke:color(display-p3 0.0902 0.0902 0.1020);stroke-opacity:1;" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M11.129 3C6.64 3 3 6.64 3 11.129C3 15.6181 6.64 19.2581 11.129 19.2581C15.6181 19.2581 19.2581 15.6181 19.2581 11.129C19.2581 6.64 15.6181 3 11.129 3Z" stroke="#17171A" style="stroke:#17171A;stroke:color(display-p3 0.0902 0.0902 0.1020);stroke-opacity:1;" stroke-width="1.5" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 668 B

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

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

@ -0,0 +1,4 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="24" height="24" transform="translate(0 24) rotate(-90)" fill="white" style="fill:white;fill-opacity:1;"/>
<path d="M10 6L15 12L10 18" stroke="black" stroke-opacity="0.2" style="stroke:black;stroke-opacity:0.2;" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 395 B

Loading…
Cancel
Save