From c74e0d90414e012c92c19b3d54e0c85f56478044 Mon Sep 17 00:00:00 2001 From: wenlei Date: Tue, 2 Jan 2024 17:16:31 +0800 Subject: [PATCH] Search and setup interface preliminary build --- .../IndieMusic.xcodeproj/project.pbxproj | 108 ++++++ .../Common/NavigationController.swift | 25 +- .../IndieMusic/Common/ViewController.swift | 2 +- IndieMusic/IndieMusic/Models/Mine.swift | 54 +++ IndieMusic/IndieMusic/Models/MusicStyle.swift | 30 ++ IndieMusic/IndieMusic/Models/PersonInfo.swift | 17 + IndieMusic/IndieMusic/Models/Search.swift | 47 +++ IndieMusic/IndieMusic/Models/Setting.swift | 48 +++ .../Modules/Home/HomeTabBarController.swift | 1 + .../Modules/Home/HomeViewController.swift | 4 +- .../Modules/JournalDetail/CommentView.swift | 224 +++++++++++ .../JournalDetail/CommentViewController.swift | 53 +++ .../JournalDetail/JournalDetailView.swift | 1 - .../Modules/Mine/MineSingleController.swift | 66 ++++ .../Modules/Mine/MineSingleViewModel.swift | 54 +++ .../IndieMusic/Modules/Mine/MineView.swift | 355 ++++++++++++++++++ .../Modules/Mine/MineViewController.swift | 61 ++- .../Modules/Mine/MineViewModel.swift | 33 +- .../Search/MusicStyleViewController.swift | 320 ++++++++++++++++ .../Search/SearchResultsController.swift | 288 ++++++++++++++ .../Modules/Search/SearchViewController.swift | 221 ++++++++++- .../Modules/Setting/AboutViewController.swift | 163 ++++++++ .../Setting/AccountViewController.swift | 19 + .../Modules/Setting/AccountViewModel.swift | 78 ++++ .../Modules/Setting/CacheViewController.swift | 176 +++++++++ .../Modules/Setting/EditInfoView.swift | 60 +++ .../Setting/EditInfoViewController.swift | 76 ++++ .../Modules/Setting/EditInfoViewModel.swift | 79 ++++ .../Modules/Setting/EditNameController.swift | 80 ++++ .../Setting/FeedbackViewController.swift | 329 ++++++++++++++++ .../Setting/PrivacyViewController.swift | 23 ++ .../Modules/Setting/SettingView.swift | 111 ++++++ .../Setting/SettingViewController.swift | 77 ++++ .../Modules/Setting/SettingViewMdel.swift | 89 +++++ .../Setting/ThanksViewController.swift | 114 ++++++ .../Setting/TimingViewController.swift | 89 +++++ .../nav_back_btn.imageset/nav_back_btn.svg | 4 - .../Assets.xcassets/mine/Contents.json | 6 + .../mine/mine_play_btn.imageset/Contents.json | 21 ++ .../mine_play_btn.imageset/mine_play_btn.svg | 5 + .../Assets.xcassets/search/Contents.json | 6 + .../search_bar_icon.imageset}/Contents.json | 2 +- .../search_bar_icon.imageset/search_icon.svg | 4 + .../Assets.xcassets/setting/Contents.json | 6 + .../setting_arrow.imageset/Contents.json | 21 ++ .../setting_arrow.imageset/setting_arrow.svg | 4 + 46 files changed, 3623 insertions(+), 31 deletions(-) create mode 100644 IndieMusic/IndieMusic/Models/Mine.swift create mode 100644 IndieMusic/IndieMusic/Models/MusicStyle.swift create mode 100644 IndieMusic/IndieMusic/Models/PersonInfo.swift create mode 100644 IndieMusic/IndieMusic/Models/Search.swift create mode 100644 IndieMusic/IndieMusic/Models/Setting.swift create mode 100644 IndieMusic/IndieMusic/Modules/JournalDetail/CommentView.swift create mode 100644 IndieMusic/IndieMusic/Modules/JournalDetail/CommentViewController.swift create mode 100644 IndieMusic/IndieMusic/Modules/Mine/MineSingleController.swift create mode 100644 IndieMusic/IndieMusic/Modules/Mine/MineSingleViewModel.swift create mode 100644 IndieMusic/IndieMusic/Modules/Mine/MineView.swift create mode 100644 IndieMusic/IndieMusic/Modules/Search/MusicStyleViewController.swift create mode 100644 IndieMusic/IndieMusic/Modules/Search/SearchResultsController.swift create mode 100644 IndieMusic/IndieMusic/Modules/Setting/AboutViewController.swift create mode 100644 IndieMusic/IndieMusic/Modules/Setting/AccountViewController.swift create mode 100644 IndieMusic/IndieMusic/Modules/Setting/AccountViewModel.swift create mode 100644 IndieMusic/IndieMusic/Modules/Setting/CacheViewController.swift create mode 100644 IndieMusic/IndieMusic/Modules/Setting/EditInfoView.swift create mode 100644 IndieMusic/IndieMusic/Modules/Setting/EditInfoViewController.swift create mode 100644 IndieMusic/IndieMusic/Modules/Setting/EditInfoViewModel.swift create mode 100644 IndieMusic/IndieMusic/Modules/Setting/EditNameController.swift create mode 100644 IndieMusic/IndieMusic/Modules/Setting/FeedbackViewController.swift create mode 100644 IndieMusic/IndieMusic/Modules/Setting/PrivacyViewController.swift create mode 100644 IndieMusic/IndieMusic/Modules/Setting/SettingView.swift create mode 100644 IndieMusic/IndieMusic/Modules/Setting/SettingViewController.swift create mode 100644 IndieMusic/IndieMusic/Modules/Setting/SettingViewMdel.swift create mode 100644 IndieMusic/IndieMusic/Modules/Setting/ThanksViewController.swift create mode 100644 IndieMusic/IndieMusic/Modules/Setting/TimingViewController.swift delete mode 100644 IndieMusic/IndieMusic/Resources/Assets.xcassets/audio/nav_back_btn.imageset/nav_back_btn.svg create mode 100644 IndieMusic/IndieMusic/Resources/Assets.xcassets/mine/Contents.json create mode 100644 IndieMusic/IndieMusic/Resources/Assets.xcassets/mine/mine_play_btn.imageset/Contents.json create mode 100644 IndieMusic/IndieMusic/Resources/Assets.xcassets/mine/mine_play_btn.imageset/mine_play_btn.svg create mode 100644 IndieMusic/IndieMusic/Resources/Assets.xcassets/search/Contents.json rename IndieMusic/IndieMusic/Resources/Assets.xcassets/{audio/nav_back_btn.imageset => search/search_bar_icon.imageset}/Contents.json (87%) create mode 100644 IndieMusic/IndieMusic/Resources/Assets.xcassets/search/search_bar_icon.imageset/search_icon.svg create mode 100644 IndieMusic/IndieMusic/Resources/Assets.xcassets/setting/Contents.json create mode 100644 IndieMusic/IndieMusic/Resources/Assets.xcassets/setting/setting_arrow.imageset/Contents.json create mode 100644 IndieMusic/IndieMusic/Resources/Assets.xcassets/setting/setting_arrow.imageset/setting_arrow.svg diff --git a/IndieMusic/IndieMusic.xcodeproj/project.pbxproj b/IndieMusic/IndieMusic.xcodeproj/project.pbxproj index adb6ce2..26fe25e 100644 --- a/IndieMusic/IndieMusic.xcodeproj/project.pbxproj +++ b/IndieMusic/IndieMusic.xcodeproj/project.pbxproj @@ -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 = ""; }; 774A18112B07327C00F56DF1 /* CommentCountButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommentCountButton.swift; sourceTree = ""; }; 774A18132B07329600F56DF1 /* MultiUserAvatarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultiUserAvatarView.swift; sourceTree = ""; }; + 7751D34F2B42ABBF00F1F2BD /* SettingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingViewController.swift; sourceTree = ""; }; + 7751D3512B42AC2B00F1F2BD /* SettingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingView.swift; sourceTree = ""; }; + 7751D3532B42AE0E00F1F2BD /* SettingViewMdel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingViewMdel.swift; sourceTree = ""; }; + 7751D3552B42AE4600F1F2BD /* Setting.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Setting.swift; sourceTree = ""; }; + 7751D3572B42B5A200F1F2BD /* EditInfoViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditInfoViewController.swift; sourceTree = ""; }; + 7751D3592B42B5BD00F1F2BD /* EditInfoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditInfoView.swift; sourceTree = ""; }; + 7751D35B2B42B5E900F1F2BD /* EditInfoViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditInfoViewModel.swift; sourceTree = ""; }; + 7751D35D2B42B61100F1F2BD /* PersonInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PersonInfo.swift; sourceTree = ""; }; + 7751D35F2B42BA3D00F1F2BD /* EditNameController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditNameController.swift; sourceTree = ""; }; + 7751D3612B42BC0C00F1F2BD /* AccountViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountViewController.swift; sourceTree = ""; }; + 7751D3632B42BC2E00F1F2BD /* AccountViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountViewModel.swift; sourceTree = ""; }; + 7751D3652B42BE7F00F1F2BD /* FeedbackViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedbackViewController.swift; sourceTree = ""; }; + 7751D3672B42E96200F1F2BD /* ThanksViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThanksViewController.swift; sourceTree = ""; }; + 7751D3692B42ED6C00F1F2BD /* TimingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimingViewController.swift; sourceTree = ""; }; + 7751D36B2B439F0000F1F2BD /* AboutViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutViewController.swift; sourceTree = ""; }; + 7751D36D2B43A03E00F1F2BD /* PrivacyViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrivacyViewController.swift; sourceTree = ""; }; + 7751D36F2B43A4FC00F1F2BD /* CacheViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CacheViewController.swift; sourceTree = ""; }; + 7751D3712B43B9ED00F1F2BD /* Search.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Search.swift; sourceTree = ""; }; + 7751D3732B43C9FA00F1F2BD /* MusicStyleViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MusicStyleViewController.swift; sourceTree = ""; }; + 7751D3752B43E8D200F1F2BD /* MusicStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MusicStyle.swift; sourceTree = ""; }; + 7751D3772B43EA1200F1F2BD /* SearchResultsController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchResultsController.swift; sourceTree = ""; }; 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 = ""; }; 778B8A222AF8E36D0034AFD4 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; @@ -225,6 +273,12 @@ 77FA0B4B2B0EF8BB00404C5E /* LoginViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginViewModel.swift; sourceTree = ""; }; 77FA0B4D2B0EF8C700404C5E /* PhoneCodeViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhoneCodeViewModel.swift; sourceTree = ""; }; 77FA0B4F2B0EFEF400404C5E /* PhoneCodeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhoneCodeView.swift; sourceTree = ""; }; + 77FA0B512B0F3BC700404C5E /* MineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MineView.swift; sourceTree = ""; }; + 77FA0B532B0F447400404C5E /* Mine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Mine.swift; sourceTree = ""; }; + 77FA0B552B0F4ABF00404C5E /* MineSingleController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MineSingleController.swift; sourceTree = ""; }; + 77FA0B572B0F4C0800404C5E /* MineSingleViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MineSingleViewModel.swift; sourceTree = ""; }; + 77FA0B592B147EC900404C5E /* CommentViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommentViewController.swift; sourceTree = ""; }; + 77FA0B5B2B147EE800404C5E /* CommentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommentView.swift; sourceTree = ""; tabWidth = 14; }; 77FAF7612B07434A00FC2CA1 /* AudioMoreActionController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioMoreActionController.swift; sourceTree = ""; }; 77FAF7632B075FEB00FC2CA1 /* JournalDetailViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JournalDetailViewModel.swift; sourceTree = ""; }; 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 = ""; }; @@ -284,6 +338,8 @@ 77FA0B2F2B0C4D5A00404C5E /* ShareActionController.swift */, 77FA0B332B0C50BA00404C5E /* ShareActionViewModel.swift */, 77FA0B312B0C4E8E00404C5E /* ShareActionView.swift */, + 77FA0B592B147EC900404C5E /* CommentViewController.swift */, + 77FA0B5B2B147EE800404C5E /* CommentView.swift */, ); path = JournalDetail; sourceTree = ""; @@ -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 = ""; @@ -520,6 +581,9 @@ children = ( 778B8A742AF8ECE50034AFD4 /* MineViewModel.swift */, 778B8A752AF8ECE50034AFD4 /* MineViewController.swift */, + 77FA0B512B0F3BC700404C5E /* MineView.swift */, + 77FA0B552B0F4ABF00404C5E /* MineSingleController.swift */, + 77FA0B572B0F4C0800404C5E /* MineSingleViewModel.swift */, ); path = Mine; sourceTree = ""; @@ -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 = ""; @@ -554,6 +633,8 @@ children = ( 778B8A7D2AF8ECE50034AFD4 /* SearchViewController.swift */, 778B8A7E2AF8ECE50034AFD4 /* SearchViewModel.swift */, + 7751D3732B43C9FA00F1F2BD /* MusicStyleViewController.swift */, + 7751D3772B43EA1200F1F2BD /* SearchResultsController.swift */, ); path = Search; sourceTree = ""; @@ -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 */, diff --git a/IndieMusic/IndieMusic/Common/NavigationController.swift b/IndieMusic/IndieMusic/Common/NavigationController.swift index fe83470..6b93d94 100644 --- a/IndieMusic/IndieMusic/Common/NavigationController.swift +++ b/IndieMusic/IndieMusic/Common/NavigationController.swift @@ -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] + 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. + 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 } diff --git a/IndieMusic/IndieMusic/Common/ViewController.swift b/IndieMusic/IndieMusic/Common/ViewController.swift index 553fb4c..4614c9d 100644 --- a/IndieMusic/IndieMusic/Common/ViewController.swift +++ b/IndieMusic/IndieMusic/Common/ViewController.swift @@ -119,7 +119,7 @@ class ViewController: UIViewController { // self.navigationItem.leftBarButtonItems = [spacer, backBarButton] view.backgroundColor = .white - navigationItem.leftBarButtonItem = backBarButton +// navigationItem.leftBarButtonItem = backBarButton updateUI() } diff --git a/IndieMusic/IndieMusic/Models/Mine.swift b/IndieMusic/IndieMusic/Models/Mine.swift new file mode 100644 index 0000000..993204c --- /dev/null +++ b/IndieMusic/IndieMusic/Models/Mine.swift @@ -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 + } +} diff --git a/IndieMusic/IndieMusic/Models/MusicStyle.swift b/IndieMusic/IndieMusic/Models/MusicStyle.swift new file mode 100644 index 0000000..a54e299 --- /dev/null +++ b/IndieMusic/IndieMusic/Models/MusicStyle.swift @@ -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 + } +} diff --git a/IndieMusic/IndieMusic/Models/PersonInfo.swift b/IndieMusic/IndieMusic/Models/PersonInfo.swift new file mode 100644 index 0000000..1ff4e59 --- /dev/null +++ b/IndieMusic/IndieMusic/Models/PersonInfo.swift @@ -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 + +} diff --git a/IndieMusic/IndieMusic/Models/Search.swift b/IndieMusic/IndieMusic/Models/Search.swift new file mode 100644 index 0000000..cbe32de --- /dev/null +++ b/IndieMusic/IndieMusic/Models/Search.swift @@ -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 + } +} diff --git a/IndieMusic/IndieMusic/Models/Setting.swift b/IndieMusic/IndieMusic/Models/Setting.swift new file mode 100644 index 0000000..0033510 --- /dev/null +++ b/IndieMusic/IndieMusic/Models/Setting.swift @@ -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 + } +} diff --git a/IndieMusic/IndieMusic/Modules/Home/HomeTabBarController.swift b/IndieMusic/IndieMusic/Modules/Home/HomeTabBarController.swift index d4b089d..cf9f9fc 100644 --- a/IndieMusic/IndieMusic/Modules/Home/HomeTabBarController.swift +++ b/IndieMusic/IndieMusic/Modules/Home/HomeTabBarController.swift @@ -71,6 +71,7 @@ class HomeTabBarController: UITabBarController, Navigatable { var customeTabBar: UITabBar = { let tabBar = UITabBar.init() + tabBar.isTranslucent = false return tabBar }() diff --git a/IndieMusic/IndieMusic/Modules/Home/HomeViewController.swift b/IndieMusic/IndieMusic/Modules/Home/HomeViewController.swift index dfad40b..3b70e43 100644 --- a/IndieMusic/IndieMusic/Modules/Home/HomeViewController.swift +++ b/IndieMusic/IndieMusic/Modules/Home/HomeViewController.swift @@ -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() { diff --git a/IndieMusic/IndieMusic/Modules/JournalDetail/CommentView.swift b/IndieMusic/IndieMusic/Modules/JournalDetail/CommentView.swift new file mode 100644 index 0000000..4f5b4eb --- /dev/null +++ b/IndieMusic/IndieMusic/Modules/JournalDetail/CommentView.swift @@ -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) + } + + + } + +} + + diff --git a/IndieMusic/IndieMusic/Modules/JournalDetail/CommentViewController.swift b/IndieMusic/IndieMusic/Modules/JournalDetail/CommentViewController.swift new file mode 100644 index 0000000..8d3ae68 --- /dev/null +++ b/IndieMusic/IndieMusic/Modules/JournalDetail/CommentViewController.swift @@ -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) + } + } + + +} diff --git a/IndieMusic/IndieMusic/Modules/JournalDetail/JournalDetailView.swift b/IndieMusic/IndieMusic/Modules/JournalDetail/JournalDetailView.swift index eaae97d..2920c39 100644 --- a/IndieMusic/IndieMusic/Modules/JournalDetail/JournalDetailView.swift +++ b/IndieMusic/IndieMusic/Modules/JournalDetail/JournalDetailView.swift @@ -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) diff --git a/IndieMusic/IndieMusic/Modules/Mine/MineSingleController.swift b/IndieMusic/IndieMusic/Modules/Mine/MineSingleController.swift new file mode 100644 index 0000000..ea08efb --- /dev/null +++ b/IndieMusic/IndieMusic/Modules/Mine/MineSingleController.swift @@ -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 { + return RxTableViewSectionedReloadDataSource( + 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 + } + ) + } +} diff --git a/IndieMusic/IndieMusic/Modules/Mine/MineSingleViewModel.swift b/IndieMusic/IndieMusic/Modules/Mine/MineSingleViewModel.swift new file mode 100644 index 0000000..873c24e --- /dev/null +++ b/IndieMusic/IndieMusic/Modules/Mine/MineSingleViewModel.swift @@ -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 + let selection: Driver + + } + + struct Output { + let items: BehaviorRelay<[MineSingleSection]> + let selection: Driver + let itemSelected: PublishSubject + + } + + let itemSelected = PublishSubject() + 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) + } + +} diff --git a/IndieMusic/IndieMusic/Modules/Mine/MineView.swift b/IndieMusic/IndieMusic/Modules/Mine/MineView.swift new file mode 100644 index 0000000..626cf90 --- /dev/null +++ b/IndieMusic/IndieMusic/Modules/Mine/MineView.swift @@ -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 + } + } + +} diff --git a/IndieMusic/IndieMusic/Modules/Mine/MineViewController.swift b/IndieMusic/IndieMusic/Modules/Mine/MineViewController.swift index e4aa34b..826afa6 100644 --- a/IndieMusic/IndieMusic/Modules/Mine/MineViewController.swift +++ b/IndieMusic/IndieMusic/Modules/Mine/MineViewController.swift @@ -6,19 +6,76 @@ // import UIKit +import RxSwift +import RxCocoa +import RxDataSources -class MineViewController: ViewController { +class MineViewController: TableViewController { + let headerView: MineHeaderView = { + let headerView = MineHeaderView.init(frame: CGRect.init(x: 0, y: 0, width: BaseDimensions.screenWidth, height: 201)) + + return headerView + }() + + + + 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 { + return RxTableViewSectionedReloadDataSource( + 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 + } + ) + } +} diff --git a/IndieMusic/IndieMusic/Modules/Mine/MineViewModel.swift b/IndieMusic/IndieMusic/Modules/Mine/MineViewModel.swift index 7a199e1..9804253 100644 --- a/IndieMusic/IndieMusic/Modules/Mine/MineViewModel.swift +++ b/IndieMusic/IndieMusic/Modules/Mine/MineViewModel.swift @@ -6,20 +6,49 @@ // import Foundation +import RxSwift +import RxCocoa +import RxDataSources class MineViewModel: ViewModel, ViewModelType { struct Input { + let viewWillAppear: ControlEvent + let selection: Driver + } struct Output { + let items: BehaviorRelay<[MineSection]> + let selection: Driver + let itemSelected: PublishSubject + } + let itemSelected = PublishSubject() + let items = BehaviorRelay<[MineSection]>.init(value: []) func transform(input: Input) -> Output { - - return 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.init(items: items, + selection: input.selection, + itemSelected: itemSelected) } } diff --git a/IndieMusic/IndieMusic/Modules/Search/MusicStyleViewController.swift b/IndieMusic/IndieMusic/Modules/Search/MusicStyleViewController.swift new file mode 100644 index 0000000..df66eaa --- /dev/null +++ b/IndieMusic/IndieMusic/Modules/Search/MusicStyleViewController.swift @@ -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 { + return RxCollectionViewSectionedReloadDataSource( + 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) + } + } + +} diff --git a/IndieMusic/IndieMusic/Modules/Search/SearchResultsController.swift b/IndieMusic/IndieMusic/Modules/Search/SearchResultsController.swift new file mode 100644 index 0000000..2d0896c --- /dev/null +++ b/IndieMusic/IndieMusic/Modules/Search/SearchResultsController.swift @@ -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 { + return RxCollectionViewSectionedReloadDataSource( + 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 { + return RxTableViewSectionedReloadDataSource( + configureCell: { dataSource, tableView, indexPath, item in + let cell: SongViewCell = tableView.dequeueReusableCell(withIdentifier: "SongViewCell", for: indexPath) as! SongViewCell + + cell.audio = item + + return cell + } + ) + } +} diff --git a/IndieMusic/IndieMusic/Modules/Search/SearchViewController.swift b/IndieMusic/IndieMusic/Modules/Search/SearchViewController.swift index a9bc5d9..e0fad31 100644 --- a/IndieMusic/IndieMusic/Modules/Search/SearchViewController.swift +++ b/IndieMusic/IndieMusic/Modules/Search/SearchViewController.swift @@ -6,8 +6,27 @@ // import UIKit +import RxSwift +import RxCocoa +import RxDataSources -class SearchViewController: ViewController { +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 + }() + + + override func viewDidLoad() { super.viewDidLoad() @@ -15,5 +34,205 @@ class SearchViewController: ViewController { view.backgroundColor = .red } + + 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 { + return RxCollectionViewSectionedReloadDataSource( + 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) + } + } } diff --git a/IndieMusic/IndieMusic/Modules/Setting/AboutViewController.swift b/IndieMusic/IndieMusic/Modules/Setting/AboutViewController.swift new file mode 100644 index 0000000..e6c1348 --- /dev/null +++ b/IndieMusic/IndieMusic/Modules/Setting/AboutViewController.swift @@ -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 { + return RxTableViewSectionedReloadDataSource( + 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) + } +} + + diff --git a/IndieMusic/IndieMusic/Modules/Setting/AccountViewController.swift b/IndieMusic/IndieMusic/Modules/Setting/AccountViewController.swift new file mode 100644 index 0000000..548f979 --- /dev/null +++ b/IndieMusic/IndieMusic/Modules/Setting/AccountViewController.swift @@ -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. + } + + +} diff --git a/IndieMusic/IndieMusic/Modules/Setting/AccountViewModel.swift b/IndieMusic/IndieMusic/Modules/Setting/AccountViewModel.swift new file mode 100644 index 0000000..ad29453 --- /dev/null +++ b/IndieMusic/IndieMusic/Modules/Setting/AccountViewModel.swift @@ -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 + let selection: Driver + + } + + struct Output { + let items: BehaviorRelay<[SettingSection]> + let selection: Driver + let itemSelected: PublishSubject + + } + + let itemSelected = PublishSubject() + 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) + } + +} diff --git a/IndieMusic/IndieMusic/Modules/Setting/CacheViewController.swift b/IndieMusic/IndieMusic/Modules/Setting/CacheViewController.swift new file mode 100644 index 0000000..db38dca --- /dev/null +++ b/IndieMusic/IndieMusic/Modules/Setting/CacheViewController.swift @@ -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 + } +} diff --git a/IndieMusic/IndieMusic/Modules/Setting/EditInfoView.swift b/IndieMusic/IndieMusic/Modules/Setting/EditInfoView.swift new file mode 100644 index 0000000..bc9d674 --- /dev/null +++ b/IndieMusic/IndieMusic/Modules/Setting/EditInfoView.swift @@ -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) + } + + } + +} diff --git a/IndieMusic/IndieMusic/Modules/Setting/EditInfoViewController.swift b/IndieMusic/IndieMusic/Modules/Setting/EditInfoViewController.swift new file mode 100644 index 0000000..6278561 --- /dev/null +++ b/IndieMusic/IndieMusic/Modules/Setting/EditInfoViewController.swift @@ -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 { + return RxTableViewSectionedReloadDataSource( + 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 + } + ) + } +} + diff --git a/IndieMusic/IndieMusic/Modules/Setting/EditInfoViewModel.swift b/IndieMusic/IndieMusic/Modules/Setting/EditInfoViewModel.swift new file mode 100644 index 0000000..b5807b3 --- /dev/null +++ b/IndieMusic/IndieMusic/Modules/Setting/EditInfoViewModel.swift @@ -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 + let selection: Driver + + } + + struct Output { + let items: BehaviorRelay<[SettingSection]> + let selection: Driver + let itemSelected: PublishSubject + + } + + let itemSelected = PublishSubject() + 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) + } + +} + diff --git a/IndieMusic/IndieMusic/Modules/Setting/EditNameController.swift b/IndieMusic/IndieMusic/Modules/Setting/EditNameController.swift new file mode 100644 index 0000000..42eaadd --- /dev/null +++ b/IndieMusic/IndieMusic/Modules/Setting/EditNameController.swift @@ -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) + } + } +} diff --git a/IndieMusic/IndieMusic/Modules/Setting/FeedbackViewController.swift b/IndieMusic/IndieMusic/Modules/Setting/FeedbackViewController.swift new file mode 100644 index 0000000..f6b2404 --- /dev/null +++ b/IndieMusic/IndieMusic/Modules/Setting/FeedbackViewController.swift @@ -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) + } + + } +} diff --git a/IndieMusic/IndieMusic/Modules/Setting/PrivacyViewController.swift b/IndieMusic/IndieMusic/Modules/Setting/PrivacyViewController.swift new file mode 100644 index 0000000..f7560eb --- /dev/null +++ b/IndieMusic/IndieMusic/Modules/Setting/PrivacyViewController.swift @@ -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() + + + } +} diff --git a/IndieMusic/IndieMusic/Modules/Setting/SettingView.swift b/IndieMusic/IndieMusic/Modules/Setting/SettingView.swift new file mode 100644 index 0000000..4ae41bd --- /dev/null +++ b/IndieMusic/IndieMusic/Modules/Setting/SettingView.swift @@ -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") + } +} diff --git a/IndieMusic/IndieMusic/Modules/Setting/SettingViewController.swift b/IndieMusic/IndieMusic/Modules/Setting/SettingViewController.swift new file mode 100644 index 0000000..f97449f --- /dev/null +++ b/IndieMusic/IndieMusic/Modules/Setting/SettingViewController.swift @@ -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 { + return RxTableViewSectionedReloadDataSource( + 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 + } + ) + } +} + diff --git a/IndieMusic/IndieMusic/Modules/Setting/SettingViewMdel.swift b/IndieMusic/IndieMusic/Modules/Setting/SettingViewMdel.swift new file mode 100644 index 0000000..735f02b --- /dev/null +++ b/IndieMusic/IndieMusic/Modules/Setting/SettingViewMdel.swift @@ -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 + let selection: Driver + + } + + struct Output { + let items: BehaviorRelay<[SettingSection]> + let selection: Driver + let itemSelected: PublishSubject + + } + + let itemSelected = PublishSubject() + 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) + } + +} diff --git a/IndieMusic/IndieMusic/Modules/Setting/ThanksViewController.swift b/IndieMusic/IndieMusic/Modules/Setting/ThanksViewController.swift new file mode 100644 index 0000000..608bf76 --- /dev/null +++ b/IndieMusic/IndieMusic/Modules/Setting/ThanksViewController.swift @@ -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 + } + + } + +} + diff --git a/IndieMusic/IndieMusic/Modules/Setting/TimingViewController.swift b/IndieMusic/IndieMusic/Modules/Setting/TimingViewController.swift new file mode 100644 index 0000000..5c593f7 --- /dev/null +++ b/IndieMusic/IndieMusic/Modules/Setting/TimingViewController.swift @@ -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) + } + + } + +} diff --git a/IndieMusic/IndieMusic/Resources/Assets.xcassets/audio/nav_back_btn.imageset/nav_back_btn.svg b/IndieMusic/IndieMusic/Resources/Assets.xcassets/audio/nav_back_btn.imageset/nav_back_btn.svg deleted file mode 100644 index f41b9f9..0000000 --- a/IndieMusic/IndieMusic/Resources/Assets.xcassets/audio/nav_back_btn.imageset/nav_back_btn.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/IndieMusic/IndieMusic/Resources/Assets.xcassets/mine/Contents.json b/IndieMusic/IndieMusic/Resources/Assets.xcassets/mine/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/IndieMusic/IndieMusic/Resources/Assets.xcassets/mine/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/IndieMusic/IndieMusic/Resources/Assets.xcassets/mine/mine_play_btn.imageset/Contents.json b/IndieMusic/IndieMusic/Resources/Assets.xcassets/mine/mine_play_btn.imageset/Contents.json new file mode 100644 index 0000000..96c174b --- /dev/null +++ b/IndieMusic/IndieMusic/Resources/Assets.xcassets/mine/mine_play_btn.imageset/Contents.json @@ -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 + } +} diff --git a/IndieMusic/IndieMusic/Resources/Assets.xcassets/mine/mine_play_btn.imageset/mine_play_btn.svg b/IndieMusic/IndieMusic/Resources/Assets.xcassets/mine/mine_play_btn.imageset/mine_play_btn.svg new file mode 100644 index 0000000..8680bcf --- /dev/null +++ b/IndieMusic/IndieMusic/Resources/Assets.xcassets/mine/mine_play_btn.imageset/mine_play_btn.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/IndieMusic/IndieMusic/Resources/Assets.xcassets/search/Contents.json b/IndieMusic/IndieMusic/Resources/Assets.xcassets/search/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/IndieMusic/IndieMusic/Resources/Assets.xcassets/search/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/IndieMusic/IndieMusic/Resources/Assets.xcassets/audio/nav_back_btn.imageset/Contents.json b/IndieMusic/IndieMusic/Resources/Assets.xcassets/search/search_bar_icon.imageset/Contents.json similarity index 87% rename from IndieMusic/IndieMusic/Resources/Assets.xcassets/audio/nav_back_btn.imageset/Contents.json rename to IndieMusic/IndieMusic/Resources/Assets.xcassets/search/search_bar_icon.imageset/Contents.json index 07848ab..7ded5fd 100644 --- a/IndieMusic/IndieMusic/Resources/Assets.xcassets/audio/nav_back_btn.imageset/Contents.json +++ b/IndieMusic/IndieMusic/Resources/Assets.xcassets/search/search_bar_icon.imageset/Contents.json @@ -1,7 +1,7 @@ { "images" : [ { - "filename" : "nav_back_btn.svg", + "filename" : "search_icon.svg", "idiom" : "universal", "scale" : "1x" }, diff --git a/IndieMusic/IndieMusic/Resources/Assets.xcassets/search/search_bar_icon.imageset/search_icon.svg b/IndieMusic/IndieMusic/Resources/Assets.xcassets/search/search_bar_icon.imageset/search_icon.svg new file mode 100644 index 0000000..8468983 --- /dev/null +++ b/IndieMusic/IndieMusic/Resources/Assets.xcassets/search/search_bar_icon.imageset/search_icon.svg @@ -0,0 +1,4 @@ + + + + diff --git a/IndieMusic/IndieMusic/Resources/Assets.xcassets/setting/Contents.json b/IndieMusic/IndieMusic/Resources/Assets.xcassets/setting/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/IndieMusic/IndieMusic/Resources/Assets.xcassets/setting/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/IndieMusic/IndieMusic/Resources/Assets.xcassets/setting/setting_arrow.imageset/Contents.json b/IndieMusic/IndieMusic/Resources/Assets.xcassets/setting/setting_arrow.imageset/Contents.json new file mode 100644 index 0000000..0ed155f --- /dev/null +++ b/IndieMusic/IndieMusic/Resources/Assets.xcassets/setting/setting_arrow.imageset/Contents.json @@ -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 + } +} diff --git a/IndieMusic/IndieMusic/Resources/Assets.xcassets/setting/setting_arrow.imageset/setting_arrow.svg b/IndieMusic/IndieMusic/Resources/Assets.xcassets/setting/setting_arrow.imageset/setting_arrow.svg new file mode 100644 index 0000000..af8816e --- /dev/null +++ b/IndieMusic/IndieMusic/Resources/Assets.xcassets/setting/setting_arrow.imageset/setting_arrow.svg @@ -0,0 +1,4 @@ + + + +