diff --git a/QuickLocation.xcodeproj/project.pbxproj b/QuickLocation.xcodeproj/project.pbxproj index ee834d27..7dd045d2 100644 --- a/QuickLocation.xcodeproj/project.pbxproj +++ b/QuickLocation.xcodeproj/project.pbxproj @@ -101,8 +101,6 @@ 305A76E02FCA8C7000227D26 /* GroupView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 305A76232FCA8C7000227D26 /* GroupView.swift */; }; 305A76E12FCA8C7000227D26 /* GroupViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 305A76242FCA8C7000227D26 /* GroupViewController.swift */; }; 305A76E22FCA8C7000227D26 /* GroupViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 305A76252FCA8C7000227D26 /* GroupViewModel.swift */; }; - 305A76E32FCA8C7000227D26 /* GroupMemberView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 305A76272FCA8C7000227D26 /* GroupMemberView.swift */; }; - 305A76E42FCA8C7000227D26 /* HomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 305A76282FCA8C7000227D26 /* HomeView.swift */; }; 305A76E52FCA8C7000227D26 /* HomeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 305A76292FCA8C7000227D26 /* HomeViewController.swift */; }; 305A76E62FCA8C7000227D26 /* LaunchViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 305A762B2FCA8C7000227D26 /* LaunchViewController.swift */; }; 305A76E72FCA8C7000227D26 /* LoginView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 305A762D2FCA8C7000227D26 /* LoginView.swift */; }; @@ -167,7 +165,6 @@ 3062E8BE2FCEBD0E00CEF511 /* GroupIconListVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3062E8BD2FCEBD0E00CEF511 /* GroupIconListVC.swift */; }; 3062E8C02FCED7BB00CEF511 /* GroupIconListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3062E8BF2FCED7BB00CEF511 /* GroupIconListView.swift */; }; 3062E8C22FCFB86800CEF511 /* CreateGroupViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3062E8C12FCFB86800CEF511 /* CreateGroupViewModel.swift */; }; - 3062E8C42FCFC90F00CEF511 /* CreateGroupVipPopView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3062E8C32FCFC90F00CEF511 /* CreateGroupVipPopView.swift */; }; 307073E12FD15F50004C37CC /* GroupIMService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 307073E02FD15F50004C37CC /* GroupIMService.swift */; }; 307073E52FD18A20004C37CC /* GroupChatView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 307073E32FD18A20004C37CC /* GroupChatView.swift */; }; 307073E62FD18A20004C37CC /* GroupChatVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 307073E22FD18A20004C37CC /* GroupChatVC.swift */; }; @@ -188,13 +185,10 @@ 30A87A622FEE724D0095E7C6 /* CreateBubbleTiemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30A87A612FEE724D0095E7C6 /* CreateBubbleTiemView.swift */; }; 30A87A642FEE75520095E7C6 /* CreateBubbleTipsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30A87A632FEE75520095E7C6 /* CreateBubbleTipsView.swift */; }; 30A87A662FEE843E0095E7C6 /* CreateBubbleDoneView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30A87A652FEE843E0095E7C6 /* CreateBubbleDoneView.swift */; }; - 30A87A682FEE86560095E7C6 /* CreateBubblePopView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30A87A672FEE86560095E7C6 /* CreateBubblePopView.swift */; }; 30A87A6B2FEF5B950095E7C6 /* SearchLocationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30A87A6A2FEF5B950095E7C6 /* SearchLocationView.swift */; }; 30A87A6D2FEF5BA10095E7C6 /* SearchLocationVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30A87A6C2FEF5BA10095E7C6 /* SearchLocationVC.swift */; }; 30A87A6F2FEF7BE40095E7C6 /* SearchLocationResultVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30A87A6E2FEF7BE40095E7C6 /* SearchLocationResultVC.swift */; }; 30A87A712FEF7BED0095E7C6 /* SearchLocationResultView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30A87A702FEF7BED0095E7C6 /* SearchLocationResultView.swift */; }; - 30ACD54C2FF6336000174861 /* PopupWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30ACD54B2FF6336000174861 /* PopupWindow.swift */; }; - 30ACD67B2FF7B36A00174861 /* PopupQueueManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30ACD67A2FF7B36A00174861 /* PopupQueueManager.swift */; }; 30B2D0B12FEB111100CA0001 /* PhotoPickerStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30B2D0B02FEB111100CA0001 /* PhotoPickerStore.swift */; }; 30B2D0B32FEB111100CA0001 /* PhotoPickerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30B2D0B22FEB111100CA0001 /* PhotoPickerView.swift */; }; 30B2D0B52FEB111100CA0001 /* PhotoPickerAlbumView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30B2D0B42FEB111100CA0001 /* PhotoPickerAlbumView.swift */; }; @@ -227,9 +221,7 @@ 30C4C01D2FDBF557009215C1 /* RemoveMemberViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30C4C01C2FDBF557009215C1 /* RemoveMemberViewModel.swift */; }; 30C4C0202FDC0EC5009215C1 /* GroupInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30C4C01F2FDC0EC5009215C1 /* GroupInfoView.swift */; }; 30C4C0222FDC0ED3009215C1 /* GroupInfoVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30C4C0212FDC0ED3009215C1 /* GroupInfoVC.swift */; }; - 30C6666C2FFB7C4000E62B25 /* IAPManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30C6666B2FFB7C4000E62B25 /* IAPManager.swift */; }; 30C6679E2FFB7FEF00E62B25 /* SharePopView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30C6679C2FFB7FEF00E62B25 /* SharePopView.swift */; }; - 30CCDE4E2FE26CEA00F5214A /* PayResultPopVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30CCDE4D2FE26CEA00F5214A /* PayResultPopVC.swift */; }; 30CCDE512FE2785D00F5214A /* SignInVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30CCDE502FE2785D00F5214A /* SignInVC.swift */; }; 30CCDE532FE2786600F5214A /* SignInView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30CCDE522FE2786600F5214A /* SignInView.swift */; }; 30CCDE552FE2903100F5214A /* SignInModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30CCDE542FE2903100F5214A /* SignInModel.swift */; }; @@ -237,9 +229,6 @@ 30CCDE5A2FE39F9D00F5214A /* SOSViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30CCDE592FE39F9D00F5214A /* SOSViewController.swift */; }; 30CCDE5C2FE3A1A800F5214A /* SOSPracticeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30CCDE5B2FE3A1A800F5214A /* SOSPracticeView.swift */; }; 30D74AAB2FE8C7700050EB2C /* GPSSignalHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30D74AAA2FE8C7700050EB2C /* GPSSignalHelper.swift */; }; - 30D74AAE2FEA13E00050EB2C /* ScheduleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30D74AAD2FEA13E00050EB2C /* ScheduleView.swift */; }; - 30D74AB02FEA13ED0050EB2C /* ScheduleVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30D74AAF2FEA13ED0050EB2C /* ScheduleVC.swift */; }; - 30D74AB22FEA1D5D0050EB2C /* ScheduleViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30D74AB12FEA1D5D0050EB2C /* ScheduleViewModel.swift */; }; 30D74AB42FEA25B90050EB2C /* ViewedModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30D74AB32FEA25B90050EB2C /* ViewedModel.swift */; }; 30D74AB62FEA34FF0050EB2C /* ItineraryAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30D74AB52FEA34FF0050EB2C /* ItineraryAPI.swift */; }; 30D74AB82FEA36A50050EB2C /* ItineraryService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30D74AB72FEA36A50050EB2C /* ItineraryService.swift */; }; @@ -249,13 +238,9 @@ 30D74AC12FEA6EEF0050EB2C /* CreateSchedulePopView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30D74AC02FEA6EEF0050EB2C /* CreateSchedulePopView.swift */; }; 30D74D1F2FEBB09B0050EB2C /* CreateScheduleVM.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30D74D1E2FEBB09B0050EB2C /* CreateScheduleVM.swift */; }; 30D87CDB2FDFA9EE00E958FD /* MQTTService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30D87CDA2FDFA9EE00E958FD /* MQTTService.swift */; }; - 30D87CDD2FDFF07500E958FD /* InteractionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30D87CDC2FDFF07500E958FD /* InteractionView.swift */; }; 30D87CDF2FDFF1A100E958FD /* QuickMessageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30D87CDE2FDFF1A100E958FD /* QuickMessageView.swift */; }; 30D87D042FE1336300E958FD /* NavigationVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30D87D012FE1336300E958FD /* NavigationVC.swift */; }; 30D87D052FE1336300E958FD /* NavigationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30D87D022FE1336300E958FD /* NavigationView.swift */; }; - 30D891F52FE22E0600E958FD /* OrderAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30D891F42FE22E0600E958FD /* OrderAPI.swift */; }; - 30D891F72FE22E6E00E958FD /* OrderService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30D891F62FE22E6E00E958FD /* OrderService.swift */; }; - 30DA36BD2FECC5AB008D5A2C /* CreateScheduleVipPopView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30DA36BC2FECC5AB008D5A2C /* CreateScheduleVipPopView.swift */; }; 30DC185A2FD11E7A0041DCD1 /* WebOperations.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30DC18562FD11E7A0041DCD1 /* WebOperations.swift */; }; 30DC185B2FD11E7A0041DCD1 /* NavigationTitleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30DC18552FD11E7A0041DCD1 /* NavigationTitleView.swift */; }; 30DC185C2FD11E7A0041DCD1 /* WebViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30DC18572FD11E7A0041DCD1 /* WebViewController.swift */; }; @@ -366,11 +351,13 @@ 55B26001304B000100786601 /* VersionUpgradePopVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55B26000304B000100786600 /* VersionUpgradePopVC.swift */; }; 55B261010000000100786601 /* PrivacySettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55B261000000000100786600 /* PrivacySettingsViewController.swift */; }; 55BF752D2FFE53F70055DA57 /* LocationPermissionPopView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55BF752C2FFE53F70055DA57 /* LocationPermissionPopView.swift */; }; - 55BF75352FFF91690055DA57 /* InteractionEmojiCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55BF75342FFF91690055DA57 /* InteractionEmojiCell.swift */; }; 55C1A0113034101000786011 /* PhoneStatusCollector.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55C1A0103034101000786010 /* PhoneStatusCollector.swift */; }; 55C1A0213034102000786021 /* PrivilegeDeniedOverlay.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55C1A0203034102000786020 /* PrivilegeDeniedOverlay.swift */; }; 55C219C13024C00100784731 /* SearchLocationHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55C219C13024C00100784730 /* SearchLocationHeaderView.swift */; }; 55C4C0242FDB91C8009215C2 /* CheckPermissionGuideVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55C4C0232FDB91C8009215C2 /* CheckPermissionGuideVC.swift */; }; + 55CA150E3058E55E000F1189 /* ScheduleViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55CA150B3058E55E000F1189 /* ScheduleViewModel.swift */; }; + 55CA15103058EBE5000F1189 /* InteractionEmojiCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55CA150F3058EBE5000F1189 /* InteractionEmojiCell.swift */; }; + 55CA15123058EC23000F1189 /* InteractionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55CA15113058EC23000F1189 /* InteractionView.swift */; }; 60BEE25E61F3DE24976A7A47 /* ManagedSettingsUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7FE44DF1C46BDA7B98BC7859 /* ManagedSettingsUI.framework */; }; 68F0D48EB76039050533197C /* AppRestrictShared.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AB29D0618C4BE76F2CA5261 /* AppRestrictShared.swift */; }; 6D90E8FFE4D597E888E6A224 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1E326B06736FE04DD7A5E96D /* UIKit.framework */; }; @@ -539,8 +526,6 @@ 305A76232FCA8C7000227D26 /* GroupView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupView.swift; sourceTree = ""; }; 305A76242FCA8C7000227D26 /* GroupViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupViewController.swift; sourceTree = ""; }; 305A76252FCA8C7000227D26 /* GroupViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupViewModel.swift; sourceTree = ""; }; - 305A76272FCA8C7000227D26 /* GroupMemberView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupMemberView.swift; sourceTree = ""; }; - 305A76282FCA8C7000227D26 /* HomeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeView.swift; sourceTree = ""; }; 305A76292FCA8C7000227D26 /* HomeViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeViewController.swift; sourceTree = ""; }; 305A762B2FCA8C7000227D26 /* LaunchViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LaunchViewController.swift; sourceTree = ""; }; 305A762D2FCA8C7000227D26 /* LoginView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginView.swift; sourceTree = ""; }; @@ -609,7 +594,6 @@ 3062E8BD2FCEBD0E00CEF511 /* GroupIconListVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupIconListVC.swift; sourceTree = ""; }; 3062E8BF2FCED7BB00CEF511 /* GroupIconListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupIconListView.swift; sourceTree = ""; }; 3062E8C12FCFB86800CEF511 /* CreateGroupViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateGroupViewModel.swift; sourceTree = ""; }; - 3062E8C32FCFC90F00CEF511 /* CreateGroupVipPopView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateGroupVipPopView.swift; sourceTree = ""; }; 307073E02FD15F50004C37CC /* GroupIMService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupIMService.swift; sourceTree = ""; }; 307073E22FD18A20004C37CC /* GroupChatVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupChatVC.swift; sourceTree = ""; }; 307073E32FD18A20004C37CC /* GroupChatView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupChatView.swift; sourceTree = ""; }; @@ -630,13 +614,10 @@ 30A87A612FEE724D0095E7C6 /* CreateBubbleTiemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateBubbleTiemView.swift; sourceTree = ""; }; 30A87A632FEE75520095E7C6 /* CreateBubbleTipsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateBubbleTipsView.swift; sourceTree = ""; }; 30A87A652FEE843E0095E7C6 /* CreateBubbleDoneView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateBubbleDoneView.swift; sourceTree = ""; }; - 30A87A672FEE86560095E7C6 /* CreateBubblePopView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateBubblePopView.swift; sourceTree = ""; }; 30A87A6A2FEF5B950095E7C6 /* SearchLocationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchLocationView.swift; sourceTree = ""; }; 30A87A6C2FEF5BA10095E7C6 /* SearchLocationVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchLocationVC.swift; sourceTree = ""; }; 30A87A6E2FEF7BE40095E7C6 /* SearchLocationResultVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchLocationResultVC.swift; sourceTree = ""; }; 30A87A702FEF7BED0095E7C6 /* SearchLocationResultView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchLocationResultView.swift; sourceTree = ""; }; - 30ACD54B2FF6336000174861 /* PopupWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PopupWindow.swift; sourceTree = ""; }; - 30ACD67A2FF7B36A00174861 /* PopupQueueManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PopupQueueManager.swift; sourceTree = ""; }; 30B2D0B02FEB111100CA0001 /* PhotoPickerStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotoPickerStore.swift; sourceTree = ""; }; 30B2D0B22FEB111100CA0001 /* PhotoPickerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotoPickerView.swift; sourceTree = ""; }; 30B2D0B42FEB111100CA0001 /* PhotoPickerAlbumView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotoPickerAlbumView.swift; sourceTree = ""; }; @@ -670,9 +651,7 @@ 30C4C01C2FDBF557009215C1 /* RemoveMemberViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoveMemberViewModel.swift; sourceTree = ""; }; 30C4C01F2FDC0EC5009215C1 /* GroupInfoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupInfoView.swift; sourceTree = ""; }; 30C4C0212FDC0ED3009215C1 /* GroupInfoVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupInfoVC.swift; sourceTree = ""; }; - 30C6666B2FFB7C4000E62B25 /* IAPManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IAPManager.swift; sourceTree = ""; }; 30C6679C2FFB7FEF00E62B25 /* SharePopView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SharePopView.swift; sourceTree = ""; }; - 30CCDE4D2FE26CEA00F5214A /* PayResultPopVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayResultPopVC.swift; sourceTree = ""; }; 30CCDE502FE2785D00F5214A /* SignInVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignInVC.swift; sourceTree = ""; }; 30CCDE522FE2786600F5214A /* SignInView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignInView.swift; sourceTree = ""; }; 30CCDE542FE2903100F5214A /* SignInModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignInModel.swift; sourceTree = ""; }; @@ -680,9 +659,6 @@ 30CCDE592FE39F9D00F5214A /* SOSViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SOSViewController.swift; sourceTree = ""; }; 30CCDE5B2FE3A1A800F5214A /* SOSPracticeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SOSPracticeView.swift; sourceTree = ""; }; 30D74AAA2FE8C7700050EB2C /* GPSSignalHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GPSSignalHelper.swift; sourceTree = ""; }; - 30D74AAD2FEA13E00050EB2C /* ScheduleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScheduleView.swift; sourceTree = ""; }; - 30D74AAF2FEA13ED0050EB2C /* ScheduleVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScheduleVC.swift; sourceTree = ""; }; - 30D74AB12FEA1D5D0050EB2C /* ScheduleViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScheduleViewModel.swift; sourceTree = ""; }; 30D74AB32FEA25B90050EB2C /* ViewedModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewedModel.swift; sourceTree = ""; }; 30D74AB52FEA34FF0050EB2C /* ItineraryAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItineraryAPI.swift; sourceTree = ""; }; 30D74AB72FEA36A50050EB2C /* ItineraryService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItineraryService.swift; sourceTree = ""; }; @@ -692,13 +668,9 @@ 30D74AC02FEA6EEF0050EB2C /* CreateSchedulePopView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateSchedulePopView.swift; sourceTree = ""; }; 30D74D1E2FEBB09B0050EB2C /* CreateScheduleVM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateScheduleVM.swift; sourceTree = ""; }; 30D87CDA2FDFA9EE00E958FD /* MQTTService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MQTTService.swift; sourceTree = ""; }; - 30D87CDC2FDFF07500E958FD /* InteractionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InteractionView.swift; sourceTree = ""; }; 30D87CDE2FDFF1A100E958FD /* QuickMessageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickMessageView.swift; sourceTree = ""; }; 30D87D012FE1336300E958FD /* NavigationVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationVC.swift; sourceTree = ""; }; 30D87D022FE1336300E958FD /* NavigationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationView.swift; sourceTree = ""; }; - 30D891F42FE22E0600E958FD /* OrderAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OrderAPI.swift; sourceTree = ""; }; - 30D891F62FE22E6E00E958FD /* OrderService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OrderService.swift; sourceTree = ""; }; - 30DA36BC2FECC5AB008D5A2C /* CreateScheduleVipPopView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateScheduleVipPopView.swift; sourceTree = ""; }; 30DC18552FD11E7A0041DCD1 /* NavigationTitleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationTitleView.swift; sourceTree = ""; }; 30DC18562FD11E7A0041DCD1 /* WebOperations.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebOperations.swift; sourceTree = ""; }; 30DC18572FD11E7A0041DCD1 /* WebViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebViewController.swift; sourceTree = ""; }; @@ -813,11 +785,13 @@ 55B26000304B000100786600 /* VersionUpgradePopVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VersionUpgradePopVC.swift; sourceTree = ""; }; 55B261000000000100786600 /* PrivacySettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrivacySettingsViewController.swift; sourceTree = ""; }; 55BF752C2FFE53F70055DA57 /* LocationPermissionPopView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationPermissionPopView.swift; sourceTree = ""; }; - 55BF75342FFF91690055DA57 /* InteractionEmojiCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InteractionEmojiCell.swift; sourceTree = ""; }; 55C1A0103034101000786010 /* PhoneStatusCollector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhoneStatusCollector.swift; sourceTree = ""; }; 55C1A0203034102000786020 /* PrivilegeDeniedOverlay.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrivilegeDeniedOverlay.swift; sourceTree = ""; }; 55C219C13024C00100784730 /* SearchLocationHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchLocationHeaderView.swift; sourceTree = ""; }; 55C4C0232FDB91C8009215C2 /* CheckPermissionGuideVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckPermissionGuideVC.swift; sourceTree = ""; }; + 55CA150B3058E55E000F1189 /* ScheduleViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScheduleViewModel.swift; sourceTree = ""; }; + 55CA150F3058EBE5000F1189 /* InteractionEmojiCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InteractionEmojiCell.swift; sourceTree = ""; }; + 55CA15113058EC23000F1189 /* InteractionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InteractionView.swift; sourceTree = ""; }; 5E5F5DC8694A001BF0C47147 /* PairGuideStepsView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PairGuideStepsView.swift; path = AppRestrict/PairGuideStepsView.swift; sourceTree = ""; }; 6BAE595D39202A2958737BD3 /* SelectActivityVC.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SelectActivityVC.swift; path = AppRestrict/SelectActivityVC.swift; sourceTree = ""; }; 787F87DD1CEBED1A4E1E9FC7 /* AppRestrictView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AppRestrictView.swift; path = AppRestrict/AppRestrictView.swift; sourceTree = ""; }; @@ -949,7 +923,6 @@ 305A74CF2FCA8C7000227D26 /* UserAPI.swift */, 55B230023032000100785003 /* PigeonAPI.swift */, 30BAB8502FCD331C00C33B5C /* GroupAPI.swift */, - 30D891F42FE22E0600E958FD /* OrderAPI.swift */, 30D74AB52FEA34FF0050EB2C /* ItineraryAPI.swift */, 30B74B4A2FF390EF00F6744D /* DrivingAPI.swift */, ); @@ -1210,7 +1183,6 @@ 55B217D23022F0A000784728 /* Unlock */, 305A752C2FCA8C7000227D26 /* URL */, 30D87CD52FDF9F1900E958FD /* MQTT */, - 30C6666A2FFB7C3000E62B25 /* IAPManager */, 2F518AB6587CC227CC515D8C /* AppRestrict */, ); path = Manager; @@ -1300,10 +1272,10 @@ 305A762A2FCA8C7000227D26 /* Home */ = { isa = PBXGroup; children = ( + 55CA15113058EC23000F1189 /* InteractionView.swift */, + 55CA150F3058EBE5000F1189 /* InteractionEmojiCell.swift */, 305A76292FCA8C7000227D26 /* HomeViewController.swift */, 305A798B2FCAB99300227D26 /* HomeViewModel.swift */, - 305A76282FCA8C7000227D26 /* HomeView.swift */, - 305A76272FCA8C7000227D26 /* GroupMemberView.swift */, 55B2179030217D6600784774 /* HomeView2.swift */, 55B2179230218CE100784774 /* GroupMemberView2.swift */, 55B222000000000100784830 /* AddEmojiPopView.swift */, @@ -1319,8 +1291,6 @@ 55B240063040000100784906 /* AppUsageReport */, 30A7A9102FCAEE3D00105780 /* GroupListPopView.swift */, 30D87CDE2FDFF1A100E958FD /* QuickMessageView.swift */, - 30D87CDC2FDFF07500E958FD /* InteractionView.swift */, - 55BF75342FFF91690055DA57 /* InteractionEmojiCell.swift */, 55BF752C2FFE53F70055DA57 /* LocationPermissionPopView.swift */, 30A87A692FEF59E60095E7C6 /* SearchLocation */, 30A87A5C2FEE711C0095E7C6 /* Bubble */, @@ -1398,7 +1368,6 @@ 305A762C2FCA8C7000227D26 /* Launch */, 3062E8B32FCE6BA400CEF511 /* Scan */, 30DC18592FD11E7A0041DCD1 /* Web */, - 30ACD54A2FF6332200174861 /* PopupWindow */, 30EFF3AD2FD7FF1400EB35D4 /* TextInput */, 30C6679D2FFB7FEF00E62B25 /* Share */, F49062649CA8E5F9FA2F22A5 /* AppRestrict */, @@ -1415,7 +1384,6 @@ 55B230003032000100785001 /* UploadService.swift */, 55B230043032000100785005 /* PigeonService.swift */, 30BAB8522FCD337C00C33B5C /* GroupService.swift */, - 30D891F62FE22E6E00E958FD /* OrderService.swift */, 30D74AB72FEA36A50050EB2C /* ItineraryService.swift */, 30B74B4C2FF391FF00F6744D /* DrivingService.swift */, ); @@ -1515,7 +1483,6 @@ isa = PBXGroup; children = ( 55B26000304B000100786600 /* VersionUpgradePopVC.swift */, - 30CCDE4D2FE26CEA00F5214A /* PayResultPopVC.swift */, 30EFF3BA2FD90D7600EB35D4 /* ConfirmPopVC.swift */, 305A76642FCA8C7000227D26 /* DLAlertPopVC.swift */, 305A76652FCA8C7000227D26 /* DLCustomPopVC.swift */, @@ -1599,7 +1566,6 @@ 3062E8C12FCFB86800CEF511 /* CreateGroupViewModel.swift */, 3062E8BD2FCEBD0E00CEF511 /* GroupIconListVC.swift */, 3062E8BF2FCED7BB00CEF511 /* GroupIconListView.swift */, - 3062E8C32FCFC90F00CEF511 /* CreateGroupVipPopView.swift */, ); path = CreateGroup; sourceTree = ""; @@ -1666,7 +1632,6 @@ 30A87A612FEE724D0095E7C6 /* CreateBubbleTiemView.swift */, 30A87A632FEE75520095E7C6 /* CreateBubbleTipsView.swift */, 30A87A652FEE843E0095E7C6 /* CreateBubbleDoneView.swift */, - 30A87A672FEE86560095E7C6 /* CreateBubblePopView.swift */, ); path = Bubble; sourceTree = ""; @@ -1684,15 +1649,6 @@ path = SearchLocation; sourceTree = ""; }; - 30ACD54A2FF6332200174861 /* PopupWindow */ = { - isa = PBXGroup; - children = ( - 30ACD67A2FF7B36A00174861 /* PopupQueueManager.swift */, - 30ACD54B2FF6336000174861 /* PopupWindow.swift */, - ); - path = PopupWindow; - sourceTree = ""; - }; 30B2D0BA2FEB111100CA0001 /* PhotoPicker */ = { isa = PBXGroup; children = ( @@ -1784,14 +1740,6 @@ path = GroupInfo; sourceTree = ""; }; - 30C6666A2FFB7C3000E62B25 /* IAPManager */ = { - isa = PBXGroup; - children = ( - 30C6666B2FFB7C4000E62B25 /* IAPManager.swift */, - ); - path = IAPManager; - sourceTree = ""; - }; 30C6679D2FFB7FEF00E62B25 /* Share */ = { isa = PBXGroup; children = ( @@ -1827,9 +1775,7 @@ 30D74AAC2FEA13BD0050EB2C /* Schedule */ = { isa = PBXGroup; children = ( - 30D74AAF2FEA13ED0050EB2C /* ScheduleVC.swift */, - 30D74AB12FEA1D5D0050EB2C /* ScheduleViewModel.swift */, - 30D74AAD2FEA13E00050EB2C /* ScheduleView.swift */, + 55CA150B3058E55E000F1189 /* ScheduleViewModel.swift */, 30D74AB32FEA25B90050EB2C /* ViewedModel.swift */, 30D74AB92FEA37AD0050EB2C /* ScheduleModel.swift */, 30D74ABB2FEA67CE0050EB2C /* CreateSchedule */, @@ -1848,7 +1794,6 @@ 30D74D1E2FEBB09B0050EB2C /* CreateScheduleVM.swift */, 30D74ABE2FEA67F30050EB2C /* CreateScheduleView.swift */, 30D74AC02FEA6EEF0050EB2C /* CreateSchedulePopView.swift */, - 30DA36BC2FECC5AB008D5A2C /* CreateScheduleVipPopView.swift */, ); path = CreateSchedule; sourceTree = ""; @@ -2432,7 +2377,6 @@ 305A76922FCA8C7000227D26 /* LogUtils.swift in Sources */, 305A76932FCA8C7000227D26 /* AddImageCell.swift in Sources */, 30EFF3D82FDA8F1000EB35D4 /* EmergencyContactVC.swift in Sources */, - 30A87A682FEE86560095E7C6 /* CreateBubblePopView.swift in Sources */, 55B219C13024C00100784722 /* BubbleHeroView.swift in Sources */, 55B219C13024C00100784724 /* CreateBubbleSetupView.swift in Sources */, 55B219C13024C00100784726 /* BubbleKnowledgeView.swift in Sources */, @@ -2455,27 +2399,24 @@ 30EFF3DA2FDA935D00EB35D4 /* EmergencyContactFooterView.swift in Sources */, 3062E8C22FCFB86800CEF511 /* CreateGroupViewModel.swift in Sources */, 30A87A662FEE843E0095E7C6 /* CreateBubbleDoneView.swift in Sources */, - 55BF75352FFF91690055DA57 /* InteractionEmojiCell.swift in Sources */, 305A769B2FCA8C7000227D26 /* PopupAnimators.swift in Sources */, 30A87A4D2FEE1DB40095E7C6 /* ItineraryDetailView.swift in Sources */, 305A769C2FCA8C7000227D26 /* PopupViewController.swift in Sources */, 305A769D2FCA8C7000227D26 /* PopupViewController+Extension.swift in Sources */, 30EFF3C42FDA431D00EB35D4 /* ChangePhoneVC.swift in Sources */, - 30C6666C2FFB7C4000E62B25 /* IAPManager.swift in Sources */, 305A769E2FCA8C7000227D26 /* TextArrowCell.swift in Sources */, 305A769F2FCA8C7000227D26 /* TextContentArrowCell.swift in Sources */, 30D87D042FE1336300E958FD /* NavigationVC.swift in Sources */, 30D87D052FE1336300E958FD /* NavigationView.swift in Sources */, 30B819F42FF3CE4900FAB693 /* ItineraryTraceVC.swift in Sources */, 305A76A02FCA8C7000227D26 /* TextTableViewCell.swift in Sources */, - 30ACD67B2FF7B36A00174861 /* PopupQueueManager.swift in Sources */, 305A76A12FCA8C7000227D26 /* UIButton+RTL.m in Sources */, 30EFF3A62FD7C5AF00EB35D4 /* GroupSettingVC.swift in Sources */, + 55CA15103058EBE5000F1189 /* InteractionEmojiCell.swift in Sources */, 305A76A22FCA8C7000227D26 /* Array+Extension.swift in Sources */, 305A76A32FCA8C7000227D26 /* ControlEvents+Block.swift in Sources */, 3062E8B72FCE6BFE00CEF511 /* ScanView.swift in Sources */, 305A76A42FCA8C7000227D26 /* Date+Extension.swift in Sources */, - 30D74AAE2FEA13E00050EB2C /* ScheduleView.swift in Sources */, 305A76A52FCA8C7000227D26 /* Dictionay+Extension.swift in Sources */, 30A87A522FEE4E5D0095E7C6 /* ScheduleHistoryVC.swift in Sources */, 305A76A62FCA8C7000227D26 /* Int+Extension.swift in Sources */, @@ -2566,9 +2507,11 @@ 55B234013036000100785051 /* RelationSelectPopVC.swift in Sources */, 55B234033036000100785053 /* RelationStore.swift in Sources */, 55B220013031000100784801 /* FeedbackVC.swift in Sources */, + 55CA15123058EC23000F1189 /* InteractionView.swift in Sources */, 55B220033031000100784803 /* FeedbackView.swift in Sources */, 55B220053031000100784805 /* FeedbackSuccessView.swift in Sources */, 55B221210000000100784821 /* MoodStatusVC.swift in Sources */, + 55CA150E3058E55E000F1189 /* ScheduleViewModel.swift in Sources */, 55B221230000000100784823 /* MoodStatusView.swift in Sources */, 55B222010000000100784831 /* AddEmojiPopView.swift in Sources */, 55B222030000000100784833 /* AddMessagePopView.swift in Sources */, @@ -2588,7 +2531,6 @@ 305A76C72FCA8C7000227D26 /* UserConfigModel.swift in Sources */, 30B74B472FF3608600F6744D /* ScheduleRecordModel.swift in Sources */, 305A76C82FCA8C7000227D26 /* UserConfigResponse.swift in Sources */, - 30ACD54C2FF6336000174861 /* PopupWindow.swift in Sources */, 305A76C92FCA8C7000227D26 /* ApiManager.swift in Sources */, 305A76CA2FCA8C7000227D26 /* AppSettings.swift in Sources */, 305A76CB2FCA8C7000227D26 /* Authorize.swift in Sources */, @@ -2596,7 +2538,6 @@ 30C6679E2FFB7FEF00E62B25 /* SharePopView.swift in Sources */, 305A76CC2FCA8C7000227D26 /* FileTools.swift in Sources */, 305A76CD2FCA8C7000227D26 /* Permission.swift in Sources */, - 30D74AB02FEA13ED0050EB2C /* ScheduleVC.swift in Sources */, 55B218B13024B00100784722 /* FeatureIntroVC.swift in Sources */, 55B218B13024B00100784724 /* FeatureIntroView.swift in Sources */, 305A76CE2FCA8C7000227D26 /* RouterManager.swift in Sources */, @@ -2641,7 +2582,6 @@ 55B250043038000100786504 /* MailboxView.swift in Sources */, 55B250063038000100786506 /* MailboxViewController.swift in Sources */, 55B250083038000100786508 /* MailboxDetailViewController.swift in Sources */, - 30D74AB22FEA1D5D0050EB2C /* ScheduleViewModel.swift in Sources */, 30EFF3B52FD8F1D000EB35D4 /* ReviewMemberListVC.swift in Sources */, 30BAB84D2FCD2FDE00C33B5C /* InviteJoinView.swift in Sources */, 30A87A592FEE5A4C0095E7C6 /* ScheduleViewedView.swift in Sources */, @@ -2649,10 +2589,7 @@ 30CCDE5C2FE3A1A800F5214A /* SOSPracticeView.swift in Sources */, 30EFF3E52FDAA93400EB35D4 /* PrivacyPolicyVC.swift in Sources */, 305A76E22FCA8C7000227D26 /* GroupViewModel.swift in Sources */, - 30CCDE4E2FE26CEA00F5214A /* PayResultPopVC.swift in Sources */, - 305A76E32FCA8C7000227D26 /* GroupMemberView.swift in Sources */, 30BAB84F2FCD2FED00C33B5C /* InviteJoinVC.swift in Sources */, - 305A76E42FCA8C7000227D26 /* HomeView.swift in Sources */, 305A76E52FCA8C7000227D26 /* HomeViewController.swift in Sources */, 305A76E62FCA8C7000227D26 /* LaunchViewController.swift in Sources */, 3062E8B52FCE6BBA00CEF511 /* ScanVC.swift in Sources */, @@ -2722,16 +2659,13 @@ 305A77032FCA8C7000227D26 /* ProgressHUD.swift in Sources */, 305A77042FCA8C7000227D26 /* MXParallaxHeader.m in Sources */, 305A77052FCA8C7000227D26 /* MXScrollView.m in Sources */, - 30D87CDD2FDFF07500E958FD /* InteractionView.swift in Sources */, 30BAB8652FCD718A00C33B5C /* JoinGroupView.swift in Sources */, 305A77062FCA8C7000227D26 /* MXScrollViewController.m in Sources */, 30B74B432FF2438800F6744D /* GroupMemberListView.swift in Sources */, 305A77072FCA8C7000227D26 /* Helper.swift in Sources */, 30BF30102FED0C8E00D9CB52 /* ScheduleDetailVM.swift in Sources */, - 30DA36BD2FECC5AB008D5A2C /* CreateScheduleVipPopView.swift in Sources */, 305A77082FCA8C7000227D26 /* PageCollectionViewFlowLayout.swift in Sources */, 55BF752D2FFE53F70055DA57 /* LocationPermissionPopView.swift in Sources */, - 3062E8C42FCFC90F00CEF511 /* CreateGroupVipPopView.swift in Sources */, 30D74ABA2FEA37AD0050EB2C /* ScheduleModel.swift in Sources */, 30CCDE512FE2785D00F5214A /* SignInVC.swift in Sources */, 305A77092FCA8C7000227D26 /* PageContentView.swift in Sources */, @@ -2739,7 +2673,6 @@ 305A770B2FCA8C7000227D26 /* PageTitleView.swift in Sources */, 305A770C2FCA8C7000227D26 /* PageView.swift in Sources */, 305A770D2FCA8C7000227D26 /* PageViewManager.swift in Sources */, - 30D891F52FE22E0600E958FD /* OrderAPI.swift in Sources */, 307073EA2FD2715A004C37CC /* GroupChatViewModel.swift in Sources */, 305A770E2FCA8C7000227D26 /* DLAlertPopVC.swift in Sources */, 305A770F2FCA8C7000227D26 /* DLCustomPopVC.swift in Sources */, @@ -2751,7 +2684,6 @@ 30EFF3B72FD8F86200EB35D4 /* ReviewMemberListVM.swift in Sources */, 305A77112FCA8C7000227D26 /* DLViewTransition.m in Sources */, 3062E8BA2FCEAC6500CEF511 /* CreateGroupView.swift in Sources */, - 30D891F72FE22E6E00E958FD /* OrderService.swift in Sources */, 305A77192FCA8C7000227D26 /* CollectionHFlowLayout.swift in Sources */, 30D74AC12FEA6EEF0050EB2C /* CreateSchedulePopView.swift in Sources */, 305A771A2FCA8C7000227D26 /* JJPageControl.swift in Sources */, @@ -2897,7 +2829,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 2; + CURRENT_PROJECT_VERSION = 3; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = LRDLWZ2Y83; ENABLE_USER_SCRIPT_SANDBOXING = "$(inherited)"; @@ -2952,7 +2884,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 2; + CURRENT_PROJECT_VERSION = 3; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = LRDLWZ2Y83; ENABLE_USER_SCRIPT_SANDBOXING = "$(inherited)"; @@ -3185,7 +3117,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 2; + CURRENT_PROJECT_VERSION = 3; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = LRDLWZ2Y83; ENABLE_USER_SCRIPT_SANDBOXING = "$(inherited)"; diff --git a/QuickLocation/API/APIProvider.swift b/QuickLocation/API/APIProvider.swift index e3665689..9d0996b2 100644 --- a/QuickLocation/API/APIProvider.swift +++ b/QuickLocation/API/APIProvider.swift @@ -151,12 +151,6 @@ enum GatewayStatusCode: Int { // 审核中 case review = 201 - /** ============== 业务 ============== */ - // 需要开通vip - case needVip = 20000 - // 您创建的圈子个数已达上限,请升级会员等级 - case groupLimit = 20009 - /** ============== 未知错误 ============== */ case unknownError = -9999 } diff --git a/QuickLocation/API/OrderAPI.swift b/QuickLocation/API/OrderAPI.swift deleted file mode 100644 index 81435bfa..00000000 --- a/QuickLocation/API/OrderAPI.swift +++ /dev/null @@ -1,77 +0,0 @@ -// -// OrderAPI.swift -// QuickLocation -// -// Created by 八条 on 2026/6/17. -// - -import Moya -import SwiftyUserDefaults -internal import Alamofire - -/// 订单API -enum OrderAPI { - /// 充值内容 - /// - Parameters: - /// - type: 类型 member - case rechargeInfo(type: String) - - /// 支付参数 - /// - Parameters: - /// - goodsId: 商品ID - /// - payType: alipay、weixin - /// - source: center - /// - extra: 额外参数 - case orderPayParams(goodsId: String, payType: String, source: String, extra: [String:Any]=[:]) - - /// Apple 内购通知 - case appleNotify(receipt: String, productId: String, transactionId: String) -} - -extension OrderAPI: MultiTargetProtocol { - - var path: String { - switch self { - case .rechargeInfo: - return "api/order/goods" - case .orderPayParams: - return "api/order" - case .appleNotify: - return "api/order/notify/apple" - } - } - - var method: Moya.Method { - switch self { - case .rechargeInfo: - return .get - default: - return .post - } - } - - var task: Moya.Task { - switch self { - case let .rechargeInfo(type): - var params = Parameters() - params["type"] = type - return .requestParameters(parameters: params, encoding: URLEncoding()) - - case let .orderPayParams(goodsId, payType, source, extra): - var params = Parameters() - params["goods_id"] = goodsId - params["pay_type"] = payType - params["source"] = source - params["pay_source"] = "app" - params["extra"] = extra - return .requestParameters(parameters: params, encoding: JSONEncoding()) - - case let .appleNotify(receipt, productId, transactionId): - var params = Parameters() - params["receipt_data"] = receipt - params["product_id"] = productId - params["transaction_id"] = transactionId - return .requestParameters(parameters: params, encoding: JSONEncoding()) - } - } -} diff --git a/QuickLocation/AppDelegate.swift b/QuickLocation/AppDelegate.swift index 619fb277..5537a9d8 100644 --- a/QuickLocation/AppDelegate.swift +++ b/QuickLocation/AppDelegate.swift @@ -38,8 +38,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate { SwiftDate.defaultRegion = Region(zone: TimeZone.current, locale: Locale.current) - IAPManager.shared.startObserving() - IQKeyboardManager.shared.isEnabled = true IQKeyboardManager.shared.enableAutoToolbar = false IQKeyboardManager.shared.resignOnTouchOutside = true @@ -91,25 +89,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { return true } } - - // 处理支付宝支付结果(不限制 host,适应新版 SDK) - if url.scheme?.hasPrefix("Alipay") == true || url.host == "safepay" { - AlipaySDK.defaultService().processOrder(withPaymentResult: url) { resultDic in - print("📱 Alipay callback: \(resultDic ?? [:])") - guard let result = resultDic, - let resultStatus = result["resultStatus"] as? String, - resultStatus != "6001" else { return } - if resultStatus == "9000" { - NotificationCenter.default.post(name: .RequestOrderPayStatusNotification, object: nil) - } - } - return true - } -// else if url.host == "pay" { - return WXApi.handleOpen(url, delegate: self) -// } -// -// return true + return WXApi.handleOpen(url, delegate: self) } func application(_ application: UIApplication, @@ -197,22 +177,5 @@ extension AppDelegate: WXApiDelegate { handleWechatLoginCode(code) return } - - if resp.isKind(of: SendAuthResp.self) { - NotificationCenter.default.post(name: .resumePopupQueue, object: nil) - } - - if resp.isKind(of: PayResp.self), - let response: PayResp = resp as? PayResp { - print("===================== WxPay =====================") - print(response.errStr) - if response.errCode == 0 { // 支付成功 - DispatchQueue.global().async { - DispatchQueue.main.async { - - } - } - } - } } } diff --git a/QuickLocation/Assets.xcassets/Bubble/upgrade_bg.imageset/Contents.json b/QuickLocation/Assets.xcassets/Bubble/upgrade_bg.imageset/Contents.json deleted file mode 100644 index a19a5492..00000000 --- a/QuickLocation/Assets.xcassets/Bubble/upgrade_bg.imageset/Contents.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/QuickLocation/Assets.xcassets/Bubble/vip_pop.imageset/Contents.json b/QuickLocation/Assets.xcassets/Bubble/vip_pop.imageset/Contents.json deleted file mode 100644 index a19a5492..00000000 --- a/QuickLocation/Assets.xcassets/Bubble/vip_pop.imageset/Contents.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/QuickLocation/Assets.xcassets/Group/upgrade_bg.imageset/Contents.json b/QuickLocation/Assets.xcassets/Group/upgrade_bg.imageset/Contents.json deleted file mode 100644 index a19a5492..00000000 --- a/QuickLocation/Assets.xcassets/Group/upgrade_bg.imageset/Contents.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/QuickLocation/Assets.xcassets/Group/vip_pop.imageset/Contents.json b/QuickLocation/Assets.xcassets/Group/vip_pop.imageset/Contents.json deleted file mode 100644 index a19a5492..00000000 --- a/QuickLocation/Assets.xcassets/Group/vip_pop.imageset/Contents.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/QuickLocation/Assets.xcassets/GroupMemberList/vip.imageset/Contents.json b/QuickLocation/Assets.xcassets/GroupMemberList/vip.imageset/Contents.json deleted file mode 100644 index a19a5492..00000000 --- a/QuickLocation/Assets.xcassets/GroupMemberList/vip.imageset/Contents.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/QuickLocation/Assets.xcassets/Guide/guide_1.imageset/Contents.json b/QuickLocation/Assets.xcassets/Guide/guide_1.imageset/Contents.json deleted file mode 100644 index 74408af2..00000000 --- a/QuickLocation/Assets.xcassets/Guide/guide_1.imageset/Contents.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "Group_2040@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "Group_2040@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/QuickLocation/Assets.xcassets/Guide/guide_1.imageset/Group_2040@2x.png b/QuickLocation/Assets.xcassets/Guide/guide_1.imageset/Group_2040@2x.png deleted file mode 100644 index ddc6f621..00000000 Binary files a/QuickLocation/Assets.xcassets/Guide/guide_1.imageset/Group_2040@2x.png and /dev/null differ diff --git a/QuickLocation/Assets.xcassets/Guide/guide_1.imageset/Group_2040@3x.png b/QuickLocation/Assets.xcassets/Guide/guide_1.imageset/Group_2040@3x.png deleted file mode 100644 index b790eeb9..00000000 Binary files a/QuickLocation/Assets.xcassets/Guide/guide_1.imageset/Group_2040@3x.png and /dev/null differ diff --git a/QuickLocation/Assets.xcassets/Guide/guide_2.imageset/Contents.json b/QuickLocation/Assets.xcassets/Guide/guide_2.imageset/Contents.json deleted file mode 100644 index bb8a43d6..00000000 --- a/QuickLocation/Assets.xcassets/Guide/guide_2.imageset/Contents.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "Group_2041@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "Group_2041@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/QuickLocation/Assets.xcassets/Guide/guide_2.imageset/Group_2041@2x.png b/QuickLocation/Assets.xcassets/Guide/guide_2.imageset/Group_2041@2x.png deleted file mode 100644 index 0c6514a9..00000000 Binary files a/QuickLocation/Assets.xcassets/Guide/guide_2.imageset/Group_2041@2x.png and /dev/null differ diff --git a/QuickLocation/Assets.xcassets/Guide/guide_2.imageset/Group_2041@3x.png b/QuickLocation/Assets.xcassets/Guide/guide_2.imageset/Group_2041@3x.png deleted file mode 100644 index dcec37b6..00000000 Binary files a/QuickLocation/Assets.xcassets/Guide/guide_2.imageset/Group_2041@3x.png and /dev/null differ diff --git a/QuickLocation/Assets.xcassets/Guide/guide_3.imageset/Contents.json b/QuickLocation/Assets.xcassets/Guide/guide_3.imageset/Contents.json deleted file mode 100644 index 7fba5ace..00000000 --- a/QuickLocation/Assets.xcassets/Guide/guide_3.imageset/Contents.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "Group_2042@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "Group_2042@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/QuickLocation/Assets.xcassets/Guide/guide_3.imageset/Group_2042@2x.png b/QuickLocation/Assets.xcassets/Guide/guide_3.imageset/Group_2042@2x.png deleted file mode 100644 index 1ccb32e6..00000000 Binary files a/QuickLocation/Assets.xcassets/Guide/guide_3.imageset/Group_2042@2x.png and /dev/null differ diff --git a/QuickLocation/Assets.xcassets/Guide/guide_3.imageset/Group_2042@3x.png b/QuickLocation/Assets.xcassets/Guide/guide_3.imageset/Group_2042@3x.png deleted file mode 100644 index 8e249f08..00000000 Binary files a/QuickLocation/Assets.xcassets/Guide/guide_3.imageset/Group_2042@3x.png and /dev/null differ diff --git a/QuickLocation/Assets.xcassets/Guide/guide_4.imageset/Contents.json b/QuickLocation/Assets.xcassets/Guide/guide_4.imageset/Contents.json deleted file mode 100644 index 3a3637c7..00000000 --- a/QuickLocation/Assets.xcassets/Guide/guide_4.imageset/Contents.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "Group_2043@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "Group_2043@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/QuickLocation/Assets.xcassets/Guide/guide_4.imageset/Group_2043@2x.png b/QuickLocation/Assets.xcassets/Guide/guide_4.imageset/Group_2043@2x.png deleted file mode 100644 index 75f0b8b5..00000000 Binary files a/QuickLocation/Assets.xcassets/Guide/guide_4.imageset/Group_2043@2x.png and /dev/null differ diff --git a/QuickLocation/Assets.xcassets/Guide/guide_4.imageset/Group_2043@3x.png b/QuickLocation/Assets.xcassets/Guide/guide_4.imageset/Group_2043@3x.png deleted file mode 100644 index d4b8f7d5..00000000 Binary files a/QuickLocation/Assets.xcassets/Guide/guide_4.imageset/Group_2043@3x.png and /dev/null differ diff --git a/QuickLocation/Assets.xcassets/Guide/guide_5.imageset/Contents.json b/QuickLocation/Assets.xcassets/Guide/guide_5.imageset/Contents.json deleted file mode 100644 index 14e39f8b..00000000 --- a/QuickLocation/Assets.xcassets/Guide/guide_5.imageset/Contents.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "Group_2044@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "Group_2044@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/QuickLocation/Assets.xcassets/Guide/guide_5.imageset/Group_2044@2x.png b/QuickLocation/Assets.xcassets/Guide/guide_5.imageset/Group_2044@2x.png deleted file mode 100644 index 194ff1d4..00000000 Binary files a/QuickLocation/Assets.xcassets/Guide/guide_5.imageset/Group_2044@2x.png and /dev/null differ diff --git a/QuickLocation/Assets.xcassets/Guide/guide_5.imageset/Group_2044@3x.png b/QuickLocation/Assets.xcassets/Guide/guide_5.imageset/Group_2044@3x.png deleted file mode 100644 index 77536622..00000000 Binary files a/QuickLocation/Assets.xcassets/Guide/guide_5.imageset/Group_2044@3x.png and /dev/null differ diff --git a/QuickLocation/Assets.xcassets/Home/HistoryTrack/vip_required.imageset/Contents.json b/QuickLocation/Assets.xcassets/Home/HistoryTrack/vip_required.imageset/Contents.json deleted file mode 100644 index a19a5492..00000000 --- a/QuickLocation/Assets.xcassets/Home/HistoryTrack/vip_required.imageset/Contents.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/QuickLocation/Assets.xcassets/MemberVipRequired/Contents.json b/QuickLocation/Assets.xcassets/MemberVipRequired/Contents.json deleted file mode 100644 index 6e965652..00000000 --- a/QuickLocation/Assets.xcassets/MemberVipRequired/Contents.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "info" : { - "author" : "xcode", - "version" : 1 - }, - "properties" : { - "provides-namespace" : true - } -} diff --git a/QuickLocation/Assets.xcassets/MemberVipRequired/app_usage.imageset/Contents.json b/QuickLocation/Assets.xcassets/MemberVipRequired/app_usage.imageset/Contents.json deleted file mode 100644 index a19a5492..00000000 --- a/QuickLocation/Assets.xcassets/MemberVipRequired/app_usage.imageset/Contents.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/QuickLocation/Assets.xcassets/MemberVipRequired/phone_report.imageset/Contents.json b/QuickLocation/Assets.xcassets/MemberVipRequired/phone_report.imageset/Contents.json deleted file mode 100644 index a19a5492..00000000 --- a/QuickLocation/Assets.xcassets/MemberVipRequired/phone_report.imageset/Contents.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/QuickLocation/Assets.xcassets/MemberVipRequired/today_track.imageset/Contents.json b/QuickLocation/Assets.xcassets/MemberVipRequired/today_track.imageset/Contents.json deleted file mode 100644 index adfee5fa..00000000 --- a/QuickLocation/Assets.xcassets/MemberVipRequired/today_track.imageset/Contents.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "today_track@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "today_track@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/QuickLocation/Assets.xcassets/MemberVipRequired/today_track.imageset/today_track@2x.png b/QuickLocation/Assets.xcassets/MemberVipRequired/today_track.imageset/today_track@2x.png deleted file mode 100644 index 045a8200..00000000 Binary files a/QuickLocation/Assets.xcassets/MemberVipRequired/today_track.imageset/today_track@2x.png and /dev/null differ diff --git a/QuickLocation/Assets.xcassets/MemberVipRequired/today_track.imageset/today_track@3x.png b/QuickLocation/Assets.xcassets/MemberVipRequired/today_track.imageset/today_track@3x.png deleted file mode 100644 index 5b54a324..00000000 Binary files a/QuickLocation/Assets.xcassets/MemberVipRequired/today_track.imageset/today_track@3x.png and /dev/null differ diff --git a/QuickLocation/Assets.xcassets/Mine/vip_card.imageset/Contents.json b/QuickLocation/Assets.xcassets/Mine/vip_card.imageset/Contents.json deleted file mode 100644 index a19a5492..00000000 --- a/QuickLocation/Assets.xcassets/Mine/vip_card.imageset/Contents.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/QuickLocation/Assets.xcassets/Schedule/upgrade_bg.imageset/Contents.json b/QuickLocation/Assets.xcassets/Schedule/upgrade_bg.imageset/Contents.json deleted file mode 100644 index 379ba423..00000000 --- a/QuickLocation/Assets.xcassets/Schedule/upgrade_bg.imageset/Contents.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "按钮@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "按钮@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/QuickLocation/Assets.xcassets/Schedule/upgrade_bg.imageset/按钮@2x.png b/QuickLocation/Assets.xcassets/Schedule/upgrade_bg.imageset/按钮@2x.png deleted file mode 100644 index 03245e7f..00000000 Binary files a/QuickLocation/Assets.xcassets/Schedule/upgrade_bg.imageset/按钮@2x.png and /dev/null differ diff --git a/QuickLocation/Assets.xcassets/Schedule/upgrade_bg.imageset/按钮@3x.png b/QuickLocation/Assets.xcassets/Schedule/upgrade_bg.imageset/按钮@3x.png deleted file mode 100644 index 0017676d..00000000 Binary files a/QuickLocation/Assets.xcassets/Schedule/upgrade_bg.imageset/按钮@3x.png and /dev/null differ diff --git a/QuickLocation/Assets.xcassets/Schedule/vip_pop.imageset/Contents.json b/QuickLocation/Assets.xcassets/Schedule/vip_pop.imageset/Contents.json deleted file mode 100644 index a19a5492..00000000 --- a/QuickLocation/Assets.xcassets/Schedule/vip_pop.imageset/Contents.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/QuickLocation/Assets.xcassets/SearchLocation/vip_mask.imageset/Contents.json b/QuickLocation/Assets.xcassets/SearchLocation/vip_mask.imageset/Contents.json deleted file mode 100644 index a19a5492..00000000 --- a/QuickLocation/Assets.xcassets/SearchLocation/vip_mask.imageset/Contents.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/QuickLocation/Assets.xcassets/VipFeature/Contents.json b/QuickLocation/Assets.xcassets/VipFeature/Contents.json deleted file mode 100644 index 6e965652..00000000 --- a/QuickLocation/Assets.xcassets/VipFeature/Contents.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "info" : { - "author" : "xcode", - "version" : 1 - }, - "properties" : { - "provides-namespace" : true - } -} diff --git a/QuickLocation/Assets.xcassets/VipFeature/crown.imageset/Contents.json b/QuickLocation/Assets.xcassets/VipFeature/crown.imageset/Contents.json deleted file mode 100644 index afbb3108..00000000 --- a/QuickLocation/Assets.xcassets/VipFeature/crown.imageset/Contents.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "crown@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "crown@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/QuickLocation/Assets.xcassets/VipFeature/crown.imageset/crown@2x.png b/QuickLocation/Assets.xcassets/VipFeature/crown.imageset/crown@2x.png deleted file mode 100644 index aac3c219..00000000 Binary files a/QuickLocation/Assets.xcassets/VipFeature/crown.imageset/crown@2x.png and /dev/null differ diff --git a/QuickLocation/Assets.xcassets/VipFeature/crown.imageset/crown@3x.png b/QuickLocation/Assets.xcassets/VipFeature/crown.imageset/crown@3x.png deleted file mode 100644 index 6cdddf78..00000000 Binary files a/QuickLocation/Assets.xcassets/VipFeature/crown.imageset/crown@3x.png and /dev/null differ diff --git a/QuickLocation/Assets.xcassets/VipFeature/limited_offer.imageset/Contents.json b/QuickLocation/Assets.xcassets/VipFeature/limited_offer.imageset/Contents.json deleted file mode 100644 index a19a5492..00000000 --- a/QuickLocation/Assets.xcassets/VipFeature/limited_offer.imageset/Contents.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/QuickLocation/Assets.xcassets/VipFeature/media_locked_bg.imageset/Contents.json b/QuickLocation/Assets.xcassets/VipFeature/media_locked_bg.imageset/Contents.json deleted file mode 100644 index a19a5492..00000000 --- a/QuickLocation/Assets.xcassets/VipFeature/media_locked_bg.imageset/Contents.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/QuickLocation/Assets.xcassets/VipFeature/narrow_button_bg.imageset/Contents.json b/QuickLocation/Assets.xcassets/VipFeature/narrow_button_bg.imageset/Contents.json deleted file mode 100644 index ef02356a..00000000 --- a/QuickLocation/Assets.xcassets/VipFeature/narrow_button_bg.imageset/Contents.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "narrow_button_bg@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "narrow_button_bg@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/QuickLocation/Assets.xcassets/VipFeature/narrow_button_bg.imageset/narrow_button_bg@2x.png b/QuickLocation/Assets.xcassets/VipFeature/narrow_button_bg.imageset/narrow_button_bg@2x.png deleted file mode 100644 index 03e861eb..00000000 Binary files a/QuickLocation/Assets.xcassets/VipFeature/narrow_button_bg.imageset/narrow_button_bg@2x.png and /dev/null differ diff --git a/QuickLocation/Assets.xcassets/VipFeature/narrow_button_bg.imageset/narrow_button_bg@3x.png b/QuickLocation/Assets.xcassets/VipFeature/narrow_button_bg.imageset/narrow_button_bg@3x.png deleted file mode 100644 index d4e14d2c..00000000 Binary files a/QuickLocation/Assets.xcassets/VipFeature/narrow_button_bg.imageset/narrow_button_bg@3x.png and /dev/null differ diff --git a/QuickLocation/Assets.xcassets/VipFeature/realtime_location.imageset/Contents.json b/QuickLocation/Assets.xcassets/VipFeature/realtime_location.imageset/Contents.json deleted file mode 100644 index a19a5492..00000000 --- a/QuickLocation/Assets.xcassets/VipFeature/realtime_location.imageset/Contents.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/QuickLocation/Assets.xcassets/VipFeature/wide_button_bg.imageset/Contents.json b/QuickLocation/Assets.xcassets/VipFeature/wide_button_bg.imageset/Contents.json deleted file mode 100644 index cd8c1585..00000000 --- a/QuickLocation/Assets.xcassets/VipFeature/wide_button_bg.imageset/Contents.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "wide_button_bg@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "wide_button_bg@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/QuickLocation/Assets.xcassets/VipFeature/wide_button_bg.imageset/wide_button_bg@2x.png b/QuickLocation/Assets.xcassets/VipFeature/wide_button_bg.imageset/wide_button_bg@2x.png deleted file mode 100644 index 5f8d3628..00000000 Binary files a/QuickLocation/Assets.xcassets/VipFeature/wide_button_bg.imageset/wide_button_bg@2x.png and /dev/null differ diff --git a/QuickLocation/Assets.xcassets/VipFeature/wide_button_bg.imageset/wide_button_bg@3x.png b/QuickLocation/Assets.xcassets/VipFeature/wide_button_bg.imageset/wide_button_bg@3x.png deleted file mode 100644 index ea8d7489..00000000 Binary files a/QuickLocation/Assets.xcassets/VipFeature/wide_button_bg.imageset/wide_button_bg@3x.png and /dev/null differ diff --git a/QuickLocation/Manager/Account/AppContextManager.swift b/QuickLocation/Manager/Account/AppContextManager.swift index bc9e50ef..7d96b6af 100644 --- a/QuickLocation/Manager/Account/AppContextManager.swift +++ b/QuickLocation/Manager/Account/AppContextManager.swift @@ -62,14 +62,7 @@ class AppContextManager: NSObject { var sex: Int { account?.sex ?? -1 } - - /// 会员 1:非会员 2:普通会员 3:终身会员 - var vip: Int { - guard AppContextManager.shared.systemConfig?.isIntercept == false else { - return 2 - } - return account?.vip ?? 1 - } + /// 状态:0、无状态 1、SOS 2、气泡等 var status: Int { account?.status ?? 0 diff --git a/QuickLocation/Manager/Account/UserConfigModel.swift b/QuickLocation/Manager/Account/UserConfigModel.swift index e130421e..2f4c1258 100644 --- a/QuickLocation/Manager/Account/UserConfigModel.swift +++ b/QuickLocation/Manager/Account/UserConfigModel.swift @@ -32,12 +32,6 @@ struct UserConfigModel: Mappable { /// 用户 ID var uid: String? - /// 会员 1:非会员 2:普通会员 3:终身会员 - var vip: Int = 1 - /// 会员类型 - var vip_name: String = "" - /// 会员过期时间 - var vip_expire_time: String = "" /// 状态:0、无状态 1、SOS 2、气泡等 var status: Int = 0 /// 心情:0、无状态 1、开心 2、愤怒 @@ -59,9 +53,6 @@ struct UserConfigModel: Mappable { sex <- map["sex"] head_pic <- (map["head_pic"], kFlexString) config <- map["config"] - vip <- map["vip"] - vip_name <- map["vip_name"] - vip_expire_time <- map["vip_expire_time"] status <- map["status"] mood <- map["mood"] } @@ -70,9 +61,9 @@ struct UserConfigModel: Mappable { struct SystemConfigModel: Mappable { /// 弹窗配置 - var popupConfig: PopupWindowConfigModel? +// var popupConfig: PopupWindowConfigModel? /// 弹窗时间配置 - var timeConfig: PopupWindowTimeModel? +// var timeConfig: PopupWindowTimeModel? /// 微信分享配置 var shareConfig: WxShareConfigModel? /// 飞鸽传书发送次数 @@ -89,17 +80,6 @@ struct SystemConfigModel: Mappable { /// 圈子里的banner var groupBannerList: [String] = [] - /// 引导页显示开关 - var guideDisplay: Bool = true - - /// 全局控制显示隐藏 弹窗和充值 - var globalDisplay: Bool = true - - /// 是否拦截 - var isIntercept: Bool { - return globalDisplay == false || !WXApi.isWXAppInstalled() // 未安装微信 - } - init?(map: Map) { } @@ -107,63 +87,14 @@ struct SystemConfigModel: Mappable { mutating func mapping(map: Map) { chatWarning <- map["client.chatwarning", nested: false] groupBannerList <- map["client.team.ad", nested: false] - popupConfig <- map["client.popup.display", nested: false] - timeConfig <- map["client.time.setting", nested: false] +// timeConfig <- map["client.time.setting", nested: false] pigeonConfig <- map["client.time.setting.pigeon", nested: false] shareConfig <- map["client.weixin.share", nested: false] - guideDisplay <- map["client.guide_display", nested: false] - globalDisplay <- map["client.global_display", nested: false] versionUpgradeModel <- map["client.version.upgrade", nested: false] bannerList <- map["client.banner.explore", nested: false] } } -struct PopupWindowConfigModel: Mappable { - /// 是否弹vip弹窗 - var pay_pop: Bool = true - - /// 搜索位置弹窗 - var search_phone: Bool = true - - - init?(map: Map) { - - } - - mutating func mapping(map: Map) { - pay_pop <- map["pay_pop"] - search_phone <- map["search_phone"] - } -} - -struct PopupWindowTimeModel: Mappable { - /// 会员充值push倒计时 - var buy_vip_tip: Int = 0 - /// 搜索位置 倒计时(秒) - var search_phone: Int = 0 - /// 注册提示 - var signup_tip: Int = 0 - /// vip提示倒计时(秒) - var pay_pop_time: Int = 0 - /// vip折扣 - var min_discount: Double = 0 - /// 默认支付方式 1 支付宝 2 微信 - var pay_pop_type: Int = 0 - - init?(map: Map) { - - } - - mutating func mapping(map: Map) { - buy_vip_tip <- map["buy_vip_tip"] - search_phone <- map["search_phone"] - signup_tip <- map["signup_tip"] - pay_pop_time <- map["pay_pop_time"] - min_discount <- map["min_discount"] - pay_pop_type <- map["pay_pop_type"] - } -} - struct PigeonTimeSettingModel: Mappable { /// 时间窗口内最多发送次数 var nums: Int = 0 @@ -237,7 +168,7 @@ struct VersionUpgradeModel: Mappable { struct BannerConfigModel: Mappable { /// 图片地址 var img: String = "" - /// url:member跳充值页 url:网页地址 + /// url:member跳cz页 url:网页地址 var url: String = "" /// app:原生应用内跳转 web:跳转网页 var type: String = "" diff --git a/QuickLocation/Manager/App/ApiManager.swift b/QuickLocation/Manager/App/ApiManager.swift index 5554515b..b96f30a0 100644 --- a/QuickLocation/Manager/App/ApiManager.swift +++ b/QuickLocation/Manager/App/ApiManager.swift @@ -114,8 +114,6 @@ extension ApiManager { handleTokenExpired(msg: message) case GatewayStatusCode.failure.rawValue, GatewayStatusCode.noAuthority.rawValue: // 退出当前界面 handlePopView(message, handle) - case GatewayStatusCode.needVip.rawValue: - handleNeedVip(message) default: // 接口没返回code的时候取success字段 if success != nil { @@ -136,7 +134,6 @@ extension ApiManager { return .failure(handleError(with: code, domain: "Data Error", message: message, - isShowTip: code != GatewayStatusCode.needVip.rawValue, data: response)) case let .failure(error): let message = error.gatewayMessage ?? "请检查网络连接" @@ -197,14 +194,6 @@ extension ApiManager { } } - // MARK: - 需开通VIP - private func handleNeedVip(_ msg: String) { - MainAsync { - UIViewController.showConfirmPop(title: "温馨提示", message: msg, confirmText: "去开通", confirmBlock: { - AppRouter.push(Route.web, userInfo: ["url": URLManager.shared.homeUrl]) - }, cancelText: "取消") - } - } } extension ApiManager { diff --git a/QuickLocation/Manager/IAPManager/IAPManager.swift b/QuickLocation/Manager/IAPManager/IAPManager.swift deleted file mode 100644 index f72fee1e..00000000 --- a/QuickLocation/Manager/IAPManager/IAPManager.swift +++ /dev/null @@ -1,81 +0,0 @@ -// -// IAPManager.swift -// QuickLocation -// -// Created by 八条 on 2026/7/3. -// - -import StoreKit -import RxSwift - -class IAPManager: NSObject { - static let shared = IAPManager() - private let disposeBag = DisposeBag() - - private var currentGoodsId: String = "" - private var purchaseCompletion: ((Bool, String?) -> Void)? - - func startObserving() { - SKPaymentQueue.default().add(self) - } - - func purchase(goodsId: String, completion: @escaping (Bool, String?) -> Void) { - currentGoodsId = goodsId - purchaseCompletion = completion - let request = SKProductsRequest(productIdentifiers: [goodsId]) - request.delegate = self - request.start() - } -} - -// MARK: - SKProductsRequestDelegate -extension IAPManager: SKProductsRequestDelegate { - func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) { - guard let product = response.products.first else { - purchaseCompletion?(false, "商品不可用") - return - } - SKPaymentQueue.default().add(SKPayment(product: product)) - } -} - -// MARK: - SKPaymentTransactionObserver -extension IAPManager: SKPaymentTransactionObserver { - func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) { - for tx in transactions { - switch tx.transactionState { - case .purchased: - verifyReceipt(transaction: tx) - case .failed: - queue.finishTransaction(tx) - let msg = tx.error?.localizedDescription ?? "支付失败" - purchaseCompletion?(false, msg) - default: - break - } - } - } - - private func verifyReceipt(transaction: SKPaymentTransaction) { - guard let receiptURL = Bundle.main.appStoreReceiptURL, - let receiptData = try? Data(contentsOf: receiptURL) else { - SKPaymentQueue.default().finishTransaction(transaction) - purchaseCompletion?(false, "获取凭证失败") - return - } - let receipt = receiptData.base64EncodedString() - let txId = transaction.transactionIdentifier ?? "" - - OrderService.appleNotify( - receipt: receipt, - productId: currentGoodsId, - transactionId: txId - ).subscribe(onNext: { [weak self] _ in - SKPaymentQueue.default().finishTransaction(transaction) - self?.purchaseCompletion?(true, nil) - }, onError: { [weak self] error in - SKPaymentQueue.default().finishTransaction(transaction) - self?.purchaseCompletion?(false, error.localizedDescription) - }).disposed(by: disposeBag) - } -} diff --git a/QuickLocation/Model/GroupModel.swift b/QuickLocation/Model/GroupModel.swift index 088bf3b2..d0515c1d 100644 --- a/QuickLocation/Model/GroupModel.swift +++ b/QuickLocation/Model/GroupModel.swift @@ -92,7 +92,6 @@ struct GroupUsersResponse: BaseModelProtocol { var message: String? var model: GroupInfoModel? var list: [GroupMemberModel] = [] - var vip = GroupMemberVip() var reviewCount: Int = 0 init?(map: Map) {} @@ -102,7 +101,6 @@ struct GroupUsersResponse: BaseModelProtocol { message <- map["message"] model <- map["data.group"] list <- map["data.mates"] - vip <- map["data.vip"] reviewCount <- (map["data.reviewCount"], kStrTransformInt) if reviewCount == 0 { reviewCount <- (map["data.review_count"], kStrTransformInt) @@ -231,7 +229,7 @@ struct GroupInfoModel: Mappable, Equatable { var people_no: Int = 0 /// 描述 var description: String = "" - /// 会员等级 + /// 等级 var level: String = "" /// 邀请码 var share_code: String = "" @@ -288,27 +286,6 @@ struct GroupPrivilege: Mappable, Equatable { } } -struct GroupMemberVip: Mappable, Equatable { - var app_usage_record: Bool? - var phone_report: Bool? - var trip_analysis_others: Bool? - var app_lock: Bool? - var pigeon_mail: Bool? - var view_phone: Bool? - - init() {} - init?(map: Map) {} - - mutating func mapping(map: Map) { - app_usage_record <- (map["app_usage_record"], kOptionalFlexibleBool) - phone_report <- (map["phone_report"], kOptionalFlexibleBool) - trip_analysis_others <- (map["trip_analysis_others"], kOptionalFlexibleBool) - app_lock <- (map["app_lock"], kOptionalFlexibleBool) - pigeon_mail <- (map["pigeon_mail"], kOptionalFlexibleBool) - view_phone <- (map["view_phone"], kOptionalFlexibleBool) - } -} - private let kFlexibleBool = TransformOf(fromJSON: { value in switch value { case let value as Bool: @@ -327,31 +304,6 @@ private let kFlexibleBool = TransformOf(fromJSON: { value in value }) -private let kOptionalFlexibleBool = TransformOf(fromJSON: { value in - switch value { - case let value as Bool: - return value - case let value as NSNumber: - return value.boolValue - case let value as Int: - return value != 0 - case let value as String: - let text = value.trimmingCharacters(in: .whitespacesAndNewlines).lowercased() - switch text { - case "1", "true", "yes": - return true - case "0", "false", "no": - return false - default: - return nil - } - default: - return nil - } -}, toJSON: { value in - value -}) - extension UIImageView { @MainActor func setGroupIcon(_ model: GroupInfoModel) { @@ -470,11 +422,6 @@ struct GroupMemberModel: Mappable, Equatable { remark.isEmpty ? nick_name : remark } - /// 会员等级 1普通 2白银 3永久 4钻石 - var level: Int = 1 - var shouldShowVipAvatarFrame: Bool { - AppContextManager.shared.systemConfig?.isIntercept != true && level != 1 - } /// 状态:0、无状态 1、SOS 2、气泡等 var status: Int = 0 /// 入圈天数(若服务端下发) @@ -530,7 +477,6 @@ struct GroupMemberModel: Mappable, Equatable { if avater.isEmpty { avater <- (map["avatar"], kFlexString) } - level <- (map["level"], kStrTransformInt) nick_name <- map["nick_name"] remark <- map["remark"] battery <- map["battery"] diff --git a/QuickLocation/Resource/lotties/dialog_buy_vip_3.json b/QuickLocation/Resource/lotties/dialog_buy_vip_3.json deleted file mode 100644 index e0e28396..00000000 --- a/QuickLocation/Resource/lotties/dialog_buy_vip_3.json +++ /dev/null @@ -1 +0,0 @@ -{"v":"5.12.1","fr":25,"ip":0,"op":110,"w":375,"h":375,"nm":"合成 1","ddd":0,"assets":[{"id":"image_0","w":480,"h":480,"u":"images/","p":"dialog_buy_vip3_img_0.png","e":0},{"id":"image_1","w":192,"h":160,"u":"images/","p":"dialog_buy_vip3_img_1.png","e":0}],"layers":[{"ddd":0,"ind":1,"ty":2,"nm":"image 112.png","cl":"png","refId":"image_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":0,"s":[306,117.5,0],"to":[0,0,0],"ti":[117,4,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":18.462,"s":[226,248,0],"to":[-117,-4,0],"ti":[-39.5,36,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":36.923,"s":[125,136,0],"to":[6.063,-5.526,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":55.385,"s":[232.5,144,0],"to":[0,0,0],"ti":[140.5,-22,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":73.846,"s":[167.5,284,0],"to":[-140.5,22,0],"ti":[-39.436,13.632,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":92.308,"s":[73.5,227,0],"to":[40.5,-14,0],"ti":[-22,-19,0]},{"t":110.76953125,"s":[212.5,285.5,0]}],"ix":2,"l":2},"a":{"a":0,"k":[243.995,243.45,0],"ix":1,"l":2},"s":{"a":0,"k":[11.792,11.792,100],"ix":6,"l":2}},"ao":1,"ip":0,"op":126,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":2,"nm":"图层 30 1.png","cl":"png","refId":"image_1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":0,"s":[195,210.5,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":18.445,"s":[195,181.5,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":22,"s":[195,197.089,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":36.892,"s":[195,210.5,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":55.337,"s":[195,181.5,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":73.783,"s":[195,210.5,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":92.229,"s":[195,181.5,0],"to":[0,0,0],"ti":[0,0,0]},{"t":110.673828125,"s":[195,210.5,0]}],"ix":2,"l":2},"a":{"a":0,"k":[96,80,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"ip":0,"op":126,"st":0,"bm":0}],"markers":[],"props":{}} \ No newline at end of file diff --git a/QuickLocation/Section/Explore/FeatureIntroVC.swift b/QuickLocation/Section/Explore/FeatureIntroVC.swift index 3a406c11..84ffca6e 100644 --- a/QuickLocation/Section/Explore/FeatureIntroVC.swift +++ b/QuickLocation/Section/Explore/FeatureIntroVC.swift @@ -35,8 +35,7 @@ final class FeatureIntroVC: BaseViewController { super.viewDidAppear(animated) rootView.reloadFeatureItems() - guard AppContextManager.shared.systemConfig?.isIntercept == false, - let config = AppContextManager.shared.systemConfig else { return } + guard let config = AppContextManager.shared.systemConfig else { return } bannerList = config.bannerList rootView.cycleScrollView.isHidden = config.bannerList.filter { $0.enable == true }.count == 0 rootView.cycleScrollView.imageURLStringsGroup = config.bannerList.filter { $0.enable == true }.map { $0.img } @@ -58,7 +57,6 @@ final class FeatureIntroVC: BaseViewController { case .pigeonMessage: AppRouter.push(Route.pigeonMessage) case .searchLocation: - guard AppContextManager.shared.systemConfig?.isIntercept != true else { return } AppRouter.push(Route.searchLocation) case .sos: AppRouter.push(Route.sos) diff --git a/QuickLocation/Section/Explore/FeatureIntroView.swift b/QuickLocation/Section/Explore/FeatureIntroView.swift index 33794c66..46ce174f 100644 --- a/QuickLocation/Section/Explore/FeatureIntroView.swift +++ b/QuickLocation/Section/Explore/FeatureIntroView.swift @@ -154,8 +154,7 @@ final class FeatureIntroView: UIView { } func reloadFeatureItems() { - let hideSearch = AppContextManager.shared.systemConfig?.isIntercept == true - displayedItems = Self.allItems.filter { !hideSearch || $0.action != .searchLocation } + displayedItems = Self.allItems rebuildGrid() } diff --git a/QuickLocation/Section/Group/CreateGroup/CreateGroupViewModel.swift b/QuickLocation/Section/Group/CreateGroup/CreateGroupViewModel.swift index 3e774699..13371c50 100644 --- a/QuickLocation/Section/Group/CreateGroup/CreateGroupViewModel.swift +++ b/QuickLocation/Section/Group/CreateGroup/CreateGroupViewModel.swift @@ -128,15 +128,7 @@ class CreateGroupViewModel { "labels": selectedTagList]).subscribe(onNext: { [weak self] _ in self?.createSucceeded.accept(()) }, onError: { (error) in - guard let code = error.underlyingError?.code else { return } - - guard let systemConfig = AppContextManager.shared.systemConfig, systemConfig.isIntercept == false else { return } - if code == 20009 { // "您创建的圈子个数已达上限,请升级会员等级" - CreateGroupVipPopView.show() - } - else { - DLToast.show(error) - } + DLToast.show(error) }).disposed(by: disposeBag) } diff --git a/QuickLocation/Section/Group/CreateGroup/CreateGroupVipPopView.swift b/QuickLocation/Section/Group/CreateGroup/CreateGroupVipPopView.swift deleted file mode 100644 index f3443f00..00000000 --- a/QuickLocation/Section/Group/CreateGroup/CreateGroupVipPopView.swift +++ /dev/null @@ -1,120 +0,0 @@ -// -// CreateGroupVipPopView.swift -// QuickLocation -// -// Created by 八条 on 2026/6/3. -// - -import UIKit -import RxSwift -import RxCocoa - -class CreateGroupVipPopView: UIView { - - private static let shared = CreateGroupVipPopView(frame: CGRect(origin: .zero, size: kScreenSize)) - - var disposeBag = DisposeBag() - - static func show() { - guard let superView = kKeyWindow else { - return - } - - if CreateGroupVipPopView.shared.superview != nil { - CreateGroupVipPopView.shared.removeFromSuperview() - CreateGroupVipPopView.shared.bgView.frame = .zero - } - CreateGroupVipPopView.shared.bgView.alpha = 1 - CreateGroupVipPopView.shared.bgView.frame = CGRect(x: 0, y: 0, width: kScreenWidth, height: kScreenHeight) - superView.addSubview(CreateGroupVipPopView.shared) - superView.bringSubviewToFront(CreateGroupVipPopView.shared) - - UIView.animate(withDuration: 0.25) { - CreateGroupVipPopView.shared.bgView.alpha = 1 - } - } - - /// 关闭 - static func dismiss() { - guard CreateGroupVipPopView.shared.superview != nil else { return } - - UIView.animate(withDuration: 0.25, delay: 0, options: [.curveEaseIn]) { - CreateGroupVipPopView.shared.bgView.alpha = 0 - } completion: { _ in - CreateGroupVipPopView.shared.removeFromSuperview() - } - } - - private func setupRx() { - upgradedBtn.rx.tap.subscribe(onNext: { _ in - CreateGroupVipPopView.dismiss() - AppRouter.push(Route.web, userInfo: ["url": URLManager.shared.homeUrl]) - }).disposed(by: disposeBag) - - closeBtn.rx.tap.subscribe(onNext: { _ in - CreateGroupVipPopView.dismiss() - }).disposed(by: disposeBag) - } - - private lazy var bgView: UIView = { - let view = UIView() - view.backgroundColor = .black.withAlphaComponent(0.5) - return view - }() - - lazy var vipImgView: UIImageView = { - let view = UIImageView() - view.image = UIImage(named: "Group/vip_pop") - view.contentMode = .scaleAspectFill - return view - }() - - lazy var upgradedBtn: UIButton = { - let btn = UIButton(type: .custom) - btn.backgroundColor = .clear - btn.setBackgroundImage(UIImage(named: "Group/upgrade_bg"), for: .normal) - return btn - }() - - lazy var closeBtn: UIButton = { - let btn = UIButton(type: .custom) - btn.backgroundColor = .clear - btn.setBackgroundImage(UIImage(named: "Group/close"), for: .normal) - btn.extendEdgeInsets = UIEdgeInsets(top: 10, left: 100, bottom: 100, right: 100) - return btn - }() - - // MARK: - Init - override init(frame: CGRect) { - super.init(frame: frame) - backgroundColor = .clear - addSubview(bgView) - bgView.addSubview(vipImgView) - bgView.addSubview(upgradedBtn) - bgView.addSubview(closeBtn) - - vipImgView.layoutChain - .centerY() - .edgesHorzontal(25) - .heightToWidth(814/648) - - upgradedBtn.layoutChain - .topToBottomOfView(vipImgView, offset: -20) - .centerX() - .width(240) - .height(60) - - closeBtn.layoutChain - .topToBottomOfView(upgradedBtn, offset: 15) - .centerX() - .width(22) - .height(22) - - setupRx() - } - - required init?(coder aDecoder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - -} diff --git a/QuickLocation/Section/Group/GroupChat/GroupChatVC.swift b/QuickLocation/Section/Group/GroupChat/GroupChatVC.swift index 226a3b6d..7efa8b2c 100644 --- a/QuickLocation/Section/Group/GroupChat/GroupChatVC.swift +++ b/QuickLocation/Section/Group/GroupChat/GroupChatVC.swift @@ -96,7 +96,6 @@ final class GroupChatVC: BaseViewController { setupKeyboard() IQKeyboardManager.shared.isEnabled = false IQKeyboardManager.shared.resignOnTouchOutside = false - rootView.updateVipMediaAccess(isUnlocked: isVipUnlocked) } override func viewWillDisappear(_ animated: Bool) { @@ -292,7 +291,6 @@ final class GroupChatVC: BaseViewController { rootView.bringSubviewToFront(rootView.mentionPickerView) rootView.bringSubviewToFront(rootView.quoteBar) rootView.bringSubviewToFront(rootView.bottomBar) - rootView.bringSubviewToFront(rootView.disableIMView) rootView.bringSubviewToFront(rootView.voiceRecordView) } @@ -580,18 +578,6 @@ final class GroupChatVC: BaseViewController { } // MARK: - Actions - private var isVipUnlocked: Bool { - return AppContextManager.shared.vip > 1 - } - - private func requireVipForMedia() -> Bool { - guard isVipUnlocked else { - AppRouter.push(Route.web, userInfo: ["url": URLManager.shared.homeUrl]) - return false - } - return true - } - private func reactiveAction() { rootView.backBtn.rx.tap .subscribe(onNext: { _ in @@ -641,7 +627,7 @@ final class GroupChatVC: BaseViewController { rootView.galleryBtn.rx.tap .subscribe(onNext: { [weak self] in - guard let self, self.requireVipForMedia() else { return } + guard let self else { return } self.rootView.dismissAllPanels() self.showAlbum() }) @@ -649,7 +635,7 @@ final class GroupChatVC: BaseViewController { rootView.cameraBtn.rx.tap .subscribe(onNext: { [weak self] in - guard let self, self.requireVipForMedia() else { return } + guard let self else { return } self.rootView.dismissAllPanels() self.showCamera() }) @@ -714,10 +700,9 @@ final class GroupChatVC: BaseViewController { // MARK: - 显示相册 private func showAlbum() { - guard requireVipForMedia() else { return } let picker = PhotoPickerVC(maxCount: 9) picker.onConfirm = { [weak self] images in - guard let self, self.requireVipForMedia() else { return } + guard let self else { return } for image in images { self.sendImageMessage(image) } @@ -726,7 +711,6 @@ final class GroupChatVC: BaseViewController { } private func showCamera() { - guard requireVipForMedia() else { return } guard UIImagePickerController.isSourceTypeAvailable(.camera) else { DLToast.showError(text: "当前设备不支持拍照") return @@ -769,11 +753,6 @@ final class GroupChatVC: BaseViewController { private var currentVoiceHover: VoiceRecordView.HoverTarget = .none private func enterVoiceInputMode() { - guard isVipUnlocked else { - rootView.dismissAllPanels() - rootView.setVoiceInputMode(true) - return - } let status = AVCaptureDevice.authorizationStatus(for: .audio) switch status { case .authorized: @@ -857,7 +836,6 @@ final class GroupChatVC: BaseViewController { } private func startVoiceRecording() { - guard requireVipForMedia() else { return } guard !isVoiceRecording else { return } AudioServicesPlaySystemSound(1519) currentVoiceHover = .none @@ -972,11 +950,6 @@ final class GroupChatVC: BaseViewController { } private func sendVoiceMessage(url: URL, durationMs: Int) { - guard requireVipForMedia() else { - deleteRecordFile() - rootView.voiceRecordView.reset() - return - } GroupIMService.shared.sendGroupMessage(groupId: viewModel.groupId, makeMessage: { OIMMessageInfo.createSoundMessage(fromFullPath: url.path, duration: durationMs) @@ -1235,7 +1208,6 @@ private class MessageListenerProxy: NSObject, OIMAdvancedMsgListener { extension GroupChatVC { private func sendImageMessage(_ image: UIImage) { - guard requireVipForMedia() else { return } let sendImage = image.cgImage != nil ? image.fixOrientation() : image guard let data = sendImage.jpegData(compressionQuality: 0.8) else { return } let dir = NSTemporaryDirectory() diff --git a/QuickLocation/Section/Group/GroupChat/GroupChatView.swift b/QuickLocation/Section/Group/GroupChat/GroupChatView.swift index 081a307e..f3dc956a 100644 --- a/QuickLocation/Section/Group/GroupChat/GroupChatView.swift +++ b/QuickLocation/Section/Group/GroupChat/GroupChatView.swift @@ -217,7 +217,6 @@ class GroupChatView: UIView { /// 收起所有浮层面板 private var isVoiceInputMode = false - private var isVipMediaUnlocked = true func setVoiceInputMode(_ enabled: Bool) { isVoiceInputMode = enabled @@ -228,18 +227,6 @@ class GroupChatView: UIView { refreshComposer() } - func updateVipMediaAccess(isUnlocked: Bool) { - isVipMediaUnlocked = isUnlocked - let lockedBackground = isUnlocked ? nil : UIImage(named: "VipFeature/media_locked_bg") - galleryBtn.setBackgroundImage(lockedBackground, for: .normal) - cameraBtn.setBackgroundImage(lockedBackground, for: .normal) - galleryBtn.backgroundColor = isUnlocked ? .white : .clear - cameraBtn.backgroundColor = isUnlocked ? .white : .clear - voiceBtn.setImage(UIImage(named: "IM/voice_input"), for: .normal) - textField.placeholder = "发消息或者按住说话" - refreshComposer() - } - func refreshComposer() { let hasText = !(textField.text ?? "").trimmingCharacters(in: .whitespacesAndNewlines).isEmpty textField.updatePlaceholderVisibility() @@ -292,9 +279,7 @@ class GroupChatView: UIView { private func updateHoldSpeakAppearance() { var configuration = UIButton.Configuration.plain() configuration.title = "按住 说话" - configuration.image = isVipMediaUnlocked ? nil : UIImage(named: "VipFeature/crown") configuration.imagePlacement = .leading - configuration.imagePadding = isVipMediaUnlocked ? 0 : 10 configuration.contentInsets = .zero configuration.baseForegroundColor = UIColor(hexStr: "#293445") configuration.titleTextAttributesTransformer = UIConfigurationTextAttributesTransformer { attributes in @@ -389,7 +374,6 @@ class GroupChatView: UIView { addSubview(mentionPickerView) addSubview(quickActionBar) addSubview(bottomBar) - addSubview(disableIMView) bottomBar.addSubview(bottomBarCornerView) addSubview(voiceRecordView) addSubview(emojiPanelView) @@ -522,11 +506,6 @@ class GroupChatView: UIView { bottomBarHeightConstraint = bottomBar.heightAnchor.constraint(equalToConstant: minimumBottomBarHeight) bottomBarHeightConstraint?.isActive = true - disableIMView.layoutChain - .edgesHorzontal(15) - .height(50) - .bottom(kSafeBottomMargin) - bottomBarBottomConstraint = bottomBar.jh_constraint(.bottom, toAttribute: .bottom, otherView: bottomBar.superview, relation: .equal) bottomBarCornerView.layoutChain.edges() @@ -883,32 +862,6 @@ class GroupChatView: UIView { return btn }() - /// IM功能禁用 - lazy var disableIMView: UIView = { - let view = UIView() - view.backgroundColor = .clear - view.layer.shadowColor = UIColor(hexStr: "#0F2846", alpha: 0.1).cgColor - view.layer.shadowOffset = CGSize(width: 0, height: 0) - view.layer.shadowOpacity = 1 - view.layer.shadowRadius = 9 - view.isHidden = true - - let v = UIView() - v.backgroundColor = .white - v.cornerRadius = 25 - view.addSubview(v) - v.layoutChain.edges() - - let label = UILabel() - label.text = "开通VIP后可发送消息" - label.textColor = ThemeManager.shared.color.titleAuxColor - label.font = .systemFont(ofSize: 15, weight: .medium) - view.addSubview(label) - label.layoutChain.centerX().centerY() - - return view - }() - /// 语音面板 lazy var voiceRecordView: VoiceRecordView = { let v = VoiceRecordView() diff --git a/QuickLocation/Section/Group/GroupMemberList/GroupMemberListView.swift b/QuickLocation/Section/Group/GroupMemberList/GroupMemberListView.swift index ba5829f2..a474a446 100644 --- a/QuickLocation/Section/Group/GroupMemberList/GroupMemberListView.swift +++ b/QuickLocation/Section/Group/GroupMemberList/GroupMemberListView.swift @@ -264,7 +264,6 @@ final class GroupMemberListCell: UICollectionViewCell { nameLabel.text = model.showName nameLabel.textColor = UIColor(hexStr: isCurrentUser ? "#16B3FF" : "#0F2846") selectionImageView.isHidden = !isSelected - vipBackgroundView.isHidden = !model.shouldShowVipAvatarFrame let isSOS = model.status == 1 updateSOSBlink(isSOS) @@ -291,10 +290,9 @@ final class GroupMemberListCell: UICollectionViewCell { contentView.addSubview(avatarImageView) contentView.addSubview(bubbleImageView) contentView.addSubview(sosImageView) - contentView.addSubview(vipBackgroundView) contentView.addSubview(nameLabel) - [selectionImageView, avatarImageView, bubbleImageView, sosImageView, vipBackgroundView, nameLabel].forEach { + [selectionImageView, avatarImageView, bubbleImageView, sosImageView, nameLabel].forEach { $0.translatesAutoresizingMaskIntoConstraints = false } @@ -319,9 +317,6 @@ final class GroupMemberListCell: UICollectionViewCell { sosImageView.trailingAnchor.constraint(equalTo: avatarImageView.trailingAnchor), sosImageView.bottomAnchor.constraint(equalTo: avatarImageView.bottomAnchor), - vipBackgroundView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 7), - vipBackgroundView.centerXAnchor.constraint(equalTo: contentView.centerXAnchor), - nameLabel.topAnchor.constraint(equalTo: avatarImageView.bottomAnchor, constant: 7), nameLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor), nameLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor) @@ -360,12 +355,6 @@ final class GroupMemberListCell: UICollectionViewCell { return view }() - private lazy var vipBackgroundView: UIImageView = { - let view = UIImageView(image: UIImage(named: "GroupMemberList/vip")) - view.isHidden = true - return view - }() - private lazy var nameLabel: UILabel = { let label = UILabel() label.font = .systemFont(ofSize: 12, weight: .medium) diff --git a/QuickLocation/Section/Home/Bubble/CreateBubblePopView.swift b/QuickLocation/Section/Home/Bubble/CreateBubblePopView.swift deleted file mode 100644 index 33a67aef..00000000 --- a/QuickLocation/Section/Home/Bubble/CreateBubblePopView.swift +++ /dev/null @@ -1,120 +0,0 @@ -// -// CreateBubblePopView.swift -// QuickLocation -// -// Created by 八条 on 2026/6/26. -// - -import UIKit -import RxSwift -import RxCocoa - -class CreateBubblePopView: UIView { - - private static let shared = CreateBubblePopView(frame: CGRect(origin: .zero, size: kScreenSize)) - - var disposeBag = DisposeBag() - - static func show() { - guard let superView = kKeyWindow else { - return - } - - if CreateBubblePopView.shared.superview != nil { - CreateBubblePopView.shared.removeFromSuperview() - CreateBubblePopView.shared.bgView.frame = .zero - } - CreateBubblePopView.shared.bgView.alpha = 1 - CreateBubblePopView.shared.bgView.frame = CGRect(x: 0, y: 0, width: kScreenWidth, height: kScreenHeight) - superView.addSubview(CreateBubblePopView.shared) - superView.bringSubviewToFront(CreateBubblePopView.shared) - - UIView.animate(withDuration: 0.25) { - CreateBubblePopView.shared.bgView.alpha = 1 - } - } - - /// 关闭 - static func dismiss() { - guard CreateBubblePopView.shared.superview != nil else { return } - - UIView.animate(withDuration: 0.25, delay: 0, options: [.curveEaseIn]) { - CreateBubblePopView.shared.bgView.alpha = 0 - } completion: { _ in - CreateBubblePopView.shared.removeFromSuperview() - } - } - - private func setupRx() { - upgradedBtn.rx.tap.subscribe(onNext: { _ in - CreateBubblePopView.dismiss() - AppRouter.push(Route.web, userInfo: ["url": URLManager.shared.homeUrl]) - }).disposed(by: disposeBag) - - closeBtn.rx.tap.subscribe(onNext: { _ in - CreateBubblePopView.dismiss() - }).disposed(by: disposeBag) - } - - private lazy var bgView: UIView = { - let view = UIView() - view.backgroundColor = .black.withAlphaComponent(0.5) - return view - }() - - lazy var vipImgView: UIImageView = { - let view = UIImageView() - view.image = UIImage(named: "Bubble/vip_pop") - view.contentMode = .scaleAspectFill - return view - }() - - lazy var upgradedBtn: UIButton = { - let btn = UIButton(type: .custom) - btn.backgroundColor = .clear - btn.setBackgroundImage(UIImage(named: "Bubble/upgrade_bg"), for: .normal) - return btn - }() - - lazy var closeBtn: UIButton = { - let btn = UIButton(type: .custom) - btn.backgroundColor = .clear - btn.setBackgroundImage(UIImage(named: "Group/close"), for: .normal) - btn.extendEdgeInsets = UIEdgeInsets(top: 10, left: 100, bottom: 100, right: 100) - return btn - }() - - // MARK: - Init - override init(frame: CGRect) { - super.init(frame: frame) - backgroundColor = .clear - addSubview(bgView) - bgView.addSubview(vipImgView) - bgView.addSubview(upgradedBtn) - bgView.addSubview(closeBtn) - - vipImgView.layoutChain - .centerY() - .edgesHorzontal(25) - .heightToWidth(814/648) - - upgradedBtn.layoutChain - .topToBottomOfView(vipImgView, offset: -20) - .centerX() - .width(240) - .height(60) - - closeBtn.layoutChain - .topToBottomOfView(upgradedBtn, offset: 15) - .centerX() - .width(22) - .height(22) - - setupRx() - } - - required init?(coder aDecoder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - -} diff --git a/QuickLocation/Section/Home/Bubble/CreateBubbleSetupView.swift b/QuickLocation/Section/Home/Bubble/CreateBubbleSetupView.swift index 4a5675a6..11cb28b0 100644 --- a/QuickLocation/Section/Home/Bubble/CreateBubbleSetupView.swift +++ b/QuickLocation/Section/Home/Bubble/CreateBubbleSetupView.swift @@ -25,7 +25,6 @@ final class CreateBubbleSetupView: UIView { private let subtitleLab = UILabel() private let titleLab = UILabel() private let hourPicker = BubbleHourPickerView() - private let vipOfferImageView = UIImageView(image: UIImage(named: "VipFeature/limited_offer")) private let sheetOverlay = UIView() private let sheetPanel = UIView() @@ -84,7 +83,6 @@ final class CreateBubbleSetupView: UIView { addSubview(subtitleLab) addSubview(hourPicker) addSubview(confirmBtn) - addSubview(vipOfferImageView) heroView.showsOuterDecorBubbles = false heroView.layoutChain @@ -115,25 +113,6 @@ final class CreateBubbleSetupView: UIView { confirmBtn.setBackgroundImage(UIImage(named: "Common/button_bg_2"), for: .normal) confirmBtn.cornerRadius = 20 confirmBtn.layoutChain.left(30).right(30).bottom(34).height(56) - - vipOfferImageView.contentMode = .scaleAspectFit - vipOfferImageView.isHidden = true - vipOfferImageView.translatesAutoresizingMaskIntoConstraints = false - NSLayoutConstraint.activate([ - vipOfferImageView.trailingAnchor.constraint(equalTo: confirmBtn.trailingAnchor, constant: -6), - vipOfferImageView.bottomAnchor.constraint(equalTo: confirmBtn.topAnchor, constant: 10), - vipOfferImageView.widthAnchor.constraint(equalToConstant: 94), - vipOfferImageView.heightAnchor.constraint(equalToConstant: 32) - ]) - } - - func updateVipAccess(isUnlocked: Bool) { - confirmBtn.setTitle(isUnlocked ? "确定" : "开通会员 解锁功能", for: .normal) - confirmBtn.setBackgroundImage( - UIImage(named: isUnlocked ? "Common/button_bg_2" : "VipFeature/wide_button_bg"), - for: .normal - ) - vipOfferImageView.isHidden = isUnlocked } private func setupSheet() { diff --git a/QuickLocation/Section/Home/Bubble/CreateBubbleVC.swift b/QuickLocation/Section/Home/Bubble/CreateBubbleVC.swift index 621c60ab..447a8686 100644 --- a/QuickLocation/Section/Home/Bubble/CreateBubbleVC.swift +++ b/QuickLocation/Section/Home/Bubble/CreateBubbleVC.swift @@ -26,7 +26,6 @@ class CreateBubbleVC: BaseViewController { override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) - rootView.updateVipAccess(isUnlocked: isVipUnlocked) requestUserStatus() } @@ -49,10 +48,6 @@ class CreateBubbleVC: BaseViewController { rootView.setupView.confirmBtn.rx.tap .subscribe(onNext: { [weak self] in guard let self else { return } - guard self.isVipUnlocked else { - AppRouter.push(Route.web, userInfo: ["url": URLManager.shared.homeUrl]) - return - } let hours = self.rootView.setupView.selectedHour.value let message = self.rootView.setupView.buildMessage(for: hours) self.rootView.setupView.showNotifySheet(message: message) @@ -85,19 +80,10 @@ class CreateBubbleVC: BaseViewController { } private func submitCreate() { - guard isVipUnlocked else { - rootView.setupView.dismissNotifySheet() - AppRouter.push(Route.web, userInfo: ["url": URLManager.shared.homeUrl]) - return - } let hours = rootView.setupView.selectedHour.value requestSetBubble(enable: true, keep_time: hours) } - private var isVipUnlocked: Bool { - return AppContextManager.shared.vip > 1 - } - private func restoreCachedBubbleIfNeeded() { guard AppContextManager.shared.status == 2, let endDate = Defaults[\.bubbleKeepTimes], diff --git a/QuickLocation/Section/Home/Bubble/CreateBubbleView.swift b/QuickLocation/Section/Home/Bubble/CreateBubbleView.swift index 0b132dc8..35ca0d89 100644 --- a/QuickLocation/Section/Home/Bubble/CreateBubbleView.swift +++ b/QuickLocation/Section/Home/Bubble/CreateBubbleView.swift @@ -90,8 +90,4 @@ class CreateBubbleView: UIView { func updateNavTitleForSheet(_ visible: Bool) { navView.titleLabel.text = visible ? "通知您的圈子" : "设置气泡时间" } - - func updateVipAccess(isUnlocked: Bool) { - setupView.updateVipAccess(isUnlocked: isUnlocked) - } } diff --git a/QuickLocation/Section/Home/GroupMemberView.swift b/QuickLocation/Section/Home/GroupMemberView.swift deleted file mode 100644 index bc87149e..00000000 --- a/QuickLocation/Section/Home/GroupMemberView.swift +++ /dev/null @@ -1,478 +0,0 @@ -// -// GroupMemberView.swift -// QuickLocation -// -// Created by 八条 on 2026/5/29. -// - -import UIKit -import RxSwift -import RxCocoa -import Lottie - -class GroupMemberView: UIView { - - func setupCountData(_ memberCount: Int, _ memberOnlineCount: Int) { - groupContentLab.text = "共\(memberCount)成员/\(memberOnlineCount)在线" - } - - private func setupRx() { - - } - - private func setupUI() { - addSubview(headerBgView) - addSubview(bgView) - addSubview(groupIcon) - addSubview(titleIcon) - addSubview(groupContentLab) - addSubview(refreshBtn) - addSubview(inviteJoinBtn) - addSubview(tableView) - - headerBgView.layoutChain - .edges(excludingEdge: .bottom) - .heightToWidth(136/375) - - bgView.layoutChain - .topToBottomOfView(headerBgView) - .edges(excludingEdge: .top) - - groupIcon.layoutChain - .top() - .left() - .width(52) - .height(52) - - titleIcon.layoutChain - .top(5) - .leftToRightOfView(groupIcon) - .width(110) - .height(26) - - groupContentLab.layoutChain - .topToBottomOfView(titleIcon, offset: 8) - .leftToView(titleIcon) - - inviteJoinBtn.layoutChain - .top(23) - .right(15) - .height(20) - - refreshBtn.layoutChain - .topToView(inviteJoinBtn) - .rightToLeftOfView(inviteJoinBtn, offset: -20) - .height(20) - - inviteJoinBtn.sizeToFit() - refreshBtn.sizeToFit() - - tableView.layoutChain - .topToBottomOfView(groupContentLab, offset: 8) - .edges(excludingEdge: .top) - } - - lazy var headerBgView: UIImageView = { - let view = UIImageView() - view.image = UIImage(named: "Home/group_member_bg") - view.backgroundColor = .clear - view.contentMode = .scaleAspectFill - return view - }() - - lazy var bgView: UIView = { - let view = UIView() - view.backgroundColor = .white - return view - }() - - lazy var groupIcon: UIImageView = { - let view = UIImageView() - view.image = UIImage(named: "Home/group_icon") - view.backgroundColor = .clear - view.contentMode = .scaleAspectFill - return view - }() - - lazy var titleIcon: UIImageView = { - let view = UIImageView() - view.image = UIImage(named: "Home/title_icon") - view.backgroundColor = .clear - view.contentMode = .scaleAspectFill - return view - }() - - lazy var groupContentLab: UILabel = { - let label = UILabel() - label.text = "共0成员/0在线" - label.font = .systemFont(ofSize: 12, weight: .medium) - label.textColor = UIColor(hexStr: "#0F2846") - return label - }() - - lazy var refreshBtn: UIButton = { - let btn = UIButton(type: .custom) - btn.setTitle(" 刷新列表", for: .normal) - btn.setTitleColor(UIColor(hexStr: "#1A1A1A"), for: .normal) - btn.titleLabel?.font = .systemFont(ofSize: 12, weight: .regular) - btn.setImage(UIImage(named: "Home/refresh"), for: .normal) - return btn - }() - - lazy var inviteJoinBtn: UIButton = { - let btn = UIButton(type: .custom) - btn.setTitle(" 邀请加入", for: .normal) - btn.setTitleColor(UIColor(hexStr: "#1A1A1A"), for: .normal) - btn.titleLabel?.font = .systemFont(ofSize: 12, weight: .regular) - btn.setImage(UIImage(named: "Home/member"), for: .normal) - return btn - }() - - lazy var tableView: UITableView = { - let tableView = UITableView(frame: .zero, style: .plain) - tableView.backgroundColor = .clear - tableView.separatorStyle = .none - tableView.estimatedRowHeight = 76 - tableView.showsVerticalScrollIndicator = false - tableView.register(GroupMemberCell.self) - tableView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 97 + kSafeBottomMargin, right: 0) - return tableView - }() - - override init(frame: CGRect) { - super.init(frame: frame) - backgroundColor = .clear - setupUI() - setupRx() - } - - required init?(coder aDecoder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } -} - -// MARK: - GroupMemberCell -class GroupMemberCell: UITableViewCell { - - func configure(model: GroupMemberModel, isCurrentUser: Bool, isOwn: Bool) { - ownView.isHidden = !isOwn - avaterImgView.setHeadPic(model.displayHeadPic) - nameLab.text = model.showName - // 位置 - locationLab.text = "在 " + model.lastLocation - - nameLab.textColor = UIColor(hexStr: isCurrentUser ? "#16B3FF" : "#0F2846") - - // 会员权益 - batteryInfoView.isHidden = true - if AppContextManager.shared.vip > 1, model.is_online { - batteryInfoView.isHidden = model.battery.int == 0 - // 电量 16是电池图标宽度,右边有电池造型需要减去 - let batteryPercent = min(CGFloat(model.battery.int), 100) - batteryView.layoutChain.width(CGFloat(16 - 1) * batteryPercent / 100.0) - batteryLab.text = "\(model.battery)%" - } - - // 在线状态 - if model.is_online { - onlineDotView.isHidden = false - onlineStatusLab.text = "在线" - onlineStatusLab.textColor = ThemeManager.shared.color.titleAuxColor - } else { - onlineDotView.isHidden = true - onlineStatusLab.text = model.lastUpdateText - onlineStatusLab.textColor = UIColor(hexStr: "#999999") - } - - // sos - sosLottieView.isHidden = model.status != 1 - model.status == 1 ? sosLottieView.play() : sosLottieView.stop() - - // 气泡 - shieldIconView.isHidden = model.status != 2 - } - - private func setupSubviews() { - contentView.addSubview(selectedBgView) - contentView.addSubview(avaterImgView) - contentView.addSubview(batteryInfoView) - batteryInfoView.addSubview(cornerView) - cornerView.addSubview(batteryView) - cornerView.addSubview(batteryIcon) - cornerView.addSubview(batteryLab) - contentView.addSubview(nameLab) - contentView.addSubview(locationIcon) - contentView.addSubview(locationLab) - contentView.addSubview(tagView) - contentView.addSubview(onlineView) - - setupLayout() - } - - private func setupLayout() { - selectedBgView.layoutChain - .edgesHorzontal(15) - .edgesVertical() - - avaterImgView.layoutChain - .edgesVertical(13) - .left(28) - .width(50) - .height(50) - - batteryInfoView.layoutChain - .leftToView(avaterImgView) - .rightToView(avaterImgView) - .bottomToView(avaterImgView) - .height(12) - - cornerView.layoutChain.edges() - - batteryIcon.layoutChain - .left(7) - .centerY() - .width(16) - .height(8) - - batteryView.layoutChain - .topToView(batteryIcon) - .leftToView(batteryIcon, offset: -1) - .bottomToView(batteryIcon) - - batteryLab.layoutChain - .leftToRightOfView(batteryIcon, offset: 4) - .right(5) - .centerY() - - nameLab.layoutChain - .topToView(avaterImgView, offset: 6) - .leftToRightOfView(avaterImgView, offset: 8) - - locationLab.layoutChain - .bottomToView(avaterImgView, offset: -6) - .leftToView(nameLab) - - locationIcon.layoutChain - .leftToRightOfView(locationLab, offset: 4) - .centerY(locationLab) - .width(10) - .height(10) - .right(80, relation: .greaterThanOrEqual) - - tagView.layoutChain - .leftToRightOfView(nameLab, offset: 4) - .centerY(nameLab) - .height(30) - - ownView.layoutChain.height(15) - - offlineView.layoutChain.height(15) - - onlineView.layoutChain - .right(26) - .bottom(18) - } - - lazy var selectedBgView: UIView = { - let view = UIView() - view.backgroundColor = UIColor(hexStr: "#EAFBFF") - view.cornerRadius = 10 - view.isHidden = true - return view - }() - - lazy var avaterImgView: UIImageView = { - let view = UIImageView() - view.backgroundColor = .lightGray - view.contentMode = .scaleAspectFill - view.cornerRadius = 25 - return view - }() - - lazy var batteryInfoView: UIView = { - let view = UIView() - view.backgroundColor = .clear - view.layer.shadowColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.1).cgColor - view.layer.shadowOffset = CGSize(width: 0, height: 2) - view.layer.shadowOpacity = 1 - view.layer.shadowRadius = 6 - view.isHidden = true - return view - }() - - lazy var cornerView: UIView = { - let view = UIView() - view.backgroundColor = .white - view.cornerRadius = 6 - return view - }() - - lazy var batteryView: UIView = { - let view = UIView() - view.backgroundColor = UIColor(hexStr: "#75E582") - return view - }() - - lazy var batteryIcon: UIImageView = { - let view = UIImageView() - view.backgroundColor = .clear - view.image = UIImage(named: "Home/battery") - return view - }() - - lazy var batteryLab: UILabel = { - let label = UILabel() - label.textColor = UIColor(hexStr: "#D4D4D4") - label.font = .systemFont(ofSize: 6, weight: .medium) - return label - }() - - - lazy var nameLab: UILabel = { - let label = UILabel() - label.textColor = UIColor(hexStr: "#0F2846") - label.font = .systemFont(ofSize: 14, weight: .semibold) - return label - }() - - lazy var locationIcon: UIImageView = { - let view = UIImageView() - view.image = UIImage(named: "Home/member_location") - return view - }() - - lazy var locationLab: UILabel = { - let label = UILabel() - label.textColor = UIColor(hexStr: "#8D8D8D") - label.font = .systemFont(ofSize: 10, weight: .regular) - return label - }() - - lazy var tagView: UIStackView = { - let view = UIStackView(arrangedSubviews: [ownView, offlineView, sosLottieView, shieldIconView]) - view.axis = .horizontal - view.alignment = .center - view.spacing = 5 - view.backgroundColor = .clear - return view - }() - - // 圈主 - lazy var ownView: UIView = { - let view = UIView() - view.backgroundColor = UIColor(hexStr: "#9FD9FF") - view.cornerRadius = 2 - - let label = UILabel() - label.textColor = UIColor(hexStr: "#194045") - label.font = .systemFont(ofSize: 8, weight: .medium) - label.text = "圈主" - - view.addSubview(label) - label.layoutChain - .edgesVertical(2) - .edgesHorzontal(8) - - return view - }() - - // 离线 - lazy var offlineView: UIView = { - let view = UIView() - view.backgroundColor = UIColor(hexStr: "#EDEDED") - view.cornerRadius = 2 - - let label = UILabel() - label.textColor = ThemeManager.shared.color.contentColor - label.font = .systemFont(ofSize: 8, weight: .medium) - label.text = "离线" - - view.addSubview(label) - label.layoutChain - .edgesVertical(2) - .edgesHorzontal(8) - - view.isHidden = true - return view - }() - - // sos - lazy var sosLottieView: LottieAnimationView = { - let view = LottieAnimationView(name: "siren") - view.loopMode = .loop - view.isHidden = true - - view.layoutChain.width(26).height(26) - - return view - }() - - // 气泡(盾牌) - lazy var shieldIconView: UIImageView = { - let view = UIImageView(image: UIImage(named: "Home/shield")) - view.contentMode = .scaleAspectFill - view.isHidden = true - - view.layoutChain.width(20).height(20) - - return view - }() - - // 在线 - lazy var onlineView: UIView = { - let view = UIView() - view.backgroundColor = .clear - - view.addSubview(onlineDotView) - view.addSubview(onlineStatusLab) - - onlineDotView.layoutChain - .left() - .centerY() - .height(8) - .width(8) - - onlineStatusLab.layoutChain - .edgesVertical() - .leftToRightOfView(onlineDotView, offset: 3) - .right() - - return view - }() - - lazy var onlineDotView: UIView = { - let view = UIView() - view.backgroundColor = UIColor(hexStr: "#67EA76") - view.cornerRadius = 4 - return view - }() - - lazy var onlineStatusLab: UILabel = { - let label = UILabel() - label.textColor = ThemeManager.shared.color.titleAuxColor - label.font = .systemFont(ofSize: 10, weight: .medium) - label.text = "在线" - return label - }() - - override func awakeFromNib() { - super.awakeFromNib() - // Initialization code - } - - override init(style: CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - selectionStyle = .none - backgroundColor = .clear - setupSubviews() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) - selectedBgView.isHidden = !selected - } -} diff --git a/QuickLocation/Section/Home/GroupMemberView2.swift b/QuickLocation/Section/Home/GroupMemberView2.swift index 93b8a569..45381372 100644 --- a/QuickLocation/Section/Home/GroupMemberView2.swift +++ b/QuickLocation/Section/Home/GroupMemberView2.swift @@ -12,7 +12,6 @@ import SwiftyUserDefaults enum MemberFeatureAccessState: Equatable { case available - case vipRequired case privilegeDenied } @@ -28,7 +27,6 @@ class GroupMemberView2: UIView { private var appUsageBottomConstraint: NSLayoutConstraint? private var isAppUsageVisible = false private var currentMemberModel: GroupMemberModel? - private var currentGroupVip = GroupMemberVip() private var emojiEchoByUserId: [String: String] = [:] private var messageEchoByUserId: [String: String] = [:] private var phoneStatusObserver: NSObjectProtocol? @@ -37,7 +35,6 @@ class GroupMemberView2: UIView { private var localWeatherSnapshotKey: String? private var localWeatherUpdatedAt: Date? private var pendingWeatherLocationKey: String? - private(set) var isTodayTrackVipRequired = false var onCoupleMemberTap: ((GroupMemberModel) -> Void)? private static let weatherRefreshInterval: TimeInterval = 15 * 60 @@ -55,11 +52,9 @@ class GroupMemberView2: UIView { func setupMemberInfo( _ model: GroupMemberModel, isOwner: Bool, - phoneUsage: PhoneUsageTodayModel?, - groupVip: GroupMemberVip + phoneUsage: PhoneUsageTodayModel? ) { currentMemberModel = model - currentGroupVip = groupVip memberNameLab.text = model.showName ownView.isHidden = !isOwner relationIconView.configure(relationIdx: model.extra.relation_idx) @@ -78,7 +73,7 @@ class GroupMemberView2: UIView { } applyPhoneUsage(phoneUsage) - if isCurrentUser, !isPhoneDeviceVipRequired { + if isCurrentUser { requestLocalWeather() } updateRealtimeInteractionVisibility(isCurrentUser: isCurrentUser) @@ -87,7 +82,6 @@ class GroupMemberView2: UIView { func clearMemberInfo() { currentMemberModel = nil - currentGroupVip = GroupMemberVip() memberNameLab.text = "" ownView.isHidden = true relationIconView.configure(relationIdx: "") @@ -105,20 +99,18 @@ class GroupMemberView2: UIView { func updatePhoneUsage(_ phoneUsage: PhoneUsageTodayModel?, for userId: String) { guard currentMemberModel?.user_id == userId else { return } applyPhoneUsage(phoneUsage) - if Self.isCurrentUser(userId), !isPhoneDeviceVipRequired { + if Self.isCurrentUser(userId) { applyLocalDeviceInfo() } } func refreshLocalDeviceInfoIfNeeded() { - guard isShowingCurrentUser, !isPhoneDeviceVipRequired else { return } + guard isShowingCurrentUser else { return } applyLocalDeviceInfo() } func refreshInterceptState() { memberCV.reloadData() - coupleLeftSlot.refreshVipVisibility() - coupleRightSlot.refreshVipVisibility() updateFeatureVisibilityLayout() } @@ -206,9 +198,7 @@ class GroupMemberView2: UIView { } private func applyPhoneUsage(_ usage: PhoneUsageTodayModel?) { - if isPhoneDeviceVipRequired { - stopLocalPhoneStatusObserving() - } else if isShowingCurrentUser { + if isShowingCurrentUser { applyLocalDeviceInfo() startLocalPhoneStatusObserving() } else { @@ -219,7 +209,6 @@ class GroupMemberView2: UIView { applyDeviceInfo(usage?.phoneInfo) } } - applyPhoneDeviceAccessState() if isShowingOfflineOther { phoneReportView.configure(with: nil) appUsageView.configure(with: nil) @@ -236,15 +225,11 @@ class GroupMemberView2: UIView { var isPhoneReportDenied: Bool { phoneReportView.isDenied } var isAppUsageDenied: Bool { appUsageView.isDenied } - var isPhoneReportVipRequired: Bool { phoneReportView.isVipRequired } - var isAppUsageVipRequired: Bool { appUsageView.isVipRequired } var onPhoneReportRemind: (() -> Void)? var onAppUsageRemind: (() -> Void)? private func applyFeatureAccessStates(appUsagePreview: MemberAppUsagePreview?) { guard currentMemberModel != nil else { - isTodayTrackVipRequired = false - todayTrackVipView.isHidden = true phoneReportView.setAccessState(.available) appUsageView.setAccessState(.available) updateAppUsageVisibility(appUsagePreview != nil) @@ -253,16 +238,12 @@ class GroupMemberView2: UIView { let isSelf = isShowingCurrentUser let memberPrivilege = currentMemberModel?.extra.privilege ?? GroupPrivilege() let phoneState = Self.accessState( - vipAllowed: currentGroupVip.phone_report, privilegeAllowed: isSelf || memberPrivilege.phone_report ) let appUsageState = Self.accessState( - vipAllowed: currentGroupVip.app_usage_record, privilegeAllowed: isSelf || memberPrivilege.app_usage_record ) - isTodayTrackVipRequired = !isSelf && currentGroupVip.trip_analysis_others == false - todayTrackVipView.isHidden = !isTodayTrackVipRequired phoneReportView.setAccessState(phoneState) phoneReportView.onDeniedAction = { [weak self] in self?.onPhoneReportRemind?() } appUsageView.setAccessState(appUsageState) @@ -274,13 +255,7 @@ class GroupMemberView2: UIView { updateAppUsageVisibility(showUsage) } - private static func accessState( - vipAllowed: Bool?, - privilegeAllowed: Bool - ) -> MemberFeatureAccessState { - if vipAllowed == false { - return .vipRequired - } + private static func accessState(privilegeAllowed: Bool) -> MemberFeatureAccessState { if !privilegeAllowed { return .privilegeDenied } @@ -291,23 +266,6 @@ class GroupMemberView2: UIView { Self.isCurrentUser(currentMemberModel?.user_id) } - private var isPhoneDeviceVipRequired: Bool { - currentMemberModel != nil && !isShowingCurrentUser && currentGroupVip.view_phone == false - } - - private func applyPhoneDeviceAccessState() { - let requiresVip = isPhoneDeviceVipRequired - phoneModelView.isHidden = requiresVip - batteryView.isHidden = requiresVip - networkView.isHidden = requiresVip - weatherView.isHidden = requiresVip - phoneDeviceVipButton.isHidden = !requiresVip - } - - @objc private func handlePhoneDeviceVipTap() { - AppRouter.push(Route.web, userInfo: ["url": URLManager.shared.homeUrl]) - } - private static func isCurrentUser(_ userId: String?) -> Bool { let memberId = userId?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" let selfId = AppContextManager.shared.userId.trimmingCharacters(in: .whitespacesAndNewlines) @@ -346,7 +304,7 @@ class GroupMemberView2: UIView { object: nil, queue: .main ) { [weak self] _ in - guard let self, self.isShowingCurrentUser, !self.isPhoneDeviceVipRequired else { return } + guard let self, self.isShowingCurrentUser else { return } self.applyLocalDeviceInfo() } } @@ -375,7 +333,6 @@ class GroupMemberView2: UIView { } private func requestLocalWeather() { - guard !isPhoneDeviceVipRequired else { return } guard let latitude = Defaults[\.currentLatitude], let longitude = Defaults[\.currentLongitude] else { if localWeatherSnapshot == nil { @@ -409,7 +366,7 @@ class GroupMemberView2: UIView { MemberWeatherService.shared.weather(for: location) { [weak self] result in guard let self, self.weatherRequestID == requestID else { return } self.pendingWeatherLocationKey = nil - guard self.isShowingCurrentUser, !self.isPhoneDeviceVipRequired else { return } + guard self.isShowingCurrentUser else { return } switch result { case .success(let snapshot): self.localWeatherSnapshot = snapshot @@ -442,15 +399,16 @@ class GroupMemberView2: UIView { } private func updateFeatureVisibilityLayout() { - let hidesPhoneReport = AppContextManager.shared.systemConfig?.isIntercept == true + let hidesPhoneReport = false + let showsAppUsage = !hidesPhoneReport && isAppUsageVisible phoneReportView.isHidden = hidesPhoneReport - appUsageView.isHidden = hidesPhoneReport + appUsageView.isHidden = !showsAppUsage appUsageTopToPhoneReportConstraint?.isActive = !hidesPhoneReport appUsageTopToTodayTrackConstraint?.isActive = hidesPhoneReport phoneReportBottomConstraint?.isActive = !hidesPhoneReport && !isAppUsageVisible - appUsageBottomConstraint?.isActive = isAppUsageVisible - todayTrackBottomConstraint?.isActive = hidesPhoneReport && !isAppUsageVisible + appUsageBottomConstraint?.isActive = showsAppUsage + todayTrackBottomConstraint?.isActive = hidesPhoneReport setNeedsLayout() } @@ -950,7 +908,6 @@ class GroupMemberView2: UIView { view.addSubview(batteryView) view.addSubview(networkView) view.addSubview(weatherView) - view.addSubview(phoneDeviceVipButton) phoneModelView.layoutChain .topToBottomOfView(locationLab, offset: 20) @@ -971,12 +928,6 @@ class GroupMemberView2: UIView { .leftToRightOfView(networkView) .right() .widthToView(phoneModelView) - - phoneDeviceVipButton.layoutChain - .centerX() - .centerY(phoneModelView) - .width(174) - .height(34) return view }() @@ -1239,17 +1190,6 @@ class GroupMemberView2: UIView { label.font = .systemFont(ofSize: 12, weight: .medium) return label }() - - private lazy var phoneDeviceVipButton: UIButton = { - let button = UIButton(type: .custom) - button.setTitle("开通会员 解锁功能", for: .normal) - button.setTitleColor(.white, for: .normal) - button.titleLabel?.font = FontManager.boboBold(14) - button.setBackgroundImage(UIImage(named: "VipFeature/narrow_button_bg"), for: .normal) - button.isHidden = true - button.addTarget(self, action: #selector(handlePhoneDeviceVipTap), for: .touchUpInside) - return button - }() // MARK: - 手机报告 / APP使用记录 lazy var phoneReportView = MemberPhoneReportView() @@ -1463,28 +1403,9 @@ class GroupMemberView2: UIView { stayNodataView.layoutChain .topToBottomOfView(stayTxtLab, offset: 14) .leftToView(stayTxtLab) - - view.addSubview(todayTrackVipView) - todayTrackVipView.translatesAutoresizingMaskIntoConstraints = false - NSLayoutConstraint.activate([ - todayTrackVipView.topAnchor.constraint(equalTo: infoView.topAnchor), - todayTrackVipView.leadingAnchor.constraint(equalTo: infoView.leadingAnchor), - todayTrackVipView.trailingAnchor.constraint(equalTo: infoView.trailingAnchor), - todayTrackVipView.bottomAnchor.constraint(equalTo: infoView.bottomAnchor) - ]) return view }() - - private lazy var todayTrackVipView: UIImageView = { - let view = UIImageView(image: UIImage(named: "MemberVipRequired/today_track")) - view.contentMode = .scaleAspectFill - view.clipsToBounds = true - view.cornerRadius = 16 - view.isHidden = true - view.isUserInteractionEnabled = false - return view - }() lazy var stayNumLab: UILabel = { let label = UILabel() @@ -1630,20 +1551,13 @@ private final class CoupleMemberSlot: UIControl { avatarImageView.setHeadPic(model?.displayHeadPic) avatarImageView.layer.borderColor = UIColor(hexStr: isSelected ? "#FFD43B" : "#FFFFFF").cgColor nameLabel.text = model?.showName - refreshVipVisibility() - } - - func refreshVipVisibility() { - vipImageView.isHidden = member?.shouldShowVipAvatarFrame != true } private func setupUI() { addSubview(avatarImageView) - addSubview(vipImageView) addSubview(nameLabel) avatarImageView.translatesAutoresizingMaskIntoConstraints = false - vipImageView.translatesAutoresizingMaskIntoConstraints = false nameLabel.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ @@ -1652,9 +1566,6 @@ private final class CoupleMemberSlot: UIControl { avatarImageView.widthAnchor.constraint(equalToConstant: 50), avatarImageView.heightAnchor.constraint(equalToConstant: 50), - vipImageView.topAnchor.constraint(equalTo: avatarImageView.topAnchor, constant: -2), - vipImageView.centerXAnchor.constraint(equalTo: avatarImageView.centerXAnchor), - nameLabel.topAnchor.constraint(equalTo: avatarImageView.bottomAnchor, constant: 9), nameLabel.leadingAnchor.constraint(equalTo: leadingAnchor), nameLabel.trailingAnchor.constraint(equalTo: trailingAnchor) @@ -1671,13 +1582,6 @@ private final class CoupleMemberSlot: UIControl { return view }() - private let vipImageView: UIImageView = { - let view = UIImageView(image: UIImage(named: "GroupMemberList/vip")) - view.contentMode = .scaleAspectFit - view.isHidden = true - return view - }() - private let nameLabel: UILabel = { let label = UILabel() label.font = .systemFont(ofSize: 12, weight: .medium) diff --git a/QuickLocation/Section/Home/HomeView.swift b/QuickLocation/Section/Home/HomeView.swift deleted file mode 100644 index 94788f2c..00000000 --- a/QuickLocation/Section/Home/HomeView.swift +++ /dev/null @@ -1,913 +0,0 @@ -// -// HomeView.swift -// QuickLocation -// -// Created by 八条 on 2026/5/27. -// - -import UIKit -import RxSwift -import RxCocoa -import Lottie -#if !targetEnvironment(simulator) -import AMapNaviKit -import MarqueeLabel -#endif - -class HomeView: UIView { - - var disposeBag = DisposeBag() - - let groupMemberView = GroupMemberView(frame: .zero) - - let quickMessageView = QuickMessageView(frame: CGRectMake(0, kScreenHeight, kScreenWidth, 93)) - - let interactionView = InteractionView(frame: CGRectMake(0, kScreenHeight, kScreenWidth, 384)) - - var gpsSignalViewList: [UIView] = [] - - /// 根据信号格数更新信号条颜色 - func updateGPSSignal(bars: Int) { - let filled = max(0, min(bars, gpsSignalViewList.count)) - for (i, view) in gpsSignalViewList.enumerated() { - view.backgroundColor = i < filled ? UIColor(hexStr: "#4ED178") : UIColor(hexStr: "#E0E0E0") - } - } - - // MARK: - groupMemberView 拖拽 - private var groupMemberTopConstraint: NSLayoutConstraint? - private var groupMemberUpLimit: CGFloat = 0 - private var groupMemberDownLimit: CGFloat = 0 - private var isGroupMemberLimitsSet = false - private var panStartTop: CGFloat = 0 - /// 内嵌 tableView 是否可滑动(最大化时才可) - private var isSubCanScroll = false - - private var groupMemberTableTopOffset: CGFloat { - -groupMemberView.tableView.adjustedContentInset.top - } - - // MARK: - Map - #if !targetEnvironment(simulator) - lazy var mapView: MAMapView! = { - let mv = MAMapView() - mv.zoomLevel = 16 - mv.showsUserLocation = true - mv.userTrackingMode = .none - mv.showsCompass = false - mv.showsScale = false - mv.isRotateEnabled = false - mv.isRotateCameraEnabled = false - DispatchQueue.main.async { mv.logoCenter = CGPoint(x: kScreenWidth - 50, y: kScreenHeight / 2 + 65) } - return mv - }() - #else - lazy var mapPlaceholderView: UIView = { - let v = UIView() - v.backgroundColor = UIColor(hexStr: "#EDEDED") - let label = UILabel() - label.text = "Map requires a real device" - label.font = UIFont.systemFont(ofSize: 14) - label.textColor = UIColor(hexStr: "#999999") - label.textAlignment = .center - v.addSubview(label) - label.translatesAutoresizingMaskIntoConstraints = false - NSLayoutConstraint.activate([ - label.centerXAnchor.constraint(equalTo: v.centerXAnchor), - label.centerYAnchor.constraint(equalTo: v.centerYAnchor) - ]) - return v - }() - #endif - - /// 面板关闭回调 - var onDismissPanel: (() -> Void)? - - // MARK: - Setup - private func setupRx() { - quickMessageView.closeBtn.rx.tap - .subscribe(onNext: { [weak self] _ in - self?.dismissMemberPanel() - self?.onDismissPanel?() - }) - .disposed(by: disposeBag) - - groupMemberView.tableView.rx.setDelegate(self) - .disposed(by: disposeBag) - - // 查找位置 - searchLottieView.rx.tapGesture.subscribe { _ in - AppRouter.push(Route.searchLocation) - }.disposed(by: disposeBag) - - // 感叹号 - warningIconView.rx.tapGesture.subscribe { _ in - LocationPermissionPopView.show() - }.disposed(by: disposeBag) - } - - private func setupUI() { - #if !targetEnvironment(simulator) - addSubview(mapView) - #else - addSubview(mapPlaceholderView) - #endif - - addSubview(navBarBg) - addSubview(avatarImgView) - addSubview(groupView) - groupView.addSubview(groupIconView) - groupView.addSubview(groupNameLab) - groupView.addSubview(groupArrowIconView) - addSubview(messageView) - addSubview(messageStackView) - addSubview(toolsView) - addSubview(warningIconView) - addSubview(searchLottieView) - addSubview(locationView) - locationView.addSubview(locationIconView) - addSubview(emojiPopView) - addSubview(sosPopView) - - #if !targetEnvironment(simulator) - mapView.layoutChain - .top() - .edges(excludingEdge: .top) - sendSubviewToBack(mapView) - #else - mapPlaceholderView.layoutChain - .topToBottomOfView(navBarBg) - .left(0).right(0).bottom(0) - #endif - - navBarBg.layoutChain - .edges(excludingEdge: .bottom) - .heightToWidth(160/375) - - avatarImgView.layoutChain - .top(59) - .left(15) - .width(36) - .heightToWidth(1) - - groupView.layoutChain - .centerY(avatarImgView) - .height(36) - .centerX() - .width(185, relation: .greaterThanOrEqual) - - groupIconView.layoutChain - .left(11) - .centerY() - .width(30) - .height(30) - - groupArrowIconView.layoutChain - .right(15) - .centerY() - .width(15) - .height(8.5) - - groupNameLab.layoutChain - .edgesVertical() - .leftToRightOfView(groupIconView) - .rightToLeftOfView(groupArrowIconView) - - messageView.layoutChain - .right(15) - .centerY(groupView) - .width(36) - .height(36) - - messageStackView.layoutChain - .topToBottomOfView(messageView, offset: 23) - .edgesHorzontal(15) - - toolsView.layoutChain - .left(15) - .width(40) - .centerY(self, offset: -50) - - warningIconView.layoutChain - .bottomToTopOfView(toolsView, offset: -10) - .centerX(toolsView) - .width(28) - .heightToWidth(1) - - searchLottieView.layoutChain - .centerY(toolsView) - .right() - .width(100) - .height(100) - - locationView.layoutChain - .right(15) - .bottomToView(toolsView, offset: -10) - .width(40) - .height(40) - - locationIconView.layoutChain - .centerX() - .centerY() - - emojiPopView.layoutChain - .centerX().centerY() - .width(180).height(180) - - sosPopView.layoutChain - .bottomToView(toolsView) - .leftToRightOfView(toolsView) - .height(57).width(57) - - // 圈子成员View - addSubview(groupMemberView) - - groupMemberView.layoutChain - .topToBottomOfView(toolsView, offset: 10) - .edgesHorzontal() - .bottom() - - groupMemberTopConstraint = groupMemberView.jh_constraint( - .top, toAttribute: .bottom, otherView: toolsView, relation: .equal - ) - - let pan = UIPanGestureRecognizer(target: self, action: #selector(handleGroupMemberPan(_:))) - pan.delegate = self - groupMemberView.addGestureRecognizer(pan) - groupMemberView.tableView.isScrollEnabled = false - - // 底部弹出面板(quickMessageView 在上,interactionView 在下) - addSubview(interactionView) - addSubview(quickMessageView) - } - - // MARK: - 底部面板显隐 - func showMemberPanel(member: CircleMember) { - interactionView.configure(member: member) - quickMessageView.isHidden = false - interactionView.isHidden = false - toolsView.isHidden = true - searchLottieView.isHidden = true - quickMessageView.frame.origin.y = kScreenHeight - 384 - 93 - interactionView.frame.origin.y = kScreenHeight - 384 - } - - func dismissMemberPanel() { - quickMessageView.frame.origin.y = kScreenHeight - interactionView.frame.origin.y = kScreenHeight - quickMessageView.isHidden = true - interactionView.isHidden = true - toolsView.isHidden = false - searchLottieView.isHidden = AppContextManager.shared.systemConfig?.isIntercept == true - onDismissPanel?() - } - - override init(frame: CGRect) { - super.init(frame: .zero) - backgroundColor = .white - setupUI() - setupRx() - - searchLottieView.play() - } - - required init?(coder aDecoder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - // MARK: - Layout - override func layoutSubviews() { - super.layoutSubviews() - - noticeView.layoutIfNeeded() - noticeInfoView.setGradientLayer(frame: noticeInfoView.bounds, - startPoint: CGPoint(x: 0, y: 0.5), - endPoint: CGPoint(x: 1, y: 0.5), - colors: [UIColor(hexStr: "#FFFFFF", alpha: 0), UIColor(hexStr: "#FFFFFF"), UIColor(hexStr: "#FFFFFF", alpha: 0)], - locations: [0, 0.5, 1]) - - if !isGroupMemberLimitsSet { - isGroupMemberLimitsSet = true - groupMemberDownLimit = groupMemberView.frame.minY - groupMemberUpLimit = groupView.frame.maxY + 20 - } - } - - // MARK: - Pan Gesture - @objc private func handleGroupMemberPan(_ pan: UIPanGestureRecognizer) { - guard isGroupMemberLimitsSet, let topConstraint = groupMemberTopConstraint else { return } - - switch pan.state { - case .began: - layoutIfNeeded() - panStartTop = groupMemberView.frame.minY - - case .changed: - let newTop = panStartTop + pan.translation(in: self).y - let scrollOffset = groupMemberView.tableView.contentOffset.y - - // 最大化状态下,tableView 可以向下滑时,不干扰自身滑动; - // 只有 tableView 到达顶部继续下拉时,才切换为 view 拖拽 - if isSubCanScroll { - if scrollOffset > groupMemberTableTopOffset + 0.5 { - // 内容正在滑动,不移动 GroupMemberView - return - } - - if pan.velocity(in: self).y > 0 || groupMemberView.frame.minY > groupMemberUpLimit + 1 { - // 内容真正到顶并继续下拉 → 切回面板拖拽 - isSubCanScroll = false - panStartTop = groupMemberView.frame.minY - } - } else { - // GroupMemberView 在顶部且继续上滑 → 激活内容滑动 - if groupMemberView.frame.minY <= groupMemberUpLimit && newTop <= groupMemberUpLimit { - isSubCanScroll = true - panStartTop = groupMemberView.frame.minY - topConstraint.constant = groupMemberUpLimit - groupMemberDownLimit + 10 - return - } - } - - let clamped = max(groupMemberUpLimit, min(groupMemberDownLimit, newTop)) - topConstraint.constant = clamped - groupMemberDownLimit + 10 - - case .ended, .cancelled: - let velocity = pan.velocity(in: self) - let isNearUp = abs(groupMemberView.frame.minY - groupMemberUpLimit) < abs(groupMemberView.frame.minY - groupMemberDownLimit) - let target: CGFloat - if groupMemberView.frame.minY <= groupMemberUpLimit + 5 { - // 顶部附近由位置决定去向,避免 tableView 松手速度触发父面板误回收 - target = isNearUp ? groupMemberUpLimit : groupMemberDownLimit - } else if abs(velocity.y) > 200 { - target = velocity.y < 0 ? groupMemberUpLimit : groupMemberDownLimit - } else { - target = isNearUp ? groupMemberUpLimit : groupMemberDownLimit - } - topConstraint.constant = target - groupMemberDownLimit + 10 - let atTop = target == self.groupMemberUpLimit - if !atTop { - isSubCanScroll = false - groupMemberView.tableView.isScrollEnabled = false - groupMemberView.tableView.setContentOffset(CGPoint(x: 0, y: groupMemberTableTopOffset), animated: false) - } - isSubCanScroll = atTop - - UIView.animate(withDuration: 0.25, delay: 0, - options: [.curveEaseOut, .allowUserInteraction]) { - self.layoutIfNeeded() - } completion: { _ in - self.groupMemberView.tableView.isScrollEnabled = atTop - } - - default: - break - } - } - - /// 收起 GroupMemberView(选中成员后调用) - func dismissGroupMemberView() { - guard isGroupMemberLimitsSet, let topConstraint = groupMemberTopConstraint else { return } - isSubCanScroll = false - groupMemberView.tableView.isScrollEnabled = false - topConstraint.constant = groupMemberDownLimit - groupMemberDownLimit + 10 - groupMemberView.tableView.setContentOffset(CGPoint(x: 0, y: groupMemberTableTopOffset), animated: false) - UIView.animate(withDuration: 0.25, delay: 0, options: .curveEaseOut) { - self.layoutIfNeeded() - } - } - - // MARK: - UI Components - lazy var navBarBg: UIImageView = { - let view = UIImageView() - view.image = UIImage(named: "Home/navBar_bg") - view.contentMode = .scaleAspectFill - return view - }() - - lazy var avatarImgView: UIImageView = { - let view = UIImageView() - view.backgroundColor = .lightGray - view.contentMode = .scaleAspectFill - view.cornerRadius = 18 - return view - }() - - // 圈子选择 - lazy var groupView: UIView = { - let view = UIView() - view.backgroundColor = .white - view.cornerRadius = 18 - return view - }() - - lazy var groupIconView: UIImageView = { - let view = UIImageView() - view.image = UIImage(named: "Home/group") - view.backgroundColor = .clear - view.contentMode = .scaleAspectFill - return view - }() - - lazy var groupNameLab: UILabel = { - let label = UILabel() - label.font = .systemFont(ofSize: 16, weight: .medium) - label.textColor = UIColor(hexStr: "#0F2846") - label.textAlignment = .center - return label - }() - - lazy var groupArrowIconView: UIImageView = { - let view = UIImageView() - view.image = UIImage(named: "Home/arrow_down") - view.backgroundColor = .clear - view.contentMode = .scaleAspectFill - return view - }() - - /// 消息 - lazy var messageView: UIView = { - let view = UIView() - view.backgroundColor = .white - view.cornerRadius = 18 - view.clipsToBounds = false - view.isHidden = true - - view.addSubview(messageIcon) - view.addSubview(messageDotView) - - messageIcon.layoutChain - .centerX().centerY() - - messageDotView.layoutChain - .top() - .right() - .width(10) - .height(10) - - return view - }() - - lazy var messageIcon: UIImageView = { - let view = UIImageView() - view.image = UIImage(named: "Home/message") - view.backgroundColor = .clear - view.contentMode = .scaleAspectFill - return view - }() - - lazy var messageDotView: UIView = { - let view = UIView() - view.backgroundColor = UIColor(hexStr: "#FD5E61") - view.cornerRadius = 5 - return view - }() - - lazy var messageStackView: UIStackView = { - let view = UIStackView(arrangedSubviews: [tipsView, messageBubbleView]) - view.axis = .vertical - view.alignment = .leading - view.spacing = 5 - view.backgroundColor = .clear - return view - }() - - lazy var tipsView: UIView = { - let view = UIView() - view.backgroundColor = .clear - view.layoutChain.height(22) - - view.addSubview(gpsSignalView) - gpsSignalView.layoutChain - .left() - .centerY() - - view.addSubview(noticeView) - noticeView.layoutChain - .leftToRightOfView(gpsSignalView, offset: 0) - .right(15) - .edgesVertical() - - return view - }() - - // MARK: - 卫星信号 - lazy var gpsSignalView: UIView = { - let view = UIView() - view.cornerRadius = 5 - view.backgroundColor = .black.withAlphaComponent(0.4) - - let signalView1 = UIView() - signalView1.backgroundColor = UIColor(hexStr: "#E6E6E6") - view.addSubview(signalView1) - signalView1.layoutChain - .left(7) - .bottom(5) - .width(3) - .height(4) - - let signalView2 = UIView() - signalView2.backgroundColor = UIColor(hexStr: "#E6E6E6") - view.addSubview(signalView2) - signalView2.layoutChain - .leftToRightOfView(signalView1, offset: 2) - .bottomToView(signalView1) - .width(3) - .height(6) - - let signalView3 = UIView() - signalView3.backgroundColor = UIColor(hexStr: "#E6E6E6") - view.addSubview(signalView3) - signalView3.layoutChain - .leftToRightOfView(signalView2, offset: 2) - .bottomToView(signalView1) - .width(3) - .height(8) - - let signalView4 = UIView() - signalView4.backgroundColor = UIColor(hexStr: "#E6E6E6") - view.addSubview(signalView4) - signalView4.layoutChain - .leftToRightOfView(signalView3, offset: 2) - .bottomToView(signalView1) - .width(3) - .height(10) - - let label = UILabel() - label.text = "卫星信号" - label.font = .systemFont(ofSize: 10, weight: .medium) - label.textColor = .white - view.addSubview(label) - label.layoutChain - .leftToRightOfView(signalView4, offset: 2) - .edgesVertical(4) - .right(7) - - gpsSignalViewList = [signalView1, signalView2, signalView3, signalView4] - - return view - }() - - // MARK: - 公告 - lazy var noticeView: UIView = { - let view = UIView() - view.backgroundColor = .clear - - view.addSubview(noticeInfoView) - noticeInfoView.layoutChain - .left() - .right() - .edgesVertical() - - view.addSubview(noticeCloseBtn) - noticeCloseBtn.layoutChain - .right() - .width(16) - .height(16) - .centerY() - - return view - }() - - lazy var noticeInfoView: UIView = { - let view = UIView() - view.backgroundColor = .clear - -// let titleLab = UILabel() -// titleLab.text = "公告信息" -// titleLab.font = .systemFont(ofSize: 10, weight: .medium) -// titleLab.textColor = UIColor(hexStr: "#0F2948") -// view.addSubview(titleLab) -// titleLab.layoutChain -// .left(16) -// .centerY() -// .width(40) - - view.addSubview(noticeLab) - noticeLab.layoutChain - .left(16) - .centerY() - .right(24) - - return view - }() - - lazy var noticeLab: CallbackMarqueeLabel = { - let label = CallbackMarqueeLabel() - label.font = .systemFont(ofSize: 10, weight: .medium) - label.textColor = UIColor(hexStr: "#0F2948") - return label - }() - - lazy var noticeCloseBtn: UIButton = { - let btn = UIButton() - btn.setImage(UIImage(named: "Common/x_black"), for: .normal) - btn.backgroundColor = .white - btn.cornerRadius = 8 - btn.extendEdgeInsets = UIEdgeInsets(top: 15, left: 15, bottom: 15, right: 15) - btn.rx.tap.subscribe(onNext: { [weak self] _ in - self?.noticeView.isHidden = true - }).disposed(by: disposeBag) - return btn - }() - - // MARK: - 消息气泡 - lazy var messageBubbleView: UIView = { - let view = UIView() - view.backgroundColor = .white.withAlphaComponent(0.8) - view.cornerRadius = 10 - view.isHidden = true - - view.addSubview(messageLab) - messageLab.layoutChain - .edges(all: 12) - - return view - }() - - lazy var messageLab: UILabel = { - let label = UILabel() - label.font = .systemFont(ofSize: 12, weight: .medium) - label.textColor = UIColor(hexStr: "#0F2846") - return label - }() - - // MARK: - SOS - lazy var sosPopView: LottieAnimationView = { - let view = LottieAnimationView(name: "siren") - view.loopMode = .loop - view.isHidden = true - return view - }() - - // MARK: - 表情展示 - lazy var emojiPopView: LottieAnimationView = { - let view = LottieAnimationView() - view.loopMode = .playOnce - view.isHidden = true - return view - }() - - // MARK: - warning 惊叹号图标 - lazy var warningIconView: UIImageView = { - let view = UIImageView() - view.image = UIImage(named: "Home/warning") - view.contentMode = .scaleAspectFill - view.isHidden = true - return view - }() - - // MARK: - 侧边工具栏 - lazy var toolsView: UIStackView = { - let view = UIStackView(arrangedSubviews: [bubbleView, signInView, sosView, scheduleView]) - view.axis = .vertical - view.distribution = .fill - view.alignment = .fill - view.backgroundColor = .black.withAlphaComponent(0.5) - view.cornerRadius = 20 - return view - }() - - // 气泡 - lazy var bubbleView: UIView = { - let view = UIView() - view.backgroundColor = .clear - - view.addSubview(bubbleIcon) - bubbleIcon.layoutChain - .top(10) - .centerX() - .width(28) - .height(28) - - view.addSubview(bubbleLab) - bubbleLab.layoutChain - .topToBottomOfView(bubbleIcon, offset: 4) - .edgesHorzontal() - - let lineView = UIView() - lineView.backgroundColor = .white - view.addSubview(lineView) - lineView.layoutChain - .width(12) - .height(2) - .centerX() - .bottom(7) - lineView.layoutChain.topToBottomOfView(bubbleLab, offset: 4) - - return view - }() - - lazy var bubbleIcon: UIImageView = { - let view = UIImageView() - view.image = UIImage(named: "Home/bubble") - view.backgroundColor = .clear - view.contentMode = .scaleAspectFill - return view - }() - - lazy var bubbleLab: UILabel = { - let label = UILabel() - label.text = "气泡" - label.font = .systemFont(ofSize: 10, weight: .medium) - label.textColor = .white - label.textAlignment = .center - return label - }() - - // 签到 - lazy var signInView: UIView = { - let view = UIView() - view.backgroundColor = .clear - - view.addSubview(signInIcon) - signInIcon.layoutChain - .top() - .centerX() - .width(28) - .height(28) - - view.addSubview(signInLab) - signInLab.layoutChain - .topToBottomOfView(signInIcon, offset: 4) - .edgesHorzontal() - - let lineView = UIView() - lineView.backgroundColor = .white - view.addSubview(lineView) - lineView.layoutChain - .width(12) - .height(2) - .centerX() - .bottom(7) - lineView.layoutChain.topToBottomOfView(signInLab, offset: 4) - return view - }() - - lazy var signInIcon: UIImageView = { - let view = UIImageView() - view.image = UIImage(named: "Home/signIn") - view.backgroundColor = .clear - view.contentMode = .scaleAspectFill - return view - }() - - lazy var signInLab: UILabel = { - let label = UILabel() - label.text = "签到" - label.font = .systemFont(ofSize: 10, weight: .medium) - label.textColor = .white - label.textAlignment = .center - return label - }() - - // SOS - lazy var sosView: UIView = { - let view = UIView() - view.backgroundColor = .clear - view.addSubview(sosIcon) - view.addSubview(sosLab) - - sosIcon.layoutChain - .top() - .centerX() - .width(28) - .height(28) - - sosLab.layoutChain - .topToBottomOfView(sosIcon, offset: 4) - .edgesHorzontal() - - let lineView = UIView() - lineView.backgroundColor = .white - view.addSubview(lineView) - lineView.layoutChain - .width(12) - .height(2) - .centerX() - .bottom(7) - lineView.layoutChain.topToBottomOfView(sosLab, offset: 4) - - return view - }() - - lazy var sosIcon: UIImageView = { - let view = UIImageView() - view.image = UIImage(named: "Home/sos") - view.backgroundColor = .clear - view.contentMode = .scaleAspectFill - return view - }() - - lazy var sosLab: UILabel = { - let label = UILabel() - label.text = "SOS" - label.font = .systemFont(ofSize: 10, weight: .medium) - label.textColor = .white - label.textAlignment = .center - return label - }() - - // 行程 - lazy var scheduleView: UIView = { - let view = UIView() - view.backgroundColor = .clear - - let icon = UIImageView(image: UIImage(named: "Home/schedule")) - icon.contentMode = .scaleAspectFill - view.addSubview(icon) - icon.layoutChain - .top() - .centerX() - .width(28) - .height(28) - - let label = UILabel() - label.text = "行程" - label.font = .systemFont(ofSize: 10, weight: .medium) - label.textColor = .white - label.textAlignment = .center - view.addSubview(label) - label.layoutChain - .topToBottomOfView(icon, offset: 4) - .edgesHorzontal() - label.layoutChain.bottom(10) - - return view - }() - - // MARK: - 查位置 - lazy var searchLottieView: LottieAnimationView = { - let view = LottieAnimationView(name: "home_search") - view.loopMode = .loop - return view - }() - - // MARK: - 定位按钮 - lazy var locationView: UIView = { - let view = UIView() - view.backgroundColor = .black.withAlphaComponent(0.4) - view.cornerRadius = 20 - return view - }() - - lazy var locationIconView: UIImageView = { - let view = UIImageView() - view.backgroundColor = .clear - view.image = UIImage(named: "Home/location") - return view - }() -} - -// MARK: - UIScrollViewDelegate -extension HomeView: UIScrollViewDelegate { - func scrollViewWillBeginDragging(_ scrollView: UIScrollView) { - guard scrollView == groupMemberView.tableView else { return } - if scrollView.contentOffset.y > groupMemberTableTopOffset { - isSubCanScroll = true - } - } - - func scrollViewDidScroll(_ scrollView: UIScrollView) { - guard scrollView == groupMemberView.tableView else { return } - if isSubCanScroll { - if scrollView.contentOffset.y <= groupMemberTableTopOffset { - isSubCanScroll = false - scrollView.contentOffset = CGPoint(x: 0, y: groupMemberTableTopOffset) - } - } else { - scrollView.contentOffset = CGPoint(x: 0, y: groupMemberTableTopOffset) - } - } -} - -// MARK: - UIGestureRecognizerDelegate -extension HomeView: UIGestureRecognizerDelegate { - func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, - shouldRecognizeSimultaneouslyWith other: UIGestureRecognizer) -> Bool { - // 允许 GroupMemberView 的 pan 与 tableView 的 pan 同时识别 - // 滚动状态由 isSubCanScroll + contentOffset 控制,不影响手势判定 - return true - } -} - -// MARK: - CallbackMarqueeLabel -class CallbackMarqueeLabel: MarqueeLabel { - // 闭包回调对外抛出事件 - var onScrollLoopComplete: (() -> Void)? - var onScrollStart: (() -> Void)? - - // 滚动开始 - override func labelWillBeginScroll() { - super.labelWillBeginScroll() - onScrollStart?() - } - - // 单次滚动一圈完成 - override func labelReturnedToHome(_ finished: Bool) { - super.labelReturnedToHome(finished) - // 只处理正常滚动结束,过滤中途重置 - guard finished else { return } - onScrollLoopComplete?() - } -} diff --git a/QuickLocation/Section/Home/HomeViewController.swift b/QuickLocation/Section/Home/HomeViewController.swift index 4fde6ccf..6a5aa1c1 100644 --- a/QuickLocation/Section/Home/HomeViewController.swift +++ b/QuickLocation/Section/Home/HomeViewController.swift @@ -72,7 +72,6 @@ class HomeViewController: BaseViewController { private var lastUpdateTimes: [String: Date] = [:] /// 离线检测定时器 private var offlineCheckTimer: Timer? - private var popupQueue: PopupQueueManager? private static var sosPlayerKey: UInt8 = 0 private var groupRefreshWorkItem: DispatchWorkItem? private var groupDataRetryWorkItem: DispatchWorkItem? @@ -330,12 +329,7 @@ class HomeViewController: BaseViewController { // 今日轨迹二级页 rootView.groupMemberView.todayTrackView.rx.tapGesture.subscribe(onNext: { [weak self] _ in - guard let self else { return } - if self.rootView.groupMemberView.isTodayTrackVipRequired { - AppRouter.push(Route.web, userInfo: ["url": URLManager.shared.homeUrl]) - } else { - self.openTodayTrackDetail() - } + self?.openTodayTrackDetail() }).disposed(by: disposeBag) // 实时互动 @@ -350,10 +344,6 @@ class HomeViewController: BaseViewController { // 手机报告二级页 rootView.groupMemberView.phoneReportView.rx.tapGesture.subscribe(onNext: { [weak self] _ in guard let self else { return } - if self.rootView.groupMemberView.isPhoneReportVipRequired { - AppRouter.push(Route.web, userInfo: ["url": URLManager.shared.homeUrl]) - return - } guard !self.rootView.groupMemberView.isPhoneReportDenied else { return } self.openPhoneReportDetail() }).disposed(by: disposeBag) @@ -361,10 +351,6 @@ class HomeViewController: BaseViewController { // APP 报告二级页 rootView.groupMemberView.appUsageView.rx.tapGesture.subscribe(onNext: { [weak self] _ in guard let self else { return } - if self.rootView.groupMemberView.isAppUsageVipRequired { - AppRouter.push(Route.web, userInfo: ["url": URLManager.shared.homeUrl]) - return - } guard !self.rootView.groupMemberView.isAppUsageDenied else { return } self.openAppUsageReport() }).disposed(by: disposeBag) @@ -384,9 +370,6 @@ class HomeViewController: BaseViewController { // User Config刷新 NotificationCenter.default.rx.notification(.RefreshUserConfigNotification, object: nil) .startWith(Notification(name: .RefreshUserConfigNotification)) - .do(onNext: { [weak self] _ in - self?.popupQueue = nil - }) .flatMapLatest { _ in SystemService.userConfig() } @@ -395,15 +378,11 @@ class HomeViewController: BaseViewController { Defaults[\.loginToken] = model.token AppContextManager.shared.systemConfig = model.config self.rootView.groupMemberView.refreshInterceptState() -// rootView.searchLottieView.isHidden = model.config?.isIntercept == true self.requestUserInfo { [weak self] in self?.requestGroupInfo() } self.requestNotice() self.refreshPigeonInbox() - self.popupQueue = nil - self.popupQueue = PopupQueueManager() -// self.popupQueue?.start(from: self) }).disposed(by: disposeBag) // 圈子刷新 @@ -849,7 +828,7 @@ class HomeViewController: BaseViewController { return } - self.viewModel.updateGroupUsers(response.list, vip: response.vip) + self.viewModel.updateGroupUsers(response.list) // 成员接口是气泡结束的权威来源:status=0 时重新显示地图点。 self.syncMemberAnnotations(self.viewModel.memberList) self.refreshMQTTSubscriptions(self.viewModel.memberList) @@ -1184,8 +1163,7 @@ class HomeViewController: BaseViewController { rootView.groupMemberView.setupMemberInfo( model, isOwner: viewModel.isGroupOwn(id: model.user_id), - phoneUsage: usage, - groupVip: viewModel.groupVip + phoneUsage: usage ) } diff --git a/QuickLocation/Section/Home/HomeViewModel.swift b/QuickLocation/Section/Home/HomeViewModel.swift index a2483ca5..dc366630 100644 --- a/QuickLocation/Section/Home/HomeViewModel.swift +++ b/QuickLocation/Section/Home/HomeViewModel.swift @@ -87,7 +87,6 @@ class HomeViewModel { } private(set) var memberList: [GroupMemberModel] = [] - private(set) var groupVip = GroupMemberVip() func markMemberInBubble(userId: String) { updateMemberStatus(userId: userId, status: 2) @@ -113,13 +112,11 @@ class HomeViewModel { sectionedItems.onNext(memberList.mapSection()) } - func updateGroupUsers(_ list: [GroupMemberModel], vip: GroupMemberVip) { - groupVip = vip + func updateGroupUsers(_ list: [GroupMemberModel]) { updateMembers(list) } func clearMembers() { - groupVip = GroupMemberVip() updateMembers([]) } diff --git a/QuickLocation/Section/Home/InteractionEmojiCell.swift b/QuickLocation/Section/Home/InteractionEmojiCell.swift index 9485ea4a..33e0b857 100644 --- a/QuickLocation/Section/Home/InteractionEmojiCell.swift +++ b/QuickLocation/Section/Home/InteractionEmojiCell.swift @@ -76,8 +76,5 @@ final class InteractionEmojiCell: UICollectionViewCell { let path = Bundle.main.path(forResource: "\(pngName)", ofType: "png") { imageView.image = UIImage(contentsOfFile: path) } - - guard AppContextManager.shared.systemConfig?.isIntercept == false else { return } - lockView.isHidden = name.hasPrefix("normal_") || AppContextManager.shared.vip > 1 } } diff --git a/QuickLocation/Section/Home/InteractionView.swift b/QuickLocation/Section/Home/InteractionView.swift index 652c3b60..7940b8e0 100644 --- a/QuickLocation/Section/Home/InteractionView.swift +++ b/QuickLocation/Section/Home/InteractionView.swift @@ -25,22 +25,15 @@ class InteractionView: UIView { nameLab.text = member.name locationLab.text = member.address - // 会员权益 - if AppContextManager.shared.vip > 1 { - batteryInfoView.isHidden = member.battery.int == 0 - // 电量 - let batteryInt = Int(member.battery) ?? 0 - let batteryPercent = min(CGFloat(batteryInt), 100) - batteryView.layoutChain.width(CGFloat(16 - 1) * batteryPercent / 100.0) - batteryLab.text = "\(member.battery)%" + batteryInfoView.isHidden = member.battery.int == 0 + // 电量 + let batteryInt = Int(member.battery) ?? 0 + let batteryPercent = min(CGFloat(batteryInt), 100) + batteryView.layoutChain.width(CGFloat(16 - 1) * batteryPercent / 100.0) + batteryLab.text = "\(member.battery)%" - // 趣味表情 - lockView.isHidden = true - } - else { - batteryInfoView.isHidden = true - lockView.isHidden = false - } + // 趣味表情 + lockView.isHidden = true } /// 当前表情列表(normal / fun) @@ -84,7 +77,7 @@ class InteractionView: UIView { emojiCollectionView.rx.modelSelected(String.self) .subscribe(onNext: { [weak self] name in guard let self = self else { return } - if name.hasPrefix("fun_"), AppContextManager.shared.vip <= 1 { return } + if name.hasPrefix("fun_") { return } // 解析 index: normal_5 → 15, fun_2 → 22 let prefix: String let numStr: String @@ -612,7 +605,7 @@ final class EmojiPanelCell: UICollectionViewCell { self.lottieView.play() } - lockView.isHidden = true//AppContextManager.shared.vip > 1 + lockView.isHidden = true } func playAnimation() { diff --git a/QuickLocation/Section/Home/MemberAppUsageView.swift b/QuickLocation/Section/Home/MemberAppUsageView.swift index ec5606bd..90308b03 100644 --- a/QuickLocation/Section/Home/MemberAppUsageView.swift +++ b/QuickLocation/Section/Home/MemberAppUsageView.swift @@ -74,10 +74,8 @@ final class MemberAppUsageView: UIView { private let usageTitleLab = UILabel() private let topTitleLab = UILabel() private let topStack = UIStackView() - private let vipRequiredView = UIImageView() private let deniedOverlay = PrivilegeDeniedOverlay() private(set) var isDenied = false - private(set) var isVipRequired = false var onDeniedAction: (() -> Void)? override init(frame: CGRect) { @@ -92,7 +90,6 @@ final class MemberAppUsageView: UIView { func setAccessState(_ state: MemberFeatureAccessState) { isDenied = state == .privilegeDenied - isVipRequired = state == .vipRequired deniedOverlay.configure( title: "TA未开启设置", message: "无法查看app使用记录", @@ -102,9 +99,8 @@ final class MemberAppUsageView: UIView { deniedOverlay.onAction = { [weak self] in self?.onDeniedAction?() } deniedOverlay.setVisible(isDenied) deniedOverlay.layer.cornerRadius = cardView.layer.cornerRadius - vipRequiredView.isHidden = !isVipRequired [usageTitleLab, topTitleLab, donutView, totalTimeLab, totalHintLab, topStack].forEach { - $0.isHidden = isVipRequired + $0.isHidden = false } gestureRecognizers?.forEach { $0.isEnabled = !isDenied } } @@ -207,14 +203,6 @@ final class MemberAppUsageView: UIView { .left(160) .right(14) - vipRequiredView.image = UIImage(named: "MemberVipRequired/app_usage") - vipRequiredView.contentMode = .scaleAspectFill - vipRequiredView.clipsToBounds = true - vipRequiredView.isHidden = true - vipRequiredView.isUserInteractionEnabled = false - cardView.addSubview(vipRequiredView) - vipRequiredView.layoutChain.edges() - cardView.bringSubviewToFront(deniedOverlay) } diff --git a/QuickLocation/Section/Home/MemberPhoneReportView.swift b/QuickLocation/Section/Home/MemberPhoneReportView.swift index 1b9eeca1..e6f2863a 100644 --- a/QuickLocation/Section/Home/MemberPhoneReportView.swift +++ b/QuickLocation/Section/Home/MemberPhoneReportView.swift @@ -52,10 +52,8 @@ final class MemberPhoneReportView: UIView { private let unlockIcon = UIImageView() private let unlockTitleLab = UILabel() private let unlockValueLab = UILabel() - private let vipRequiredView = UIImageView() private let deniedOverlay = PrivilegeDeniedOverlay() private(set) var isDenied = false - private(set) var isVipRequired = false var onDeniedAction: (() -> Void)? override init(frame: CGRect) { @@ -70,7 +68,6 @@ final class MemberPhoneReportView: UIView { func setAccessState(_ state: MemberFeatureAccessState) { isDenied = state == .privilegeDenied - isVipRequired = state == .vipRequired deniedOverlay.configure( title: "TA未开启设置", message: "无法查看手机报告", @@ -80,9 +77,8 @@ final class MemberPhoneReportView: UIView { deniedOverlay.onAction = { [weak self] in self?.onDeniedAction?() } deniedOverlay.setVisible(isDenied) deniedOverlay.layer.cornerRadius = cardView.layer.cornerRadius - vipRequiredView.isHidden = !isVipRequired - leftPanel.isHidden = isVipRequired - rightPanel.isHidden = isVipRequired + leftPanel.isHidden = false + rightPanel.isHidden = false gestureRecognizers?.forEach { $0.isEnabled = !isDenied } } @@ -265,14 +261,6 @@ final class MemberPhoneReportView: UIView { .leftToRightOfView(unlockValueLab, offset: 3) .bottomToView(unlockValueLab, offset: -4) - vipRequiredView.image = UIImage(named: "MemberVipRequired/phone_report") - vipRequiredView.contentMode = .scaleAspectFill - vipRequiredView.clipsToBounds = true - vipRequiredView.isHidden = true - vipRequiredView.isUserInteractionEnabled = false - cardView.addSubview(vipRequiredView) - vipRequiredView.layoutChain.edges() - cardView.bringSubviewToFront(deniedOverlay) } } diff --git a/QuickLocation/Section/Home/SearchLocation/SearchLocationResultVC.swift b/QuickLocation/Section/Home/SearchLocation/SearchLocationResultVC.swift index 47534589..0e620865 100644 --- a/QuickLocation/Section/Home/SearchLocation/SearchLocationResultVC.swift +++ b/QuickLocation/Section/Home/SearchLocation/SearchLocationResultVC.swift @@ -36,32 +36,13 @@ class SearchLocationResultVC: BaseViewController { applyResultPresentation() } - private func isVipUnlocked() -> Bool { - AppContextManager.shared.vip > 1 - } - private func applyResultPresentation() { handleCode() - let isVip = isVipUnlocked() - rootView.updateVipAccess(isUnlocked: isVip) - if !isVip { - rootView.actionBtn.setTitle("开通会员 解锁功能", for: .normal) - rootView.actionBtn.isHidden = false - } + rootView.updateSubViews() } private func reactiveAction() { - rootView.vipMaskView.rx.tap - .subscribe(onNext: { - AppRouter.push(Route.web, userInfo: ["url": URLManager.shared.homeUrl]) - }) - .disposed(by: disposeBag) - rootView.actionBtn.rx.tap.subscribe(onNext: { _ in - guard self.isVipUnlocked() else { - AppRouter.push(Route.web, userInfo: ["url": URLManager.shared.homeUrl]) - return - } switch self.code { case 0: NotificationCenter.default.post(name: .ShowMemberLocationNotification, diff --git a/QuickLocation/Section/Home/SearchLocation/SearchLocationResultView.swift b/QuickLocation/Section/Home/SearchLocation/SearchLocationResultView.swift index d0d8d022..0ca442fd 100644 --- a/QuickLocation/Section/Home/SearchLocation/SearchLocationResultView.swift +++ b/QuickLocation/Section/Home/SearchLocation/SearchLocationResultView.swift @@ -9,7 +9,6 @@ import Lottie class SearchLocationResultView: UIView { let headerView = SearchLocationHeaderView() - private var vipResultHeightConstraint: NSLayoutConstraint? private func setupUI() { addSubview(navBgView) @@ -45,15 +44,8 @@ class SearchLocationResultView: UIView { .height(showInviteRow ? 72 : 0) } - func updateVipAccess(isUnlocked: Bool) { - normalResultContentView.isHidden = !isUnlocked - vipMaskView.isHidden = isUnlocked - vipOfferImageView.isHidden = isUnlocked - vipResultHeightConstraint?.isActive = !isUnlocked - actionBtn.setBackgroundImage( - UIImage(named: isUnlocked ? "Common/button_bg_2" : "VipFeature/wide_button_bg"), - for: .normal - ) + func updateSubViews() { + normalResultContentView.isHidden = false } lazy var navBgView: UIImageView = { @@ -85,7 +77,6 @@ class SearchLocationResultView: UIView { resultCard.layoutChain .topToBottomOfView(headerView, offset: 20) .edgesHorzontal(15) - vipResultHeightConstraint = resultCard.heightAnchor.constraint(equalToConstant: 158) contentView.addSubview(actionBtn) actionBtn.layoutChain @@ -94,15 +85,6 @@ class SearchLocationResultView: UIView { .height(56) .bottom(kSafeBottomMargin + 30) - contentView.addSubview(vipOfferImageView) - vipOfferImageView.translatesAutoresizingMaskIntoConstraints = false - NSLayoutConstraint.activate([ - vipOfferImageView.trailingAnchor.constraint(equalTo: actionBtn.trailingAnchor, constant: -6), - vipOfferImageView.bottomAnchor.constraint(equalTo: actionBtn.topAnchor, constant: 10), - vipOfferImageView.widthAnchor.constraint(equalToConstant: 94), - vipOfferImageView.heightAnchor.constraint(equalToConstant: 32) - ]) - return view }() @@ -115,8 +97,6 @@ class SearchLocationResultView: UIView { resultStackView.layoutChain.edges() resultStackView.addArrangedSubview(normalResultContentView) - card.addSubview(vipMaskView) - vipMaskView.layoutChain.edges() return card }() @@ -233,13 +213,6 @@ class SearchLocationResultView: UIView { return btn }() - private lazy var vipOfferImageView: UIImageView = { - let view = UIImageView(image: UIImage(named: "VipFeature/limited_offer")) - view.contentMode = .scaleAspectFit - view.isHidden = true - return view - }() - var inviteBtn: UIButton { actionBtn } lazy var inviteView: UIView = { @@ -282,13 +255,6 @@ class SearchLocationResultView: UIView { btn.cornerRadius = 18 return btn }() - - lazy var vipMaskView: UIButton = { - let view = UIButton(type: .custom) - view.setBackgroundImage(UIImage(named: "VipFeature/realtime_location"), for: .normal) - view.isHidden = true - return view - }() override init(frame: CGRect) { super.init(frame: .zero) diff --git a/QuickLocation/Section/Home/TodayTrackDetail/TodayTrackDetailVC.swift b/QuickLocation/Section/Home/TodayTrackDetail/TodayTrackDetailVC.swift index 4cc642c2..9fee3808 100644 --- a/QuickLocation/Section/Home/TodayTrackDetail/TodayTrackDetailVC.swift +++ b/QuickLocation/Section/Home/TodayTrackDetail/TodayTrackDetailVC.swift @@ -130,12 +130,6 @@ final class TodayTrackDetailVC: BaseViewController { }) .disposed(by: disposeBag) - rootView.vipRequiredBtn.rx.tap - .subscribe(onNext: { - AppRouter.push(Route.web, userInfo: ["url": URLManager.shared.homeUrl]) - }) - .disposed(by: disposeBag) - viewModel.displayedTrips .observe(on: MainScheduler.instance) .subscribe(onNext: { [weak self] trips in @@ -146,22 +140,7 @@ final class TodayTrackDetailVC: BaseViewController { viewModel.isEmpty .observe(on: MainScheduler.instance) .subscribe(onNext: { [weak self] empty in - guard let self, !self.viewModel.isVipRequired.value else { return } - self.rootView.emptyLab.isHidden = !empty - }) - .disposed(by: disposeBag) - - viewModel.isVipRequired - .observe(on: MainScheduler.instance) - .distinctUntilChanged() - .subscribe(onNext: { [weak self] required in - guard let self else { return } - self.stopPlayback(resetProgress: true) - self.rootView.setVipRequired(required) - self.updateSheetHeight(isVipRequired: required) - if !required { - self.rootView.emptyLab.isHidden = !self.viewModel.isEmpty.value - } + self?.rootView.emptyLab.isHidden = !empty }) .disposed(by: disposeBag) @@ -202,14 +181,6 @@ final class TodayTrackDetailVC: BaseViewController { } - private func updateSheetHeight(isVipRequired: Bool) { - guard let constraint = rootView.sheetHeightConstraint else { return } - let minHeight: CGFloat = 200 + kSafeBottomMargin - let maxHeight: CGFloat = UIScreen.main.bounds.height * 0.7 - let vipHeight: CGFloat = UIScreen.main.bounds.height * 0.47 - constraint.constant = isVipRequired ? min(maxHeight, max(minHeight, vipHeight)) : minHeight - } - private func bindSheetPan() { let pan = UIPanGestureRecognizer() rootView.sheetView.addGestureRecognizer(pan) diff --git a/QuickLocation/Section/Home/TodayTrackDetail/TodayTrackDetailView.swift b/QuickLocation/Section/Home/TodayTrackDetail/TodayTrackDetailView.swift index 806c3790..bad6f0ba 100644 --- a/QuickLocation/Section/Home/TodayTrackDetail/TodayTrackDetailView.swift +++ b/QuickLocation/Section/Home/TodayTrackDetail/TodayTrackDetailView.swift @@ -150,14 +150,6 @@ final class TodayTrackDetailView: UIView { return lab }() - let vipRequiredBtn: UIButton = { - let btn = UIButton(type: .custom) - btn.setImage(UIImage(named: "Home/HistoryTrack/vip_required"), for: .normal) - btn.imageView?.contentMode = .scaleAspectFit - btn.isHidden = true - return btn - }() - private(set) var sheetHeightConstraint: NSLayoutConstraint? override init(frame: CGRect) { @@ -272,19 +264,6 @@ final class TodayTrackDetailView: UIView { .centerX() .topToBottomOfView(dateBar, offset: 40) - sheetView.addSubview(vipRequiredBtn) - vipRequiredBtn.layoutChain - .topToBottomOfView(dateBar, offset: 28) - .centerX() - .width(303) - .height(139) - } - - func setVipRequired(_ required: Bool) { - vipRequiredBtn.isHidden = !required - timelineTV.isHidden = required - emptyLab.isHidden = true - playbackBar.isHidden = required } func cleanupMap() { diff --git a/QuickLocation/Section/Home/TodayTrackDetail/TodayTrackDetailViewModel.swift b/QuickLocation/Section/Home/TodayTrackDetail/TodayTrackDetailViewModel.swift index e3f37a92..bf54888e 100644 --- a/QuickLocation/Section/Home/TodayTrackDetail/TodayTrackDetailViewModel.swift +++ b/QuickLocation/Section/Home/TodayTrackDetail/TodayTrackDetailViewModel.swift @@ -23,7 +23,6 @@ final class TodayTrackDetailViewModel { let selectedTripId = BehaviorRelay(value: nil) let displayedTrips = BehaviorRelay<[ScheduleRecordModel]>(value: []) let isEmpty = BehaviorRelay(value: true) - let isVipRequired = BehaviorRelay(value: false) let loading = BehaviorRelay(value: false) private let disposeBag = DisposeBag() @@ -76,7 +75,6 @@ final class TodayTrackDetailViewModel { selectedTripId.accept(nil) trips.accept([]) displayedTrips.accept([]) - isVipRequired.accept(false) isEmpty.accept(false) loadTrips(userId: userId, dateKey: dateKey) } @@ -95,19 +93,14 @@ final class TodayTrackDetailViewModel { .subscribe(onNext: { [weak self] response in guard let self, self.requestToken == token else { return } self.applyTrips(response.trips) - }, onError: { [weak self] error in + }, onError: { [weak self] _ in guard let self, self.requestToken == token else { return } - if error.gatewayStatusCode == 22000 { - self.applyVipRequired() - return - } self.applyTrips([]) }) .disposed(by: disposeBag) } private func applyTrips(_ list: [ScheduleRecordModel]) { - isVipRequired.accept(false) let sorted = list.sorted { $0.start_time < $1.start_time } trips.accept(sorted) if selectedTripId.value == nil || !sorted.contains(where: { $0.id == selectedTripId.value }) { @@ -117,15 +110,6 @@ final class TodayTrackDetailViewModel { loading.accept(false) } - private func applyVipRequired() { - selectedTripId.accept(nil) - trips.accept([]) - displayedTrips.accept([]) - isEmpty.accept(false) - isVipRequired.accept(true) - loading.accept(false) - } - private func applyDisplayedTrips() { let all = trips.value if let id = selectedTripId.value, let one = all.first(where: { $0.id == id }) { diff --git a/QuickLocation/Section/Launch/LaunchViewController.swift b/QuickLocation/Section/Launch/LaunchViewController.swift index 75121958..9f7eed87 100644 --- a/QuickLocation/Section/Launch/LaunchViewController.swift +++ b/QuickLocation/Section/Launch/LaunchViewController.swift @@ -12,14 +12,6 @@ import RxCocoa class LaunchViewController: BaseViewController { - private let guideImgList: [String] = [ - "guide_1", - "guide_2", - "guide_3", - "guide_4", - "guide_5" - ] - private let showVersion = 1 override func viewDidLoad() { @@ -28,31 +20,9 @@ class LaunchViewController: BaseViewController { // Do any additional setup after loading the view. view.backgroundColor = .white setupLayout() - - experienceBtn.rx.tap.subscribe(onNext: { _ in - Defaults[\.isShowGuide] = false - AppDelegate.shared.showMainViewController() - }).disposed(by: disposeBag) - getUserConfig() } - private func navigateAfterDelay() { - Observable.just(()) - .delay(.milliseconds(2500), scheduler: MainScheduler.instance) - .subscribe(onNext: { [weak self] in - guard let systemConfig = AppContextManager.shared.systemConfig else { return } - if systemConfig.guideDisplay, Defaults[\.isShowGuide] { - self?.collectionView.isHidden = false - self?.pageControl.isHidden = false - self?.experienceBtn.isHidden = false - } else { - AppDelegate.shared.showMainViewController() - } - }) - .disposed(by: disposeBag) - } - /// 获取用户配置 func getUserConfig() { SystemService.userConfig().subscribe(onNext: { response in @@ -122,7 +92,7 @@ class LaunchViewController: BaseViewController { } private func continueAfterConfig(model: UserConfigModel) { - self.navigateAfterDelay() + AppDelegate.shared.showMainViewController() } private func showVersionUpgrade(_ upgrade: VersionUpgradeModel, model: UserConfigModel) { @@ -155,62 +125,12 @@ class LaunchViewController: BaseViewController { view.contentMode = .scaleAspectFill return view }() - - /// 引导页 - lazy var collectionView: UICollectionView = { - let viewFlowLayout = UICollectionViewFlowLayout() - viewFlowLayout.scrollDirection = .horizontal - viewFlowLayout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) - viewFlowLayout.minimumLineSpacing = 0 - viewFlowLayout.minimumInteritemSpacing = 0 - viewFlowLayout.itemSize = CGSizeMake(kScreenWidth, kScreenHeight) - - let collectionView = UICollectionView(frame: .zero, collectionViewLayout: viewFlowLayout) - collectionView.backgroundColor = .white - collectionView.dataSource = self - collectionView.delegate = self - collectionView.showsVerticalScrollIndicator = false - collectionView.showsHorizontalScrollIndicator = false - collectionView.isPagingEnabled = true - collectionView.bounces = false - collectionView.register(GuideCell.self) - collectionView.isHidden = true - return collectionView - }() - - lazy var experienceBtn: UIButton = { - let btn = UIButton(type: .custom) - btn.setTitle("立即体验", for: .normal) - btn.setTitleColor(UIColor(hexStr: "#0F2846"), for: .normal) - btn.titleLabel?.font = .systemFont(ofSize: 16, weight: .medium) - btn.setBackgroundImage(UIImage(named: "Guide/experience"), for: .normal) - btn.isHidden = true - return btn - }() - - lazy var pageControl: JJPageControl = { - let pageControl = JJPageControl(frame: CGRectMake(0, 0, kScreenWidth, 10)) - pageControl.currentColor = ThemeManager.shared.color.mainColor - pageControl.currentPointSize = CGSize(width: 20, height: 6) - pageControl.otherColor = ThemeManager.shared.color.mainColor.withAlphaComponent(0.5) - pageControl.otherPointSize = CGSize(width: 6, height: 6) - pageControl.pointCornerRadius = 3 - pageControl.controlSpacing = 18 - pageControl.pageAliment = .Center - pageControl.backgroundColor = .clear - pageControl.numberOfPages = guideImgList.count - pageControl.isHidden = true - return pageControl - }() } extension LaunchViewController { private func setupLayout() { view.addSubview(launchLogoView) view.addSubview(tipsImgView) - view.addSubview(collectionView) - view.addSubview(experienceBtn) - view.addSubview(pageControl) launchLogoView.layoutChain .centerX() @@ -219,74 +139,5 @@ extension LaunchViewController { tipsImgView.layoutChain .centerX() .bottom(kSafeBottomMargin + 50) - - collectionView.layoutChain.edges() - - experienceBtn.layoutChain - .bottom(kSafeBottomMargin + 23) - .width(245) - .height(50) - .centerX() - - pageControl.layoutChain - .bottomToTopOfView(experienceBtn, offset: -25) - .edgesHorzontal(10) - .centerX() - .height(10) - } -} - -// MARK: - UICollectionViewDataSource -extension LaunchViewController: UICollectionViewDataSource { - func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { - guideImgList.count - } - - func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { - let cell: GuideCell = collectionView.dequeueReusableCell(for: indexPath) - cell.configure(imageName: guideImgList[indexPath.row]) - return cell - } -} - -// MARK: - UICollectionViewDelegate -extension LaunchViewController: UICollectionViewDelegate { - func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { - if scrollView == collectionView { - let page = Int(scrollView.contentOffset.x / scrollView.dl.width) - pageControl.currentPage = page - } - } -} - -class GuideCell: UICollectionViewCell { - - func configure(imageName: String) { - imgView.image = UIImage(named: "Guide/" + imageName) - } - - private func setupSubViews() { - addSubview(imgView) - setupLayout() - } - - private func setupLayout() { - imgView.layoutChain.edges() - } - - lazy var imgView: UIImageView = { - let icon = UIImageView() - icon.contentMode = .scaleAspectFill - return icon - }() - - override init(frame: CGRect) { - super.init(frame: frame) - contentView.backgroundColor = .clear - setupSubViews() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") } } diff --git a/QuickLocation/Section/LockDistract/LockDistractVC.swift b/QuickLocation/Section/LockDistract/LockDistractVC.swift index 408359e6..5f7a9734 100644 --- a/QuickLocation/Section/LockDistract/LockDistractVC.swift +++ b/QuickLocation/Section/LockDistract/LockDistractVC.swift @@ -13,12 +13,10 @@ final class LockDistractVC: BaseViewController { private var groupModel: GroupModel? private var ownedGroups: [GroupInfoModel] = [] private var activeGroupKey: String = "" - private var groupVip = GroupMemberVip() private var members: [GroupMemberModel] = [] private var selectedIndex = 0 private var lockAppsDisposable: Disposable? private let lockStateSubscriptionOwner = UUID() - private var hasAppeared = false override var isNavigationBarHidden: Bool { true } @@ -31,18 +29,9 @@ final class LockDistractVC: BaseViewController { super.viewDidLoad() view.backgroundColor = UIColor(hexStr: "#FAFAFA") bind() - applyGroupVip(groupVip) loadGroupMembers() } - override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - if hasAppeared { - refreshGroupVip() - } - hasAppeared = true - } - @MainActor deinit { MQTTService.shared.updateLockStateSubscriptions( owner: lockStateSubscriptionOwner, @@ -156,7 +145,6 @@ final class LockDistractVC: BaseViewController { private func loadUsers(for groupKey: String) { guard !groupKey.isEmpty else { - applyGroupVip(GroupMemberVip()) applyMembers([]) return } @@ -167,7 +155,6 @@ final class LockDistractVC: BaseViewController { return } guard let self, self.activeGroupKey == groupKey else { return } - self.applyGroupVip(response.vip) self.applyMembers(response.list) }, onError: { error in DLToast.showError(error) @@ -187,28 +174,6 @@ final class LockDistractVC: BaseViewController { loadLockableApps() } - private var isAppLockVipUnlocked: Bool { - groupVip.app_lock == true - } - - private func applyGroupVip(_ vip: GroupMemberVip) { - groupVip = vip - rootView.updateVipAccess(isUnlocked: isAppLockVipUnlocked) - } - - private func refreshGroupVip() { - let groupKey = activeGroupKey - guard !groupKey.isEmpty else { return } - GroupService.groupUsers(groupKey: groupKey) - .subscribe(onNext: { [weak self] response in - guard let self, - self.activeGroupKey == groupKey, - response.isValid(for: groupKey) else { return } - self.applyGroupVip(response.vip) - }, onError: { _ in }) - .disposed(by: disposeBag) - } - private func stepMember(_ delta: Int) { guard !members.isEmpty else { return } let count = members.count @@ -326,9 +291,8 @@ final class LockDistractVC: BaseViewController { } DLToast.showLoading() UserService.requestPhoneUnlock(os: os, groupKey: activeGroupKey, tokens: tokens) - .subscribe(onNext: { [weak self] _ in + .subscribe(onNext: { _ in DLToast.show(text: "已向圈主发送解锁请求") - self?.refreshGroupVip() }, onError: { error in DLToast.show(error, fallbackText: "发送失败") }) @@ -359,7 +323,6 @@ final class LockDistractVC: BaseViewController { self?.rootView.lockBtn.isEnabled = true DLToast.show(text: "已解锁") self?.loadLockableApps() - self?.refreshGroupVip() }, onError: { [weak self] error in self?.rootView.lockBtn.isEnabled = true DLToast.show(error, fallbackText: "解锁失败") @@ -368,10 +331,6 @@ final class LockDistractVC: BaseViewController { } private func performPrimaryAction() { - if rootView.primaryAction == .lock, !isAppLockVipUnlocked { - AppRouter.push(Route.web, userInfo: ["url": URLManager.shared.homeUrl]) - return - } switch rootView.primaryAction { case .requestUnlock: requestUnlockForLockedApps() @@ -385,10 +344,6 @@ final class LockDistractVC: BaseViewController { } private func lockSelectedApps() { - guard isAppLockVipUnlocked else { - AppRouter.push(Route.web, userInfo: ["url": URLManager.shared.homeUrl]) - return - } guard let member = selectedMember, !activeGroupKey.isEmpty else { DLToast.show(text: "请选择要锁定的成员") return @@ -414,7 +369,6 @@ final class LockDistractVC: BaseViewController { self?.rootView.lockBtn.isEnabled = true DLToast.show(text: "锁定成功") self?.loadLockableApps() - self?.refreshGroupVip() }, onError: { [weak self] error in self?.rootView.lockBtn.isEnabled = true DLToast.show(error, fallbackText: "锁定失败") diff --git a/QuickLocation/Section/LockDistract/LockDistractView.swift b/QuickLocation/Section/LockDistract/LockDistractView.swift index 92821aba..ce9a74bd 100644 --- a/QuickLocation/Section/LockDistract/LockDistractView.swift +++ b/QuickLocation/Section/LockDistract/LockDistractView.swift @@ -35,7 +35,6 @@ final class LockDistractView: UIView { private(set) var isLocked = false private(set) var isCurrentUser = false private(set) var primaryAction: LockDistractPrimaryAction = .lock - private(set) var isVipUnlocked = true private let copyMaxLength = 20 private var lockBtnHeightConstraint: NSLayoutConstraint? private var bottomStackToAppsConstraint: NSLayoutConstraint? @@ -111,11 +110,6 @@ final class LockDistractView: UIView { appCollectionView.reloadData() } - func updateVipAccess(isUnlocked: Bool) { - isVipUnlocked = isUnlocked - applyLockedState() - } - var selectedLockApps: [PhoneLockAppItem] { lockableApps.enumerated().compactMap { index, app in selectedAppIndexes.contains(index) ? app : nil @@ -173,13 +167,12 @@ final class LockDistractView: UIView { appCollectionView.reloadData() lockBtn.isHidden = lockedByOthers lockBtnHeightConstraint?.constant = lockedByOthers ? 0 : 56 - vipOfferImageView.isHidden = lockedByOthers || primaryAction != .lock || isVipUnlocked switch primaryAction { case .lock: tipLab.text = "锁定功能需要在对方开启权限情况下才能使用哟~" - lockBtn.setTitle(isVipUnlocked ? "锁定" : "开通会员 解锁功能", for: .normal) + lockBtn.setTitle("锁定", for: .normal) lockBtn.setBackgroundImage( - UIImage(named: isVipUnlocked ? "Common/button_bg_2" : "VipFeature/wide_button_bg"), + UIImage(named: "Common/button_bg_2"), for: .normal ) case .requestUnlock: @@ -208,7 +201,6 @@ final class LockDistractView: UIView { addSubview(footerBar) footerBar.addSubview(tipRow) footerBar.addSubview(lockBtn) - footerBar.addSubview(vipOfferImageView) contentView.addSubview(navBgView) contentView.addSubview(statsRow) @@ -244,14 +236,6 @@ final class LockDistractView: UIView { .bottomToTopOfView(lockBtn, offset: -8) .top(10) - vipOfferImageView.translatesAutoresizingMaskIntoConstraints = false - NSLayoutConstraint.activate([ - vipOfferImageView.trailingAnchor.constraint(equalTo: lockBtn.trailingAnchor, constant: -6), - vipOfferImageView.bottomAnchor.constraint(equalTo: lockBtn.topAnchor, constant: 10), - vipOfferImageView.widthAnchor.constraint(equalToConstant: 94), - vipOfferImageView.heightAnchor.constraint(equalToConstant: 32) - ]) - scrollView.layoutChain .top() .edgesHorzontal() @@ -727,13 +711,6 @@ final class LockDistractView: UIView { return btn }() - lazy var vipOfferImageView: UIImageView = { - let view = UIImageView(image: UIImage(named: "VipFeature/limited_offer")) - view.contentMode = .scaleAspectFit - view.isHidden = true - return view - }() - private func makeSectionTitle(_ text: String) -> UIView { let row = UIView() let star = UIImageView(image: UIImage(named: "LockDistract/section_star")) diff --git a/QuickLocation/Section/Mine/About/AboutVC.swift b/QuickLocation/Section/Mine/About/AboutVC.swift index f68a7a81..63fa18f9 100644 --- a/QuickLocation/Section/Mine/About/AboutVC.swift +++ b/QuickLocation/Section/Mine/About/AboutVC.swift @@ -63,6 +63,7 @@ final class AboutVC: BaseViewController { } @objc private func handleLogoTap() { +#if DEBUG || AdHoc logoTapResetWork?.cancel() logoTapCount += 1 if logoTapCount >= 5 { @@ -75,6 +76,7 @@ final class AboutVC: BaseViewController { } logoTapResetWork = work DispatchQueue.main.asyncAfter(deadline: .now() + 2, execute: work) +#endif } private func showServerSwitchAlert() { diff --git a/QuickLocation/Section/Mine/CancelAccount/CancelAccountView.swift b/QuickLocation/Section/Mine/CancelAccount/CancelAccountView.swift index 1db67d23..e380586c 100644 --- a/QuickLocation/Section/Mine/CancelAccount/CancelAccountView.swift +++ b/QuickLocation/Section/Mine/CancelAccount/CancelAccountView.swift @@ -73,10 +73,9 @@ final class CancelAccountView: UIView { .bottom(20) let specs: [(String, String)] = [ - ("1. 放弃当前的VIP权益", "当前充值的VIP我们不会退款,请解除你的自动续费(如果有),同意请打勾"), - ("2. 当前账号没有违规及其他的法律纠纷", "同意请打勾"), - ("3. 确认是账号本人进行注销操作,自愿承担后果", "同意请打勾"), - ("4. 账号注销后账号不可登录,不可恢复", "同意请打勾") + ("1. 当前账号没有违规及其他的法律纠纷", "同意请打勾"), + ("2. 确认是账号本人进行注销操作,自愿承担后果", "同意请打勾"), + ("3. 账号注销后账号不可登录,不可恢复", "同意请打勾") ] var previous: UIView? for spec in specs { @@ -96,7 +95,7 @@ final class CancelAccountView: UIView { agreementBtn.titleLabel?.font = .systemFont(ofSize: 13, weight: .medium) agreementBtn.contentHorizontalAlignment = .left let agreementItem = CancelCheckItemView( - title: "5. 账号注销协议", + title: "4. 账号注销协议", actionButton: agreementBtn ) checkItems.append(agreementItem) @@ -104,7 +103,7 @@ final class CancelAccountView: UIView { agreementItem.layoutChain.topToBottomOfView(previous!).edgesHorzontal(14) let tip6 = UILabel() - tip6.text = "6. 请在输入框中输入以下文字" + tip6.text = "5. 请在输入框中输入以下文字" tip6.font = .systemFont(ofSize: 16, weight: .medium) tip6.textColor = UIColor(hexStr: "#293445") card.addSubview(tip6) diff --git a/QuickLocation/Section/Mine/MineView.swift b/QuickLocation/Section/Mine/MineView.swift index fd055ec9..b58273a9 100644 --- a/QuickLocation/Section/Mine/MineView.swift +++ b/QuickLocation/Section/Mine/MineView.swift @@ -13,30 +13,13 @@ final class MineView: UIView { var disposeBag = DisposeBag() - private let vipCardHeight: CGFloat = 90 private let settingsRowHeight: CGFloat = 52 private let quickItemTitles = ["权限检测", "隐私设置", "状态设置", "账户设置"] var onQuickTap: ((String) -> Void)? func setupData(_ model: UserConfigModel) { - guard AppContextManager.shared.systemConfig?.isIntercept == false else { - maskBgView.isHidden = false - return - } - maskBgView.isHidden = true - guard model.vip > 1 else { - vipTitleLab.text = "开通会员" - vipContentLab.text = "会员尊享10+VIP特权" - vipActivateButton.isHidden = false - vipActivateButton.setTitle("立即开通", for: .normal) - return - } - vipTitleLab.text = model.vip_name - vipContentLab.text = model.vip == 3 ? "会员终身有效" - : "会员到期:\(self.getDateInterval2String(date: model.vip_expire_time, dateFormat: "yyyy.MM.dd"))" - vipActivateButton.setTitle("点击续费", for: .normal) - vipActivateButton.isHidden = model.vip == 3 + } // MARK: - Components @@ -72,55 +55,20 @@ final class MineView: UIView { MinePhotoWallView() }() - lazy var vipCardView: UIView = { + lazy var cardView: UIView = { let view = UIView() view.layer.cornerRadius = 16 view.clipsToBounds = true return view }() - lazy var vipCardBgImageView: UIImageView = { - let iv = UIImageView() - iv.image = UIImage(named: "Mine/vip_card") - iv.contentMode = .scaleToFill - return iv - }() - lazy var maskBgView: UIImageView = { let iv = UIImageView() iv.image = UIImage(named: "Mine/mask_bg") iv.contentMode = .scaleToFill - iv.isHidden = true return iv }() - lazy var vipTitleLab: UILabel = { - let label = UILabel() - label.font = FontManager.boboBold(18) - label.textColor = .white - label.text = " " - return label - }() - - lazy var vipContentLab: UILabel = { - let label = UILabel() - label.font = .systemFont(ofSize: 12, weight: .medium) - label.textColor = .white - label.text = " " - return label - }() - - lazy var vipActivateButton: UIButton = { - let btn = UIButton(type: .custom) - btn.backgroundColor = UIColor(hexStr: "#C0FF54") - btn.setTitle("立即开通", for: .normal) - btn.setTitleColor(UIColor(hexStr: "#00343B"), for: .normal) - btn.titleLabel?.font = FontManager.boboBold(14) - btn.cornerRadius = 9 - btn.isHidden = true - return btn - }() - private lazy var quickCardView: UIView = { let v = UIView() v.backgroundColor = .white @@ -190,12 +138,8 @@ final class MineView: UIView { addSubview(navBgView) addSubview(photoWall) - contentView.addSubview(vipCardView) - vipCardView.addSubview(vipCardBgImageView) - vipCardView.addSubview(vipActivateButton) - vipCardView.addSubview(vipTitleLab) - vipCardView.addSubview(vipContentLab) - vipCardView.addSubview(maskBgView) + contentView.addSubview(cardView) + cardView.addSubview(maskBgView) contentView.addSubview(quickCardView) quickCardView.addSubview(quickStack) @@ -230,29 +174,15 @@ final class MineView: UIView { .edges() .widthToView(scrollView) - vipCardView.layoutChain + cardView.layoutChain .top(12) .left(16).right(16) - .height(vipCardHeight) - - vipCardBgImageView.layoutChain.edges() - - vipTitleLab.layoutChain - .top(22) - .left(77) - - vipContentLab.layoutChain - .topToBottomOfView(vipTitleLab, offset: 6) - .leftToView(vipTitleLab) - - vipActivateButton.layoutChain - .right(19).centerY() - .width(70).height(28) + .height(90) maskBgView.layoutChain.edges() quickCardView.layoutChain - .topToBottomOfView(vipCardView, offset: 20) + .topToBottomOfView(cardView, offset: 20) .left(16).right(16) .height(90) diff --git a/QuickLocation/Section/Mine/MineViewController.swift b/QuickLocation/Section/Mine/MineViewController.swift index 69004a26..04a4e3f3 100644 --- a/QuickLocation/Section/Mine/MineViewController.swift +++ b/QuickLocation/Section/Mine/MineViewController.swift @@ -56,12 +56,6 @@ final class MineViewController: BaseViewController { } private func reactiveAction() { - rootView.vipActivateButton.rx.tap - .subscribe(onNext: { _ in - AppRouter.push(Route.web, userInfo: ["url": URLManager.shared.homeUrl]) - }) - .disposed(by: disposeBag) - rootView.photoWall.onTapMember = { [weak self] member in self?.openMemberInfo(selectedUserId: member.user_id) } diff --git a/QuickLocation/Section/PigeonMessage/PigeonMessageVC.swift b/QuickLocation/Section/PigeonMessage/PigeonMessageVC.swift index c3f7332e..1aad6b70 100644 --- a/QuickLocation/Section/PigeonMessage/PigeonMessageVC.swift +++ b/QuickLocation/Section/PigeonMessage/PigeonMessageVC.swift @@ -13,7 +13,6 @@ final class PigeonMessageVC: BaseViewController { private var rootView: PigeonMessageView! private var groupModel: GroupModel? private var activeGroupKey: String = "" - private var groupVip = GroupMemberVip() private var members: [GroupMemberModel] = [] private var selectedMembers: [GroupMemberModel] = [] private var selectedImage: UIImage? @@ -27,7 +26,6 @@ final class PigeonMessageVC: BaseViewController { private var playbackTimer: Timer? private var recordedDuration: TimeInterval = 0 private var isPressingRecord = false - private var hasAppeared = false override func loadView() { rootView = PigeonMessageView(frame: UIScreen.main.bounds) @@ -38,18 +36,9 @@ final class PigeonMessageVC: BaseViewController { super.viewDidLoad() bindActions() setupRecordingGesture() - applyGroupVip(groupVip) loadMembers() } - override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - if hasAppeared { - refreshGroupVip() - } - hasAppeared = true - } - override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) guard isMovingFromParent || navigationController?.isBeingDismissed == true else { return } @@ -120,7 +109,6 @@ final class PigeonMessageVC: BaseViewController { private func loadUsers(for groupKey: String, showLoading: Bool) { guard !groupKey.isEmpty else { DLToast.dismiss() - applyGroupVip(GroupMemberVip()) applyMembers([]) return } @@ -133,7 +121,6 @@ final class PigeonMessageVC: BaseViewController { return } guard let self, self.activeGroupKey == groupKey else { return } - self.applyGroupVip(response.vip) self.applyMembers(response.list) }, onError: { error in DLToast.dismiss() @@ -148,28 +135,6 @@ final class PigeonMessageVC: BaseViewController { rootView.configureMembers(members, selectedIds: []) } - private var isPigeonVipUnlocked: Bool { - groupVip.pigeon_mail == true - } - - private func applyGroupVip(_ vip: GroupMemberVip) { - groupVip = vip - rootView.updateVipAccess(isUnlocked: isPigeonVipUnlocked) - } - - private func refreshGroupVip() { - let groupKey = activeGroupKey - guard !groupKey.isEmpty else { return } - GroupService.groupUsers(groupKey: groupKey) - .subscribe(onNext: { [weak self] response in - guard let self, - self.activeGroupKey == groupKey, - response.isValid(for: groupKey) else { return } - self.applyGroupVip(response.vip) - }, onError: { _ in }) - .disposed(by: disposeBag) - } - private func updateCurrentGroupDisplay() { let groupName = groupModel?.groups.first { $0.group_key == activeGroupKey @@ -516,10 +481,6 @@ final class PigeonMessageVC: BaseViewController { } @objc private func sendMessage() { - guard isPigeonVipUnlocked else { - AppRouter.push(Route.web, userInfo: ["url": URLManager.shared.homeUrl]) - return - } if let wait = pigeonSendWaitSeconds() { DLToast.show(text: "发送过于频繁,请\(Self.formatWaitDuration(wait))后再试") return @@ -619,9 +580,7 @@ final class PigeonMessageVC: BaseViewController { self.cleanupAudio(deleteFile: true) self.rootView.clearVoiceDraft() self.recordPigeonSendSuccess() - DLToast.show(text: "发送成功") { - self.refreshGroupVip() - } + DLToast.show(text: "发送成功") }, onError: { error in DLToast.dismiss() DLToast.show(error) diff --git a/QuickLocation/Section/PigeonMessage/PigeonMessageView.swift b/QuickLocation/Section/PigeonMessage/PigeonMessageView.swift index f3e176ef..49949528 100644 --- a/QuickLocation/Section/PigeonMessage/PigeonMessageView.swift +++ b/QuickLocation/Section/PigeonMessage/PigeonMessageView.swift @@ -82,7 +82,6 @@ final class PigeonMessageView: UIView, UITextFieldDelegate { private let recordingHintLabel = UILabel() private let voiceTimeLabel = UILabel() private let waveformView = PigeonWaveformView() - private let vipOfferImageView = UIImageView(image: UIImage(named: "VipFeature/limited_offer")) private var selectedImageHeightConstraint: NSLayoutConstraint? private var isRecording = false @@ -253,15 +252,6 @@ final class PigeonMessageView: UIView, UITextFieldDelegate { updateMode() } - func updateVipAccess(isUnlocked: Bool) { - sendButton.setTitle(isUnlocked ? "发送" : "开通会员 解锁功能", for: .normal) - sendButton.setBackgroundImage( - UIImage(named: isUnlocked ? "Common/button_bg_2" : "VipFeature/wide_button_bg"), - for: .normal - ) - vipOfferImageView.isHidden = isUnlocked - } - private func setupUI() { let headerView = PigeonHeaderGradientView() addSubview(headerView) @@ -394,17 +384,6 @@ final class PigeonMessageView: UIView, UITextFieldDelegate { .topToBottomOfView(modeContainer, offset: 12) .edgesHorzontal(15) .bottom(16) - - vipOfferImageView.contentMode = .scaleAspectFit - vipOfferImageView.isHidden = true - addSubview(vipOfferImageView) - vipOfferImageView.translatesAutoresizingMaskIntoConstraints = false - NSLayoutConstraint.activate([ - vipOfferImageView.trailingAnchor.constraint(equalTo: sendButton.trailingAnchor, constant: -6), - vipOfferImageView.bottomAnchor.constraint(equalTo: sendButton.topAnchor, constant: 10), - vipOfferImageView.widthAnchor.constraint(equalToConstant: 94), - vipOfferImageView.heightAnchor.constraint(equalToConstant: 32) - ]) } private func setupRecipientCard(_ card: UIView) { diff --git a/QuickLocation/Section/PopupWindow/PopupQueueManager.swift b/QuickLocation/Section/PopupWindow/PopupQueueManager.swift deleted file mode 100644 index 33f83ac5..00000000 --- a/QuickLocation/Section/PopupWindow/PopupQueueManager.swift +++ /dev/null @@ -1,195 +0,0 @@ -// -// PopupQueueManager.swift -// QuickLocation -// -// Created by 八条 on 2026/7/3. -// - -import UIKit - -class PopupQueueManager { - - private weak var sourceVC: UIViewController? - private var currentStep = 0 - private var stepGeneration = 0 - private var countdownTimer: Timer? - private var isPaused = false - - init() { - NotificationCenter.default.addObserver(self, - selector: #selector(handlePause), - name: .pausePopupQueue, - object: nil) - NotificationCenter.default.addObserver(self, - selector: #selector(handleResume), - name: .resumePopupQueue, - object: nil) - NotificationCenter.default.addObserver(self, - selector: #selector(handleInvalidate), - name: .invalidatePopupQueue, - object: nil) - } - - deinit { - NotificationCenter.default.removeObserver(self) - } - - func start(from vc: UIViewController) { - sourceVC = vc - currentStep = 0 - executeNextStep() - } - - @objc private func handlePause() { - countdownTimer?.invalidate() - countdownTimer = nil - isPaused = true - } - - @objc private func handleResume() { - guard isPaused else { return } - isPaused = false - executeNextStep() - } - - @objc private func handleInvalidate() { - countdownTimer?.invalidate() - countdownTimer = nil - isPaused = true - currentStep = 3 - } - - private func executeNextStep() { - guard AppContextManager.shared.systemConfig?.isIntercept == false else { return } - switch currentStep { - case 0: - tryStartPromotionalActivities() - case 1: - tryStartSearchPopup() - case 2: - tryStartRegisterOrVipPopup() - default: - break - } - } - - // MARK: - Step 0: PromotionalActivities - - private func tryStartPromotionalActivities() { - guard let config = AppContextManager.shared.systemConfig else { - skipToNext() - return - } - guard config.popupConfig?.pay_pop == true, - AppContextManager.shared.vip == 1, - let timeConfig = config.timeConfig else { - skipToNext() - return - } - let gen = stepGeneration - startCountdown(seconds: timeConfig.pay_pop_time) { [weak self] in - guard let self = self, self.currentStep == 0, self.stepGeneration == gen else { return } - /// TODO - } - } - - // MARK: - Step 1: Search PopupWindow - - private func tryStartSearchPopup() { - guard let config = AppContextManager.shared.systemConfig else { - skipToNext() - return - } - guard config.popupConfig?.search_phone == true, - let timeConfig = config.timeConfig else { - skipToNext() - return - } - let gen = stepGeneration - startCountdown(seconds: timeConfig.search_phone) { - guard self.currentStep == 1, self.stepGeneration == gen else { return } - PopupWindow.show(popupType: .search) { - self.skipToNext() - } - } - } - - // MARK: - Step 2: Register or VIP PopupWindow (mutually exclusive) - - private func tryStartRegisterOrVipPopup() { - guard let config = AppContextManager.shared.systemConfig, - let timeConfig = config.timeConfig else { - return - } - - if AppContextManager.shared.isGuest { - let gen = stepGeneration - startCountdown(seconds: timeConfig.signup_tip) { - guard self.currentStep == 2, self.stepGeneration == gen else { return } - PopupWindow.show(popupType: .register) { - // done - } - } - } else if AppContextManager.shared.vip == 1 { - let gen = stepGeneration - startCountdown(seconds: timeConfig.buy_vip_tip) { - guard self.currentStep == 2, self.stepGeneration == gen else { return } - PopupWindow.show(popupType: .vip) { - // done - } - } - } - } - - // MARK: - Helpers - - private func skipToNext() { - stepGeneration += 1 - currentStep += 1 - executeNextStep() - } - - private func startCountdown(seconds: Int, onExpired: @escaping () -> Void) { - guard seconds > 0 else { - onExpired() - return - } - countdownTimer?.invalidate() - var remaining = seconds - countdownTimer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { [weak self] timer in - remaining -= 1 - if remaining <= 0 { - timer.invalidate() - self?.countdownTimer = nil - onExpired() - } - } - } - - private func push(_ vc: UIViewController) { - let topVC = topViewController() - guard let nav = topVC?.navigationController else { return } - if nav.viewControllers.contains(where: { type(of: $0) == type(of: vc) }) { - return - } - nav.pushViewController(vc, animated: true) - } - - private func topViewController() -> UIViewController? { - guard let rootVC = kKeyWindow?.rootViewController else { return nil } - return topViewController(from: rootVC) - } - - private func topViewController(from root: UIViewController) -> UIViewController { - if let presented = root.presentedViewController { - return topViewController(from: presented) - } - if let nav = root as? UINavigationController, let visible = nav.visibleViewController { - return topViewController(from: visible) - } - if let tab = root as? UITabBarController, let selected = tab.selectedViewController { - return topViewController(from: selected) - } - return root - } -} diff --git a/QuickLocation/Section/PopupWindow/PopupWindow.swift b/QuickLocation/Section/PopupWindow/PopupWindow.swift deleted file mode 100644 index 2b3d65e0..00000000 --- a/QuickLocation/Section/PopupWindow/PopupWindow.swift +++ /dev/null @@ -1,1406 +0,0 @@ -// -// PopupWindow.swift -// QuickLocation -// -// Created by 八条 on 2026/7/2. -// - -import UIKit -import RxSwift -import RxCocoa -import Lottie - -enum PopupType { - /// 搜索位置 - case search - /// 注册 - case register - /// 会员 - case vip -} - -class PopupWindow: UIView { - - private static let shared = PopupWindow(frame: CGRect(origin: .zero, size: kScreenSize)) - - var disposeBag = DisposeBag() - - private var popupType: PopupType? { - didSet { - switch popupType { - case .search: - searchPopupView.isHidden = false - earthLottieView.play() - case .register: - if Bool.random() { - registerPopupView.isHidden = true - register2PopupView.isHidden = false - slideInRegister2Popup() - } else { - register2PopupView.isHidden = true - registerPopupView.isHidden = false - slideInRegisterPopup() - } - case .vip: - let roll = Int.random(in: 0...3) - switch roll { - case 0: - unlockVip2View.isHidden = true - unlockVip3View.isHidden = true - unlockVip4View.isHidden = true - unlockVip1View.isHidden = false - slideInUnlockVip1Popup() - case 1: - unlockVip1View.isHidden = true - unlockVip3View.isHidden = true - unlockVip4View.isHidden = true - unlockVip2View.isHidden = false - slideInUnlockVip2Popup() - case 2: - unlockVip1View.isHidden = true - unlockVip2View.isHidden = true - unlockVip4View.isHidden = true - unlockVip3View.isHidden = false - slideInUnlockVip3Popup() - default: - unlockVip1View.isHidden = true - unlockVip2View.isHidden = true - unlockVip3View.isHidden = true - unlockVip4View.isHidden = false - slideInUnlockVip4Popup() - } - default: - break - } - } - } - - private static var dismissCompletion: (() -> Void)? - - static func show(popupType: PopupType, dismissCompletion: (() -> Void)? = nil) { - Self.dismissCompletion = dismissCompletion - guard let superView = kKeyWindow else { - return - } - - if PopupWindow.shared.superview != nil { - PopupWindow.shared.removeFromSuperview() - PopupWindow.shared.bgView.frame = .zero - } - - PopupWindow.shared.resetPopupState() - - PopupWindow.shared.popupType = popupType - PopupWindow.shared.bgView.alpha = 1 - PopupWindow.shared.bgView.frame = CGRect(x: 0, y: 0, width: kScreenWidth, height: kScreenHeight) - superView.addSubview(PopupWindow.shared) - superView.bringSubviewToFront(PopupWindow.shared) - - UIView.animate(withDuration: 0.25) { - PopupWindow.shared.bgView.alpha = 1 - } - } - - private func resetPopupState() { - stopRegisterStarFlash() - stopRegister1LottieAlternate() - stopUnlockVip1Animations() - stopUnlockVip2Animations() - stopUnlockVip3Animations() - stopUnlockVip4Animations() - registerPopupView.transform = .identity - register2PopupView.transform = .identity - unlockVip1View.transform = .identity - unlockVip2View.transform = .identity - unlockVip3View.transform = .identity - unlockVip4View.transform = .identity - registerStar1.transform = .identity -// register2Star1.transform = .identity - - searchPopupView.isHidden = true - registerPopupView.isHidden = true - register2PopupView.isHidden = true - unlockVip1View.isHidden = true - unlockVip2View.isHidden = true - unlockVip3View.isHidden = true - unlockVip4View.isHidden = true - bgView.isUserInteractionEnabled = true - } - - /// 关闭 - static func dismiss() { - guard PopupWindow.shared.superview != nil else { return } - - UIView.animate(withDuration: 0.25, delay: 0, options: [.curveEaseIn]) { - PopupWindow.shared.bgView.alpha = 0 - } completion: { _ in - PopupWindow.shared.resetPopupState() - PopupWindow.shared.removeFromSuperview() - let completion = Self.dismissCompletion - Self.dismissCompletion = nil - completion?() - } - } - - private func setupRx() { - registerCloseBtn.rx.tap - .subscribe(onNext: { [weak self] _ in - self?.activePopupView == 2 ? self?.slideOutRegister2Popup() : self?.slideOutRegisterPopup() - }) - .disposed(by: disposeBag) - - registerBtn.rx.tap - .subscribe(onNext: { [weak self] _ in - NotificationCenter.default.post(name: .pausePopupQueue, object: nil) - self?.activePopupView == 2 ? self?.slideOutRegister2Popup() : self?.slideOutRegisterPopup() - let topVC = UIViewController.currentViewController() - if !(topVC is LoginViewController) { - AppRouter.push(Route.login) - } - }) - .disposed(by: disposeBag) - - register2CloseBtn.rx.tap - .subscribe(onNext: { [weak self] _ in - self?.slideOutRegister2Popup() - }) - .disposed(by: disposeBag) - - register2Btn.rx.tap - .subscribe(onNext: { [weak self] _ in - NotificationCenter.default.post(name: .pausePopupQueue, object: nil) - self?.slideOutRegister2Popup() - let topVC = UIViewController.currentViewController() - if !(topVC is LoginViewController) { - AppRouter.push(Route.login) - } - }) - .disposed(by: disposeBag) - - vip1CloseBtn.rx.tap - .subscribe(onNext: { [weak self] _ in - self?.slideOutUnlockVip1Popup() - }) - .disposed(by: disposeBag) - - vip1UnlockBtn.rx.tap - .subscribe(onNext: { [weak self] _ in - self?.slideOutUnlockVip1Popup() - AppRouter.push(Route.web, userInfo: ["url": URLManager.shared.homeUrl]) - }) - .disposed(by: disposeBag) - - unlockVip2CloseBtn.rx.tap - .subscribe(onNext: { [weak self] _ in - self?.slideOutUnlockVip2Popup() - }) - .disposed(by: disposeBag) - - unlockVip2Btn.rx.tap - .subscribe(onNext: { [weak self] _ in - self?.slideOutUnlockVip2Popup() - AppRouter.push(Route.web, userInfo: ["url": URLManager.shared.homeUrl]) - }) - .disposed(by: disposeBag) - - unlockVip3CloseBtn.rx.tap - .subscribe(onNext: { [weak self] _ in - self?.slideOutUnlockVip3Popup() - }) - .disposed(by: disposeBag) - - unlockVip3Btn.rx.tap - .subscribe(onNext: { [weak self] _ in - self?.slideOutUnlockVip3Popup() - AppRouter.push(Route.web, userInfo: ["url": URLManager.shared.homeUrl]) - }) - .disposed(by: disposeBag) - - unlockVip4CloseBtn.rx.tap - .subscribe(onNext: { [weak self] _ in - self?.slideOutUnlockVip4Popup() - }) - .disposed(by: disposeBag) - - unlockVip4Btn.rx.tap - .subscribe(onNext: { [weak self] _ in - self?.slideOutUnlockVip4Popup() - AppRouter.push(Route.web, userInfo: ["url": URLManager.shared.homeUrl]) - }) - .disposed(by: disposeBag) - } - - private lazy var bgView: UIView = { - let view = UIView() - view.backgroundColor = .black.withAlphaComponent(0.5) - return view - }() - - // MARK: - 实时查位置 - lazy var searchPopupView: UIView = { - let view = UIView() - view.backgroundColor = .clear - view.isHidden = true - - let bgImgView = UIImageView(image: UIImage(named: "PopupWindow/search_bg")) - bgImgView.contentMode = .scaleAspectFill - bgImgView.rx.tapGesture.subscribe(onNext: { _ in - PopupWindow.dismiss() - AppRouter.push(Route.searchLocation) - }).disposed(by: disposeBag) - view.addSubview(bgImgView) - bgImgView.layoutChain - .edges(excludingEdge: .bottom) - .heightToWidth(828/770) - - let btn = UIButton(type: .custom) - btn.backgroundColor = .clear - btn.setBackgroundImage(UIImage(named: "Group/close"), for: .normal) - btn.extendEdgeInsets = UIEdgeInsets(top: 10, left: 100, bottom: 100, right: 100) - btn.rx.tap.subscribe(onNext: { _ in - PopupWindow.dismiss() - }).disposed(by: disposeBag) - view.addSubview(btn) - btn.layoutChain - .topToBottomOfView(bgImgView, offset: 0) - .centerX() - .width(22) - .height(22) - .bottom() - -// let peopleIcon = UIImageView(image: UIImage(named: "PopupWindow/search_people")) -// peopleIcon.contentMode = .scaleAspectFill -// view.addSubview(peopleIcon) -// peopleIcon.layoutChain -// .top(20) -// .width(73) -// .height(95) -// .rightToCenterXOfView(view) - -// let eartIcon = UIImageView(image: UIImage(named: "PopupWindow/search_earth")) -// eartIcon.contentMode = .scaleAspectFill -// view.addSubview(eartIcon) -// eartIcon.layoutChain -// .topToView(peopleIcon, offset: 12) -// .width(88) -// .height(81) -// .leftToCenterXOfView(view) - - view.addSubview(earthLottieView) - earthLottieView.layoutChain - .top() - .edgesHorzontal(50) - .heightToWidth(95/155) - - return view - }() - - lazy var earthLottieView: LottieAnimationView = { - let view = LottieAnimationView(name: "dialog_phone_search") - view.loopMode = .loop - return view - }() - - // MARK: - 解锁会员 1 - lazy var unlockVip1View: UIView = { - let view = UIView() - view.backgroundColor = .clear - view.isHidden = true - - let bgImg = UIImageView(image: UIImage(named: "PopupWindow/vip_bg")) - bgImg.contentMode = .scaleAspectFill - view.addSubview(bgImg) - bgImg.layoutChain - .top(45) - .edgesHorzontal() - .bottom() - - view.addSubview(vip1HeartIcon) - vip1HeartIcon.layoutChain - .top() - .left(21) - .width(116) - .height(99) - - let logoImg = UIImageView(image: UIImage(named: "PopupWindow/vip1_logo")) - logoImg.contentMode = .scaleAspectFill - view.addSubview(logoImg) - logoImg.layoutChain - .topToView(bgImg, offset: 40) - .centerX() - .width(125) - .height(42) - - view.addSubview(vip1Tips2Img) - vip1Tips2Img.layoutChain - .topToBottomOfView(logoImg, offset: 30) - .centerX() - .width(71) - .height(26) - - view.addSubview(vip1Tips1Img) - vip1Tips1Img.layoutChain - .rightToLeftOfView(vip1Tips2Img, offset: -24) - .centerY(vip1Tips2Img) - .width(71) - .height(26) - - view.addSubview(vip1Tips3Img) - vip1Tips3Img.layoutChain - .leftToRightOfView(vip1Tips2Img, offset: 24) - .centerY(vip1Tips2Img) - .width(71) - .height(26) - - let textLab = UILabel() - textLab.text = "看看TA真实走过哪里" - textLab.font = .systemFont(ofSize: 14, weight: .medium) - textLab.textColor = UIColor(hexStr: "#16B3FF") - view.addSubview(textLab) - textLab.layoutChain - .topToBottomOfView(vip1Tips2Img, offset: 20) - .centerX() - - view.addSubview(vip1CloseBtn) - vip1CloseBtn.layoutChain - .topToView(bgImg, offset: 16) - .right(17) - - view.addSubview(vip1UnlockBtn) - vip1UnlockBtn.layoutChain - .width(224) - .height(50) - .centerX() - .bottom(kSafeBottomMargin + 15) - - return view - }() - - lazy var vip1HeartIcon: UIImageView = { - let view = UIImageView() - view.image = UIImage(named: "PopupWindow/vip1_heart") - view.contentMode = .scaleAspectFill - return view - }() - - lazy var vip1Tips1Img: UIImageView = { - let view = UIImageView() - view.image = UIImage(named: "PopupWindow/vip1_tips_1") - view.contentMode = .scaleAspectFill - return view - }() - - lazy var vip1Tips2Img: UIImageView = { - let view = UIImageView() - view.image = UIImage(named: "PopupWindow/vip1_tips_2") - view.contentMode = .scaleAspectFill - return view - }() - - lazy var vip1Tips3Img: UIImageView = { - let view = UIImageView() - view.image = UIImage(named: "PopupWindow/vip1_tips_3") - view.contentMode = .scaleAspectFill - return view - }() - - lazy var vip1CloseBtn: UIButton = { - let btn = UIButton(type: .custom) - btn.setImage(UIImage(named: "PopupWindow/close"), for: .normal) - btn.extendEdgeInsets = UIEdgeInsets(top: 30, left: 30, bottom: 30, right: 17) - return btn - }() - - lazy var vip1UnlockBtn: UIButton = { - let btn = UIButton(type: .custom) - btn.setTitle("立即解锁", for: .normal) - btn.setTitleColor(.white, for: .normal) - btn.titleLabel?.font = .systemFont(ofSize: 16, weight: .medium) - btn.setBackgroundImage(UIImage(named: "Common/button_bg_2"), for: .normal) - btn.cornerRadius = 25 - return btn - }() - - private func startUnlockVip1Animations() { - stopUnlockVip1Animations() - - let heartAnimation = CABasicAnimation(keyPath: "transform.scale") - heartAnimation.fromValue = 1.0 - heartAnimation.toValue = 1.2 - heartAnimation.duration = 0.55 - heartAnimation.autoreverses = true - heartAnimation.repeatCount = .infinity - heartAnimation.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut) - vip1HeartIcon.layer.add(heartAnimation, forKey: "vip1HeartBeat") - - addVip1TipSwingAnimation(to: vip1Tips1Img, from: -0.12, to: 0.12, duration: 0.55) - addVip1TipSwingAnimation(to: vip1Tips2Img, from: -0.12, to: 0.12, duration: 0.55) - addVip1TipSwingAnimation(to: vip1Tips3Img, from: -0.12, to: 0.12, duration: 0.55) - } - - private func addVip1TipSwingAnimation(to imageView: UIImageView, from: CGFloat, to: CGFloat, duration: CFTimeInterval) { - let animation = CABasicAnimation(keyPath: "transform.rotation.z") - animation.fromValue = from - animation.toValue = to - animation.duration = duration - animation.autoreverses = true - animation.repeatCount = .infinity - animation.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut) - imageView.layer.add(animation, forKey: "vip1TipSwing") - } - - private func stopUnlockVip1Animations() { - vip1HeartIcon.layer.removeAnimation(forKey: "vip1HeartBeat") - vip1Tips1Img.layer.removeAnimation(forKey: "vip1TipSwing") - vip1Tips2Img.layer.removeAnimation(forKey: "vip1TipSwing") - vip1Tips3Img.layer.removeAnimation(forKey: "vip1TipSwing") - } - - private let unlockVip1PopupHeight: CGFloat = 339 - - private func slideInUnlockVip1Popup() { - stopUnlockVip1Animations() - bgView.isUserInteractionEnabled = false - unlockVip1View.isHidden = false - unlockVip1View.layoutIfNeeded() - unlockVip1View.transform = CGAffineTransform(translationX: 0, y: unlockVip1PopupHeight) - UIView.animate(withDuration: 0.45, delay: 0, - usingSpringWithDamping: 0.8, - initialSpringVelocity: 0.5, - options: .curveEaseOut) { - self.unlockVip1View.transform = .identity - } completion: { _ in - self.bgView.isUserInteractionEnabled = true - self.startUnlockVip1Animations() - } - } - - private func slideOutUnlockVip1Popup() { - stopUnlockVip1Animations() - bgView.isUserInteractionEnabled = false - UIView.animate(withDuration: 0.3, delay: 0, options: .curveEaseIn) { - self.unlockVip1View.transform = CGAffineTransform(translationX: 0, y: self.unlockVip1PopupHeight) - } completion: { _ in - Self.dismiss() - } - } - - // MARK: - 解锁会员 2 - private let unlockVip2PopupHeight: CGFloat = 412 - - lazy var unlockVip2View: UIView = { - let view = UIView() - view.backgroundColor = .clear - view.isHidden = true - - let bgImg = UIImageView(image: UIImage(named: "PopupWindow/vip2_bg")) - bgImg.contentMode = .scaleAspectFill - view.addSubview(bgImg) - bgImg.layoutChain - .top(84) - .edgesHorzontal() - .bottom() - - let titleLab = UILabel() - let text = "会员升级人次" - let attr = NSMutableAttributedString(string: text) - let strokeAttrs: [NSAttributedString.Key: Any] = [ - .strokeWidth: -5, - .strokeColor: UIColor.black.cgColor, - .foregroundColor: UIColor.white, - .font: FontManager.ziHunBianHei(20) - ] - attr.setAttributes(strokeAttrs, range: NSRange(location: 0, length: text.count)) - titleLab.attributedText = attr - - view.addSubview(titleLab) - titleLab.layoutChain - .top(106) - .left(29) - - let countTitleLab = UILabel() - let countText = "已突破" - let countAttr = NSMutableAttributedString(string: countText) - let countStrokeAttrs: [NSAttributedString.Key: Any] = [ - .strokeWidth: -5, - .strokeColor: UIColor.black.cgColor, - .foregroundColor: UIColor.white, - .font: FontManager.ziHunBianHei(22) - ] - countAttr.setAttributes(countStrokeAttrs, range: NSRange(location: 0, length: countText.count)) - countTitleLab.attributedText = countAttr - view.addSubview(countTitleLab) - countTitleLab.layoutChain - .topToBottomOfView(titleLab, offset: 22) - .leftToView(titleLab) - - view.addSubview(unlockVip2CountLab) - unlockVip2CountLab.layoutChain - .leftToRightOfView(countTitleLab) - .bottomToView(countTitleLab, offset: 3) - - view.addSubview(unlockVip2LogoImg) - unlockVip2LogoImg.layoutChain - .top() - .right() - .width(178) - .height(199) - - let textImg = UIImageView(image: UIImage(named: "PopupWindow/vip2_text")) - view.addSubview(textImg) - textImg.layoutChain - .topToBottomOfView(unlockVip2LogoImg, offset: 15) - .centerX() - .width(275) - .height(41) - - view.addSubview(unlockVip2CloseBtn) - unlockVip2CloseBtn.layoutChain - .bottom(kSafeBottomMargin + 15) - .left(30) - .height(50) - - view.addSubview(unlockVip2Btn) - unlockVip2Btn.layoutChain - .bottomToView(unlockVip2CloseBtn) - .right(30) - .height(50) - .widthToView(unlockVip2CloseBtn) - - unlockVip2CloseBtn.layoutChain.rightToLeftOfView(unlockVip2Btn, offset: -10) - - return view - }() - - lazy var unlockVip2LogoImg: UIImageView = { - let view = UIImageView() - view.image = UIImage(named: "PopupWindow/vip2_logo") - view.contentMode = .scaleAspectFill - return view - }() - - private var unlockVip2CountTarget: Int = 0 - private var unlockVip2CountTimer: Timer? - - lazy var unlockVip2CountLab: UILabel = { - let label = UILabel() - unlockVip2CountTarget = Int.random(in: 10000...15000) - let text = "0+" - let attr = NSMutableAttributedString(string: text) - let strokeAttrs: [NSAttributedString.Key: Any] = [ - .strokeWidth: -5, - .strokeColor: UIColor.black.cgColor, - .foregroundColor: UIColor(hexStr: "#7CE7FC"), - .font: FontManager.ziHunBianHei(34) - ] - attr.setAttributes(strokeAttrs, range: NSRange(location: 0, length: text.count)) - label.attributedText = attr - return label - }() - - lazy var unlockVip2CloseBtn: UIButton = { - let btn = UIButton(type: .custom) - btn.setTitle("稍后再说", for: .normal) - btn.setTitleColor(UIColor(hexStr: "#16B3FF"), for: .normal) - btn.titleLabel?.font = .systemFont(ofSize: 16, weight: .medium) - btn.backgroundColor = .white - btn.cornerRadius = 25 - btn.borderWidth = 0.5 - btn.borderColor = UIColor(hexStr: "#16B3FF") - return btn - }() - - lazy var unlockVip2Btn: UIButton = { - let btn = UIButton(type: .custom) - btn.setTitle("立即升级", for: .normal) - btn.setTitleColor(.white, for: .normal) - btn.titleLabel?.font = .systemFont(ofSize: 16, weight: .medium) - btn.setBackgroundImage(UIImage(named: "Common/button_bg_2"), for: .normal) - btn.cornerRadius = 25 - return btn - }() - - private func startUnlockVip2Animations() { - stopUnlockVip2Animations() - let animation = CABasicAnimation(keyPath: "transform.rotation.z") - animation.fromValue = -0.08 - animation.toValue = 0.08 - animation.duration = 0.7 - animation.autoreverses = true - animation.repeatCount = .infinity - animation.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut) - unlockVip2LogoImg.layer.add(animation, forKey: "unlockVip2LogoSwing") - startUnlockVip2CountAnimation() - } - - private func stopUnlockVip2Animations() { - unlockVip2LogoImg.layer.removeAnimation(forKey: "unlockVip2LogoSwing") - unlockVip2CountTimer?.invalidate() - unlockVip2CountTimer = nil - } - - private func startUnlockVip2CountAnimation() { - unlockVip2CountTimer?.invalidate() - let target = unlockVip2CountTarget - let duration: TimeInterval = 2.0 - let interval: TimeInterval = 0.025 - let totalSteps = Int(duration / interval) - var step = 0 - unlockVip2CountTimer = Timer.scheduledTimer(withTimeInterval: interval, repeats: true) { [weak self] timer in - step += 1 - let progress = min(Double(step) / Double(totalSteps), 1.0) - let eased = 1.0 - pow(1.0 - progress, 3) - let current = Int(Double(target) * eased) - let text = "\(current)+" - let attr = NSMutableAttributedString(string: text) - let strokeAttrs: [NSAttributedString.Key: Any] = [ - .strokeWidth: -3, - .strokeColor: UIColor.black.cgColor, - .foregroundColor: UIColor(hexStr: "#7CE7FC"), - .font: FontManager.ziHunBianHei(34) - ] - attr.setAttributes(strokeAttrs, range: NSRange(location: 0, length: text.count)) - self?.unlockVip2CountLab.attributedText = attr - if progress >= 1.0 { - timer.invalidate() - self?.unlockVip2CountTimer = nil - } - } - } - - private func slideInUnlockVip2Popup() { - stopUnlockVip2Animations() - unlockVip2CountTarget = Int.random(in: 10000...15000) - let attr = NSMutableAttributedString(string: "0+") - let strokeAttrs: [NSAttributedString.Key: Any] = [ - .strokeWidth: -3, - .strokeColor: UIColor.black.cgColor, - .foregroundColor: UIColor(hexStr: "#7CE7FC"), - .font: FontManager.ziHunBianHei(34) - ] - attr.setAttributes(strokeAttrs, range: NSRange(location: 0, length: 2)) - unlockVip2CountLab.attributedText = attr - bgView.isUserInteractionEnabled = false - unlockVip2View.isHidden = false - unlockVip2View.layoutIfNeeded() - unlockVip2View.transform = CGAffineTransform(translationX: 0, y: unlockVip2PopupHeight) - UIView.animate(withDuration: 0.45, delay: 0, - usingSpringWithDamping: 0.8, - initialSpringVelocity: 0.5, - options: .curveEaseOut) { - self.unlockVip2View.transform = .identity - } completion: { _ in - self.bgView.isUserInteractionEnabled = true - self.startUnlockVip2Animations() - } - } - - private func slideOutUnlockVip2Popup() { - stopUnlockVip2Animations() - bgView.isUserInteractionEnabled = false - UIView.animate(withDuration: 0.3, delay: 0, options: .curveEaseIn) { - self.unlockVip2View.transform = CGAffineTransform(translationX: 0, y: self.unlockVip2PopupHeight) - } completion: { _ in - Self.dismiss() - } - } - - // MARK: - 解锁会员 3 - private let unlockVip3PopupHeight: CGFloat = 385 - - lazy var unlockVip3View: UIView = { - let view = UIView() - view.backgroundColor = .clear - view.isHidden = true - - let bgImg = UIImageView(image: UIImage(named: "PopupWindow/vip3_bg")) - bgImg.contentMode = .scaleAspectFill - view.addSubview(bgImg) - bgImg.layoutChain - .top(45) - .edgesHorzontal() - .bottom() - - view.addSubview(unlockVip3LottieView) - unlockVip3LottieView.layoutChain - .top(-120) - .right(-110) - .width(420) - .height(370) - - view.addSubview(unlockVip3CloseBtn) - unlockVip3CloseBtn.layoutChain - .bottom(kSafeBottomMargin + 15) - .left(30) - .height(50) - - view.addSubview(unlockVip3Btn) - unlockVip3Btn.layoutChain - .bottomToView(unlockVip3CloseBtn) - .right(30) - .height(50) - .widthToView(unlockVip3CloseBtn) - - unlockVip3CloseBtn.layoutChain.rightToLeftOfView(unlockVip3Btn, offset: -10) - - return view - }() - - lazy var unlockVip3LottieView: LottieAnimationView = { - let view = LottieAnimationView(name: "dialog_buy_vip_3") - view.loopMode = .loop - return view - }() - - lazy var unlockVip3CloseBtn: UIButton = { - let btn = UIButton(type: .custom) - btn.setTitle("稍后再说", for: .normal) - btn.setTitleColor(UIColor(hexStr: "#16B3FF"), for: .normal) - btn.titleLabel?.font = .systemFont(ofSize: 16, weight: .medium) - btn.backgroundColor = .white - btn.cornerRadius = 25 - btn.borderWidth = 0.5 - btn.borderColor = UIColor(hexStr: "#16B3FF") - return btn - }() - - lazy var unlockVip3Btn: UIButton = { - let btn = UIButton(type: .custom) - btn.setTitle("立即升级", for: .normal) - btn.setTitleColor(.white, for: .normal) - btn.titleLabel?.font = .systemFont(ofSize: 16, weight: .medium) - btn.setBackgroundImage(UIImage(named: "Common/button_bg_2"), for: .normal) - btn.cornerRadius = 25 - return btn - }() - - private func stopUnlockVip3Animations() { - unlockVip3LottieView.stop() - } - - private func slideInUnlockVip3Popup() { - stopUnlockVip3Animations() - bgView.isUserInteractionEnabled = false - unlockVip3View.isHidden = false - unlockVip3View.layoutIfNeeded() - unlockVip3View.transform = CGAffineTransform(translationX: 0, y: unlockVip3PopupHeight) - UIView.animate(withDuration: 0.45, delay: 0, - usingSpringWithDamping: 0.8, - initialSpringVelocity: 0.5, - options: .curveEaseOut) { - self.unlockVip3View.transform = .identity - } completion: { _ in - self.bgView.isUserInteractionEnabled = true - self.unlockVip3LottieView.play() - } - } - - private func slideOutUnlockVip3Popup() { - stopUnlockVip3Animations() - bgView.isUserInteractionEnabled = false - UIView.animate(withDuration: 0.3, delay: 0, options: .curveEaseIn) { - self.unlockVip3View.transform = CGAffineTransform(translationX: 0, y: self.unlockVip3PopupHeight) - } completion: { _ in - Self.dismiss() - } - } - - // MARK: - 解锁会员 4 - private let unlockVip4PopupHeight: CGFloat = 368 - - lazy var unlockVip4View: UIView = { - let view = UIView() - view.backgroundColor = .clear - view.isHidden = true - - let bgImg = UIImageView(image: UIImage(named: "PopupWindow/vip4_bg")) - bgImg.contentMode = .scaleAspectFill - view.addSubview(bgImg) - bgImg.layoutChain - .top() - .edgesHorzontal() - .bottom() - - view.addSubview(unlockVip4AnimateView) - unlockVip4AnimateView.layoutChain - .top(143) - .rightToCenterXOfView(view, offset: 50) - .width(60) - .height(52) - - let label = UILabel() - label.text = "终身会员" - label.font = .systemFont(ofSize: 14, weight: .medium) - view.addSubview(label) - label.layoutChain - .leftToRightOfView(unlockVip4AnimateView, offset: 17) - .bottomToView(unlockVip4AnimateView) - - view.addSubview(unlockVip4DiscountLab) - unlockVip4DiscountLab.layoutChain - .bottomToView(label, offset: 10) - .leftToRightOfView(label) - - let unitLab = UILabel() - unitLab.text = "折" - unitLab.font = .systemFont(ofSize: 14, weight: .medium) - view.addSubview(unitLab) - unitLab.layoutChain - .bottomToView(label, offset: 0) - .leftToRightOfView(unlockVip4DiscountLab) - - view.addSubview(unlockVip4CloseBtn) - unlockVip4CloseBtn.layoutChain - .top() - .right(18) - .width(22) - .height(22) - - view.addSubview(unlockVip4Btn) - unlockVip4Btn.layoutChain - .centerX() - .width(224) - .height(50) - .bottom(49) - - return view - }() - - lazy var unlockVip4AnimateView: UIImageView = { - let view = UIImageView() - view.image = UIImage(named: "PopupWindow/vip4_animate") - return view - }() - - lazy var unlockVip4DiscountLab: UILabel = { - let label = UILabel() - label.font = .systemFont(ofSize: 44, weight: .bold) - label.textColor = UIColor(hexStr: "#FF4E41") - return label - }() - - lazy var unlockVip4CloseBtn: UIButton = { - let btn = UIButton(type: .custom) - btn.setImage(UIImage(named: "PopupWindow/close"), for: .normal) - btn.extendEdgeInsets = UIEdgeInsets(top: 30, left: 30, bottom: 30, right: 18) - return btn - }() - - lazy var unlockVip4Btn: UIButton = { - let btn = UIButton(type: .custom) - btn.setTitle("立即升级", for: .normal) - btn.setTitleColor(.white, for: .normal) - btn.titleLabel?.font = .systemFont(ofSize: 16, weight: .medium) - btn.setBackgroundImage(UIImage(named: "Common/button_bg_2"), for: .normal) - btn.cornerRadius = 25 - return btn - }() - - private func startUnlockVip4Animations() { - stopUnlockVip4Animations() - - let animateScale = CABasicAnimation(keyPath: "transform.scale") - animateScale.fromValue = 1.0 - animateScale.toValue = 1.15 - animateScale.duration = 0.6 - animateScale.autoreverses = true - animateScale.repeatCount = .infinity - animateScale.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut) - unlockVip4AnimateView.layer.add(animateScale, forKey: "unlockVip4AnimateScale") - - let btnScale = CABasicAnimation(keyPath: "transform.scale") - btnScale.fromValue = 1.0 - btnScale.toValue = 1.08 - btnScale.duration = 0.8 - btnScale.autoreverses = true - btnScale.repeatCount = .infinity - btnScale.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut) - unlockVip4Btn.layer.add(btnScale, forKey: "unlockVip4BtnScale") - } - - private func stopUnlockVip4Animations() { - unlockVip4AnimateView.layer.removeAnimation(forKey: "unlockVip4AnimateScale") - unlockVip4Btn.layer.removeAnimation(forKey: "unlockVip4BtnScale") - } - - private func slideInUnlockVip4Popup() { - if let systemConfig = AppContextManager.shared.systemConfig, - let timeConfig = systemConfig.timeConfig { - unlockVip4DiscountLab.text = (String(format: "%.1f", timeConfig.min_discount/10)) - } - stopUnlockVip4Animations() - bgView.isUserInteractionEnabled = false - unlockVip4View.isHidden = false - unlockVip4View.layoutIfNeeded() - unlockVip4View.transform = CGAffineTransform(translationX: 0, y: unlockVip4PopupHeight) - UIView.animate(withDuration: 0.45, delay: 0, - usingSpringWithDamping: 0.8, - initialSpringVelocity: 0.5, - options: .curveEaseOut) { - self.unlockVip4View.transform = .identity - } completion: { _ in - self.bgView.isUserInteractionEnabled = true - self.startUnlockVip4Animations() - } - } - - private func slideOutUnlockVip4Popup() { - stopUnlockVip4Animations() - bgView.isUserInteractionEnabled = false - UIView.animate(withDuration: 0.3, delay: 0, options: .curveEaseIn) { - self.unlockVip4View.transform = CGAffineTransform(translationX: 0, y: self.unlockVip4PopupHeight) - } completion: { _ in - Self.dismiss() - } - } - - // MARK: - 注册账号 1 - lazy var registerPopupView: UIView = { - let view = UIView() - view.backgroundColor = .clear - view.isHidden = true - - let bgImg = UIImageView(image: UIImage(named: "PopupWindow/register_bg")) - bgImg.contentMode = .scaleAspectFill - view.addSubview(bgImg) - bgImg.layoutChain - .top(51) - .edgesHorzontal() - .bottom() - - let logoImg = UIImageView(image: UIImage(named: "PopupWindow/register_logo")) - logoImg.contentMode = .scaleAspectFill - view.addSubview(logoImg) - logoImg.layoutChain - .top() - .centerX() - .width(250) - .height(123) - - let textImg = UIImageView(image: UIImage(named: "PopupWindow/register_text")) - textImg.contentMode = .scaleAspectFill - view.addSubview(textImg) - textImg.layoutChain - .topToBottomOfView(logoImg, offset: 20) - .width(272) - .height(50) - .centerX() - - view.addSubview(register1UpLottieView) - register1UpLottieView.layoutChain - .bottomToTopOfView(logoImg, offset: 120) - .edgesHorzontal() - .height(200) - - view.addSubview(register1DownLottieView) - register1DownLottieView.layoutChain - .topToBottomOfView(logoImg, offset: -140) - .edgesHorzontal() - .height(200) - -// view.addSubview(registerStar1) -// registerStar1.layoutChain -// .top(19) -// .leftToView(logoImg, offset: -31) -// .width(68) -// .heightToWidth(1.0) - - view.addSubview(registerStar3) - registerStar3.layoutChain - .top(23) - .rightToView(logoImg, offset: -9) - .width(26) - .height(20) - - view.addSubview(registerStar2) - registerStar2.layoutChain - .top(31) - .rightToView(logoImg, offset: 20) - .width(48) - .height(44) - - view.addSubview(registerCloseBtn) - registerCloseBtn.layoutChain - .topToBottomOfView(textImg, offset: 30) - .left(30) - .height(50) - - view.addSubview(registerBtn) - registerBtn.layoutChain - .topToBottomOfView(textImg, offset: 30) - .right(30) - .height(50) - .widthToView(registerCloseBtn) - - registerCloseBtn.layoutChain.rightToLeftOfView(registerBtn, offset: -10) - - return view - }() - - lazy var register1UpLottieView: LottieAnimationView = { - let view = LottieAnimationView(name: "dialog_register_tip1_1") - return view - }() - - lazy var register1DownLottieView: LottieAnimationView = { - let view = LottieAnimationView(name: "dialog_register_tip1_2") - return view - }() - - lazy var registerStar1: UIImageView = { - let view = UIImageView() - view.image = UIImage(named: "PopupWindow/star_1") - return view - }() - - lazy var registerStar2: UIImageView = { - let view = UIImageView() - view.image = UIImage(named: "PopupWindow/star_2") - return view - }() - - lazy var registerStar3: UIImageView = { - let view = UIImageView() - view.image = UIImage(named: "PopupWindow/star_3") - return view - }() - - lazy var registerCloseBtn: UIButton = { - let btn = UIButton(type: .custom) - btn.setTitle("稍后再说", for: .normal) - btn.setTitleColor(UIColor(hexStr: "#16B3FF"), for: .normal) - btn.titleLabel?.font = .systemFont(ofSize: 16, weight: .medium) - btn.backgroundColor = .white - btn.cornerRadius = 25 - btn.borderWidth = 0.5 - btn.borderColor = UIColor(hexStr: "#16B3FF") - return btn - }() - - lazy var registerBtn: UIButton = { - let btn = UIButton(type: .custom) - btn.setTitle("免费注册", for: .normal) - btn.setTitleColor(.white, for: .normal) - btn.titleLabel?.font = .systemFont(ofSize: 16, weight: .medium) - btn.setBackgroundImage(UIImage(named: "Common/button_bg_2"), for: .normal) - btn.cornerRadius = 25 - return btn - }() - - private var register1LottieAlternating = false - - private func startRegister1LottieAlternate() { - stopRegister1LottieAlternate() - register1LottieAlternating = true - playRegister1Up() - } - - private func playRegister1Up() { - guard register1LottieAlternating else { return } - register1UpLottieView.isHidden = false - register1DownLottieView.isHidden = true - register1UpLottieView.play { [weak self] _ in - self?.playRegister1Down() - } - } - - private func playRegister1Down() { - guard register1LottieAlternating else { return } - register1UpLottieView.isHidden = true - register1DownLottieView.isHidden = false - register1DownLottieView.play { [weak self] _ in - self?.playRegister1Up() - } - } - - private func stopRegister1LottieAlternate() { - register1LottieAlternating = false - register1UpLottieView.stop() - register1DownLottieView.stop() - register1UpLottieView.isHidden = true - register1DownLottieView.isHidden = true - } - - private func startRegisterStarFlash() { - stopRegisterStarFlash() - let (star2, star3) = activePopupView == 2 ? (register2Star2, register2Star3) : (registerStar2, registerStar3) - - let animation2 = CABasicAnimation(keyPath: "opacity") - animation2.fromValue = 1.0 - animation2.toValue = 0.0 - animation2.duration = 0.4 - animation2.autoreverses = true - animation2.repeatCount = .infinity - star2.layer.add(animation2, forKey: "starFlash") - - let animation3 = CABasicAnimation(keyPath: "opacity") - animation3.fromValue = 0.0 - animation3.toValue = 1.0 - animation3.duration = 0.4 - animation3.autoreverses = true - animation3.repeatCount = .infinity - star3.layer.add(animation3, forKey: "starFlash") - } - - private func stopRegisterStarFlash() { - registerStar2.layer.removeAnimation(forKey: "starFlash") - registerStar3.layer.removeAnimation(forKey: "starFlash") - register2Star2.layer.removeAnimation(forKey: "starFlash") - register2Star3.layer.removeAnimation(forKey: "starFlash") - } - - private func animateRegisterStarSlideIn() { - UIView.animate(withDuration: 0.5, delay: 0, - usingSpringWithDamping: 0.7, - initialSpringVelocity: 0.6, - options: .curveEaseOut) { - self.registerStar1.transform = .identity - } - } - - private let registerPopupHeight: CGFloat = 308 - - private var activePopupView = 1 - - private func slideInRegisterPopup() { - activePopupView = 1 - stopRegisterStarFlash() - bgView.isUserInteractionEnabled = false - registerPopupView.isHidden = false - registerPopupView.layoutIfNeeded() -// registerStar1.transform = CGAffineTransform(translationX: -(registerStar1.frame.maxX + 30), y: 0) - registerPopupView.transform = CGAffineTransform(translationX: 0, y: registerPopupHeight) - UIView.animate(withDuration: 0.45, delay: 0, - usingSpringWithDamping: 0.8, - initialSpringVelocity: 0.5, - options: .curveEaseOut) { - self.registerPopupView.transform = .identity - } completion: { _ in - self.bgView.isUserInteractionEnabled = true - self.startRegisterStarFlash() - self.startRegister1LottieAlternate() -// self.animateRegisterStarSlideIn() - } - } - - private func slideOutRegisterPopup() { - stopRegisterStarFlash() - stopRegister1LottieAlternate() - bgView.isUserInteractionEnabled = false - UIView.animate(withDuration: 0.3, delay: 0, options: .curveEaseIn) { - self.registerPopupView.transform = CGAffineTransform(translationX: 0, y: self.registerPopupHeight) - } completion: { _ in - Self.dismiss() - } - } - - private func slideInRegister2Popup() { - activePopupView = 2 - stopRegisterStarFlash() - bgView.isUserInteractionEnabled = false - register2PopupView.isHidden = false - register2PopupView.layoutIfNeeded() -// register2Star1.transform = CGAffineTransform(translationX: -(register2Star1.frame.maxX + 30), y: 0) - register2PopupView.transform = CGAffineTransform(translationX: 0, y: register2PopupView.bounds.height) - UIView.animate(withDuration: 0.45, delay: 0, - usingSpringWithDamping: 0.8, - initialSpringVelocity: 0.5, - options: .curveEaseOut) { - self.register2PopupView.transform = .identity - } completion: { _ in - self.bgView.isUserInteractionEnabled = true - self.startRegisterStarFlash() - self.register2LottieView.play() -// self.animateRegister2StarSlideIn() - } - } - - private func slideOutRegister2Popup() { - stopRegisterStarFlash() - bgView.isUserInteractionEnabled = false - UIView.animate(withDuration: 0.3, delay: 0, options: .curveEaseIn) { - self.register2PopupView.transform = CGAffineTransform(translationX: 0, y: self.register2PopupView.bounds.height) - } completion: { _ in - Self.dismiss() - } - } - - private func animateRegister2StarSlideIn() { - UIView.animate(withDuration: 0.55, delay: 0.1, - usingSpringWithDamping: 0.65, - initialSpringVelocity: 0.4, - options: .curveEaseOut) { - self.register2Star1.transform = .identity - } - } - - // MARK: - 注册账号 2 - lazy var register2PopupView: UIView = { - let view = UIView() - view.backgroundColor = .clear - view.isHidden = true - - let bgImg = UIImageView(image: UIImage(named: "PopupWindow/register_bg")) - bgImg.contentMode = .scaleAspectFill - view.addSubview(bgImg) - bgImg.layoutChain - .top(58) - .edgesHorzontal() - .bottom() - - let logoImg = UIImageView(image: UIImage(named: "PopupWindow/register2_logo")) - logoImg.contentMode = .scaleAspectFill - view.addSubview(register2LottieView) - view.addSubview(logoImg) - logoImg.layoutChain - .top() - .centerX() - .width(243) - .height(97) - - let textLab = UILabel() - textLab.text = "注册后即可保存历史轨迹、多人 共享地图、跨设备同步。" - textLab.font = .systemFont(ofSize: 16, weight: .medium) - textLab.textColor = UIColor(hexStr: "#16B3FF") - textLab.numberOfLines = 0 - view.addSubview(textLab) - textLab.layoutChain - .topToBottomOfView(logoImg, offset: 33) - .edgesHorzontal(75) - - register2LottieView.layoutChain - .top() - .rightToLeftOfView(logoImg, offset: 45) - .width(100) - .heightToWidth(1.0) - - view.addSubview(register2Star3) - register2Star3.layoutChain - .top(25) - .rightToView(logoImg, offset: -6) - .width(26) - .height(20) - - view.addSubview(register2Star2) - register2Star2.layoutChain - .top(32) - .rightToView(logoImg, offset: 25) - .width(48) - .height(44) - - view.addSubview(register2Btn) - register2Btn.layoutChain - .topToBottomOfView(textLab, offset: 30) - .width(224) - .height(50) - .centerX() - - view.addSubview(register2CloseBtn) - register2CloseBtn.layoutChain - .topToView(bgImg, offset: 32) - .right(15) - - return view - }() - - lazy var register2LottieView: LottieAnimationView = { - let view = LottieAnimationView(name: "dialog_register_tip2") - view.loopMode = .loop - return view - }() - - lazy var register2Star1: UIImageView = { - let view = UIImageView() - view.image = UIImage(named: "PopupWindow/register_heart") - return view - }() - - lazy var register2Star2: UIImageView = { - let view = UIImageView() - view.image = UIImage(named: "PopupWindow/star_2") - return view - }() - - lazy var register2Star3: UIImageView = { - let view = UIImageView() - view.image = UIImage(named: "PopupWindow/star_3") - return view - }() - - lazy var register2CloseBtn: UIButton = { - let btn = UIButton(type: .custom) - btn.setImage(UIImage(named: "PopupWindow/close"), for: .normal) - btn.extendEdgeInsets = UIEdgeInsets(top: 30, left: 30, bottom: 30, right: 15) - return btn - }() - - lazy var register2Btn: UIButton = { - let btn = UIButton(type: .custom) - btn.setTitle("免费注册", for: .normal) - btn.setTitleColor(.white, for: .normal) - btn.titleLabel?.font = .systemFont(ofSize: 16, weight: .medium) - btn.setBackgroundImage(UIImage(named: "Common/button_bg_2"), for: .normal) - btn.cornerRadius = 25 - return btn - }() - - // MARK: - Init - override init(frame: CGRect) { - super.init(frame: frame) - backgroundColor = .clear - addSubview(bgView) - bgView.addSubview(searchPopupView) - bgView.addSubview(unlockVip1View) - bgView.addSubview(unlockVip2View) - bgView.addSubview(unlockVip3View) - bgView.addSubview(unlockVip4View) - bgView.addSubview(registerPopupView) - bgView.addSubview(register2PopupView) - - searchPopupView.layoutChain - .centerY() - .centerX() - - registerPopupView.layoutChain - .edgesHorzontal() - .bottom() - .height(308) - - register2PopupView.layoutChain - .edgesHorzontal() - .bottom() - .height(295) - - unlockVip1View.layoutChain - .edgesHorzontal() - .bottom() - .height(unlockVip1PopupHeight) - - unlockVip2View.layoutChain - .edgesHorzontal() - .bottom() - .height(unlockVip2PopupHeight) - - unlockVip3View.layoutChain - .edgesHorzontal() - .bottom() - .height(unlockVip3PopupHeight) - - unlockVip4View.layoutChain - .edgesHorzontal() - .bottom() - .height(unlockVip4PopupHeight) - - - setupRx() - } - - required init?(coder aDecoder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - override func layoutSubviews() { - super.layoutSubviews() - - } -} diff --git a/QuickLocation/Section/Schedule/CreateSchedule/CreateScheduleVC.swift b/QuickLocation/Section/Schedule/CreateSchedule/CreateScheduleVC.swift index a5a6af89..7b8a591e 100644 --- a/QuickLocation/Section/Schedule/CreateSchedule/CreateScheduleVC.swift +++ b/QuickLocation/Section/Schedule/CreateSchedule/CreateScheduleVC.swift @@ -110,16 +110,7 @@ class CreateScheduleVC: BaseViewController, MAMapViewDelegate { AppRouter.shared.popOrDismiss() } }, onError: { error in - guard let code = error.underlyingError?.code else { return } - - guard let systemConfig = AppContextManager.shared.systemConfig, systemConfig.isIntercept == false else { return } - - if code == 20010 { // "创建的行程数达到上限" - CreateScheduleVipPopView.show() - } - else { - self.dl.show(error) - } + self.dl.show(error) }).disposed(by: disposeBag) } diff --git a/QuickLocation/Section/Schedule/CreateSchedule/CreateScheduleVipPopView.swift b/QuickLocation/Section/Schedule/CreateSchedule/CreateScheduleVipPopView.swift deleted file mode 100644 index 979b0558..00000000 --- a/QuickLocation/Section/Schedule/CreateSchedule/CreateScheduleVipPopView.swift +++ /dev/null @@ -1,120 +0,0 @@ -// -// CreateScheduleVipPopView.swift -// QuickLocation -// -// Created by 八条 on 2026/6/25. -// - -import UIKit -import RxSwift -import RxCocoa - -class CreateScheduleVipPopView: UIView { - - private static let shared = CreateScheduleVipPopView(frame: CGRect(origin: .zero, size: kScreenSize)) - - var disposeBag = DisposeBag() - - static func show() { - guard let superView = kKeyWindow else { - return - } - - if CreateScheduleVipPopView.shared.superview != nil { - CreateScheduleVipPopView.shared.removeFromSuperview() - CreateScheduleVipPopView.shared.bgView.frame = .zero - } - CreateScheduleVipPopView.shared.bgView.alpha = 1 - CreateScheduleVipPopView.shared.bgView.frame = CGRect(x: 0, y: 0, width: kScreenWidth, height: kScreenHeight) - superView.addSubview(CreateScheduleVipPopView.shared) - superView.bringSubviewToFront(CreateScheduleVipPopView.shared) - - UIView.animate(withDuration: 0.25) { - CreateScheduleVipPopView.shared.bgView.alpha = 1 - } - } - - /// 关闭 - static func dismiss() { - guard CreateScheduleVipPopView.shared.superview != nil else { return } - - UIView.animate(withDuration: 0.25, delay: 0, options: [.curveEaseIn]) { - CreateScheduleVipPopView.shared.bgView.alpha = 0 - } completion: { _ in - CreateScheduleVipPopView.shared.removeFromSuperview() - } - } - - private func setupRx() { - upgradedBtn.rx.tap.subscribe(onNext: { _ in - CreateScheduleVipPopView.dismiss() - AppRouter.push(Route.web, userInfo: ["url": URLManager.shared.homeUrl]) - }).disposed(by: disposeBag) - - closeBtn.rx.tap.subscribe(onNext: { _ in - CreateScheduleVipPopView.dismiss() - }).disposed(by: disposeBag) - } - - private lazy var bgView: UIView = { - let view = UIView() - view.backgroundColor = .black.withAlphaComponent(0.5) - return view - }() - - lazy var vipImgView: UIImageView = { - let view = UIImageView() - view.image = UIImage(named: "Schedule/vip_pop") - view.contentMode = .scaleAspectFill - return view - }() - - lazy var upgradedBtn: UIButton = { - let btn = UIButton(type: .custom) - btn.backgroundColor = .clear - btn.setBackgroundImage(UIImage(named: "Schedule/upgrade_bg"), for: .normal) - return btn - }() - - lazy var closeBtn: UIButton = { - let btn = UIButton(type: .custom) - btn.backgroundColor = .clear - btn.setBackgroundImage(UIImage(named: "Group/close"), for: .normal) - btn.extendEdgeInsets = UIEdgeInsets(top: 10, left: 100, bottom: 100, right: 100) - return btn - }() - - // MARK: - Init - override init(frame: CGRect) { - super.init(frame: frame) - backgroundColor = .clear - addSubview(bgView) - bgView.addSubview(vipImgView) - bgView.addSubview(upgradedBtn) - bgView.addSubview(closeBtn) - - vipImgView.layoutChain - .centerY() - .edgesHorzontal(25) - .heightToWidth(814/648) - - upgradedBtn.layoutChain - .topToBottomOfView(vipImgView, offset: -20) - .centerX() - .width(240) - .height(60) - - closeBtn.layoutChain - .topToBottomOfView(upgradedBtn, offset: 15) - .centerX() - .width(22) - .height(22) - - setupRx() - } - - required init?(coder aDecoder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - -} diff --git a/QuickLocation/Section/Schedule/ScheduleVC.swift b/QuickLocation/Section/Schedule/ScheduleVC.swift deleted file mode 100644 index b74cb084..00000000 --- a/QuickLocation/Section/Schedule/ScheduleVC.swift +++ /dev/null @@ -1,179 +0,0 @@ -// -// ScheduleVC.swift -// QuickLocation -// -// Created by 八条 on 2026/6/23. -// - -import UIKit -import RxSwift -import RxCocoa -import RxDataSources -import MJRefresh -import ObjectMapper - -class ScheduleVC: BaseViewController { - - fileprivate var rootView: ScheduleView! - - override func loadView() { - rootView = ScheduleView(frame: UIScreen.main.bounds) - view = rootView - } - - private var viewModel = ScheduleViewModel() - - override func viewDidLoad() { - super.viewDidLoad() - - // Do any additional setup after loading the view. - rootView.allCheckBtn.isSelected = true - setupTableViewHeaderFooter() - bindViewModel() - reactiveAction() - - } - - override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - requestFollowList() - requestData() - } - - private func bindViewModel() { - viewModel.output.sectionedItems - .bind(to: rootView.collectionView.rx.items(dataSource: dataSource)) - .disposed(by: disposeBag) - - viewModel.output.scheduleSectionedItems - .bind(to: rootView.tableView.rx.items(dataSource: tableViewDataSource)) - .disposed(by: disposeBag) - - viewModel.output.refreshResult.subscribe(onNext: { [weak self] (status, isEmpty) in - guard let self = self else { return } - self.dl.dismiss() - self.rootView.tableView.refresh(status: status, isEmpty: isEmpty) - }).disposed(by: disposeBag) - - viewModel.output.sectionedItems - .map { !($0.first?.items.isEmpty ?? true) } - .bind(to: rootView.emptyVisitorsLabel.rx.isHidden) - .disposed(by: disposeBag) - - viewModel.output.scheduleSectionedItems - .map { !($0.first?.items.isEmpty ?? true) } - .bind(to: rootView.emptyScheduleLabel.rx.isHidden) - .disposed(by: disposeBag) - - rootView.collectionView.rx.modelSelected(ViewedModel.self) - .subscribe(viewModel.viewedCellAction.inputs) - .disposed(by: disposeBag) - - rootView.tableView.rx.modelSelected(ScheduleModel.self) - .subscribe(viewModel.cellAction.inputs) - .disposed(by: disposeBag) - } - - private func reactiveAction() { - // 全部 - rootView.allCheckBtn.rx.tap.subscribe(onNext: { [weak self] _ in - guard let self = self, !self.rootView.allCheckBtn.isSelected else { return } - self.rootView.allCheckBtn.isSelected = true - self.rootView.followedCheckBtn.isSelected = false - self.rootView.mineCheckBtn.isSelected = false - self.changeCondition(follow: false, own: false) - }).disposed(by: disposeBag) - - // 我关注的 - rootView.followedCheckBtn.rx.tap.subscribe(onNext: { [weak self] _ in - guard let self = self, !self.rootView.followedCheckBtn.isSelected else { return } - self.rootView.allCheckBtn.isSelected = false - self.rootView.followedCheckBtn.isSelected = true - self.rootView.mineCheckBtn.isSelected = false - self.changeCondition(follow: true, own: false) - }).disposed(by: disposeBag) - - // 我的 - rootView.mineCheckBtn.rx.tap.subscribe(onNext: { [weak self] _ in - guard let self = self, !self.rootView.mineCheckBtn.isSelected else { return } - self.rootView.allCheckBtn.isSelected = false - self.rootView.followedCheckBtn.isSelected = false - self.rootView.mineCheckBtn.isSelected = true - self.changeCondition(follow: false, own: true) - }).disposed(by: disposeBag) - } - - private func setupTableViewHeaderFooter() { - // 设置刷新header/footer - let header = MJRefreshNormalHeader(refreshingBlock: { [weak self] in - self?.viewModel.refresh() - }) - header.addFeedbackGenerator() - header.stateLabel?.isHidden = true - rootView.tableView.mj_header = header - - let footer = MJRefreshAutoNormalFooter(refreshingBlock: viewModel.loadMore) - footer.isHidden = true - rootView.tableView.mj_footer = footer - } - - // MARK: - API - private func requestFollowList() { - DLToast.showLoading() - UserService.followList().subscribe(onNext: { response in - DLToast.dismiss() - self.viewModel.loadViewedData(response.list) - }).disposed(by: disposeBag) - } - - private func requestSetFollow(id: String, op: Bool) { - DLToast.showLoading() - ItineraryService.follow(id: id, op: op ? 2 : 1).subscribe(onNext: { response in - DLToast.dismiss() - DLToast.show(text: op ? "已取消" : "已关注此行程, \n行程路线将自动添加到您的行程列表。") - self.requestData() - }).disposed(by: disposeBag) - } - - // MARK: - API 行程列表 - private func requestData() { - viewModel.refresh() - } - - // 更换查询条件 - private func changeCondition(follow: Bool, own: Bool) { - viewModel.changeCondition(follow: follow, own: own) - requestData() - } - - // MARK: - dataSource - private lazy var dataSource: RxCollectionViewSectionedReloadDataSource = { - RxCollectionViewSectionedReloadDataSource { datasource, collectionView, indexPath, model in - let cell: ViewedCell = collectionView.dequeueReusableCell(for: indexPath) - cell.configure(model) - return cell - } - }() - - // MARK: - UITableViewDataSource - lazy private var tableViewDataSource: RxTableViewSectionedReloadDataSource = { - return RxTableViewSectionedReloadDataSource( - configureCell: { (_, tableView, indexPath, model) in - let cell: ScheduleListPopCell = tableView.dequeueReusableCell(for: indexPath) - cell.configure(model) - - // 编辑 - cell.editBtn.rx.tap.subscribe(onNext: { _ in - AppRouter.push(Route.createSchedule, userInfo: ["scheduleJson": model.toJSON()]) - }).disposed(by: cell.disposeBag) - - // 关注 - cell.followBtn.rx.tap.subscribe(onNext: { _ in - self.requestSetFollow(id: model.id, op: cell.followBtn.isSelected) - }).disposed(by: cell.disposeBag) - - return cell - } - ) - }() -} diff --git a/QuickLocation/Section/Schedule/ScheduleView.swift b/QuickLocation/Section/Schedule/ScheduleView.swift deleted file mode 100644 index b82746e5..00000000 --- a/QuickLocation/Section/Schedule/ScheduleView.swift +++ /dev/null @@ -1,508 +0,0 @@ -// -// ScheduleView.swift -// QuickLocation -// -// Created by 八条 on 2026/6/23. -// - -import UIKit -import RxSwift -import RxCocoa -import TagListView - -class ScheduleView: UIView { - - var disposeBag = DisposeBag() - - private func setupRx() { - createBtn.rx.tap.subscribe(onNext: { _ in - AppRouter.push(Route.createSchedule) - }).disposed(by: disposeBag) - } - - private func setupUI() { - addSubview(navBgView) - addSubview(navView) - addSubview(headerView) - addSubview(travelRouteView) - addSubview(tableView) - - addSubview(createBtn) - - navBgView.layoutChain - .edges(excludingEdge: .bottom) - .height(kNaviHeight) - - navView.layoutChain - .edges(excludingEdge: .bottom) - .height(kNaviHeight) - - headerView.layoutChain - .topToBottomOfView(navView) - .edgesHorzontal() -// .height(147) - - travelRouteView.layoutChain - .topToBottomOfView(headerView) - .edgesHorzontal() - - tableView.layoutChain - .topToBottomOfView(travelRouteView) - .edges(excludingEdge: .top) - - createBtn.layoutChain - .bottom(kSafeBottomMargin + 102) - .right(10) - .width(60) - .heightToWidth(1) - } - - lazy var navBgView: UIImageView = { - let iv = UIImageView() - iv.image = UIImage(named: "Common/navBar_bg_1") - iv.contentMode = .scaleAspectFill - return iv - }() - - lazy var navView: BaseNavigationView = { - let nav = BaseNavigationView(title: "行程") - nav.backBtn.isHidden = true - return nav - }() - - /// 谁看过我 - lazy var headerView: UIView = { - let view = UIView() - view.backgroundColor = .clear - - let titleLab = UILabel() - titleLab.text = "谁看过我" - titleLab.font = .systemFont(ofSize: 16, weight: .medium) - titleLab.textColor = ThemeManager.shared.color.titleAuxColor - view.addSubview(titleLab) - titleLab.layoutChain - .top(15) - - let dotView = UIView() - dotView.backgroundColor = UIColor(hexStr: "#16B3FF") - dotView.cornerRadius = 2 - view.addSubview(dotView) - dotView.layoutChain - .left(15) - .centerY(titleLab) - .width(4) - .height(11) - - titleLab.layoutChain.leftToRightOfView(dotView, offset: 5) - - let historyBtn = UIButton() - historyBtn.setTitle("历史行程", for: .normal) - historyBtn.setTitleColor(ThemeManager.shared.color.titleAuxColor, for: .normal) - historyBtn.titleLabel?.font = .systemFont(ofSize: 12, weight: .medium) - historyBtn.rx.tap.subscribe(onNext: { _ in - AppRouter.push(Route.scheduleHistory) - }).disposed(by: disposeBag) - view.addSubview(historyBtn) - historyBtn.layoutChain - .right(15) - .centerY(titleLab) - historyBtn.sizeToFit() - - view.addSubview(collectionView) - collectionView.layoutChain - .topToBottomOfView(titleLab, offset: 15) - .edgesHorzontal() - .height(80) - .bottom(15) - - // 暂无访客 - view.addSubview(emptyVisitorsLabel) - emptyVisitorsLabel.layoutChain - .centerY(collectionView) - .centerX() - - return view - }() - - lazy var collectionView: UICollectionView = { - let layout = UICollectionViewFlowLayout() - layout.scrollDirection = .horizontal - layout.itemSize = CGSize(width: 80, height: 80) - layout.minimumLineSpacing = 15 - layout.sectionInset = UIEdgeInsets(top: 0, left: 15, bottom: 0, right: 15) - let cv = UICollectionView(frame: .zero, collectionViewLayout: layout) - cv.backgroundColor = .clear - cv.showsHorizontalScrollIndicator = false - cv.register(ViewedCell.self) - return cv - }() - - lazy var emptyVisitorsLabel: UILabel = { - let label = UILabel() - label.text = "暂无访客" - label.font = .systemFont(ofSize: 14) - label.textColor = UIColor(hexStr: "#999999") - label.textAlignment = .center - label.isHidden = true - return label - }() - - /// 行程路线 - lazy var travelRouteView: UIView = { - let view = UIView() - view.backgroundColor = .clear - - let titleLab = UILabel() - titleLab.text = "行程路线" - titleLab.font = .systemFont(ofSize: 16, weight: .medium) - titleLab.textColor = ThemeManager.shared.color.titleAuxColor - view.addSubview(titleLab) - titleLab.layoutChain - .top(15) - .edgesVertical(5) - - let dotView = UIView() - dotView.backgroundColor = UIColor(hexStr: "#16B3FF") - dotView.cornerRadius = 2 - view.addSubview(dotView) - dotView.layoutChain - .left(15) - .centerY(titleLab) - .width(4) - .height(11) - - titleLab.layoutChain.leftToRightOfView(dotView, offset: 5) - - // 筛选 checkbox(从右到左) - view.addSubview(allCheckBtn) - view.addSubview(followedCheckBtn) - view.addSubview(mineCheckBtn) - - allCheckBtn.layoutChain - .right(15) - .centerY(titleLab) - followedCheckBtn.layoutChain - .rightToLeftOfView(allCheckBtn, offset: -20) - .centerY(titleLab) - mineCheckBtn.layoutChain - .rightToLeftOfView(followedCheckBtn, offset: -20) - .centerY(titleLab) - - return view - }() - - lazy var allCheckBtn: UIButton = makeCheckButton(title: "全部") - lazy var followedCheckBtn: UIButton = makeCheckButton(title: "我关注的") - lazy var mineCheckBtn: UIButton = makeCheckButton(title: "我的") - - private func makeCheckButton(title: String) -> UIButton { - let btn = UIButton(type: .custom) - btn.setImage(UIImage(named: "Schedule/checkbox"), for: .normal) - btn.setImage(UIImage(named: "Schedule/checkbox_selected"), for: .selected) - btn.setTitle(" \(title)", for: .normal) - btn.setTitleColor(UIColor(hexStr: "#333333"), for: .normal) - btn.titleLabel?.font = .systemFont(ofSize: 13, weight: .medium) - btn.sizeToFit() - return btn - } - - lazy var tableView: UITableView = { - let tableView = UITableView(frame: .zero, style: .plain) - tableView.backgroundColor = .clear - tableView.separatorStyle = .none - tableView.estimatedRowHeight = 80 - tableView.rowHeight = UITableView.automaticDimension - tableView.showsVerticalScrollIndicator = false - tableView.register(ScheduleListPopCell.self) - tableView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 97 + kSafeBottomMargin, right: 0) - tableView.backgroundView = emptyScheduleLabel - return tableView - }() - - lazy var emptyScheduleLabel: UILabel = { - let label = UILabel() - label.text = "暂无行程" - label.font = .systemFont(ofSize: 14) - label.textColor = UIColor(hexStr: "#999999") - label.textAlignment = .center - label.isHidden = true - return label - }() - - lazy var createBtn: UIButton = { - let btn = UIButton() - btn.setImage(UIImage(named: "Schedule/create"), for: .normal) - return btn - }() - - override init(frame: CGRect) { - super.init(frame: .zero) - backgroundColor = .white - setupUI() - setupRx() - } - - required init?(coder aDecoder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } -} - -// MARK: - ViewedCell -final class ViewedCell: UICollectionViewCell { - - func configure(_ model: ViewedModel) { - iconView.setHeadPic(model.displayHeadPic) - - // 会员权益 - blurView.isHidden = AppContextManager.shared.vip > 1 - lockView.isHidden = AppContextManager.shared.vip > 1 - viewedCountLab.text = "看了\(model.count)次" - } - - lazy var iconView: UIImageView = { - let iv = UIImageView() - iv.contentMode = .scaleAspectFill - iv.cornerRadius = 40 - iv.clipsToBounds = true - iv.backgroundColor = .clear - iv.addSubview(blurView) - blurView.layoutChain.edges() - - return iv - }() - - lazy var blurView: UIVisualEffectView = { - let blurEffect = UIBlurEffect(style: .systemUltraThinMaterial) - let view = UIVisualEffectView(effect: blurEffect) - return view - }() - - lazy var lockView: UIView = { - let view = UIView() - view.backgroundColor = .clear - - let lockIcon = UIImageView(image: UIImage(named: "Common/lock_white")) - lockIcon.contentMode = .scaleAspectFill - view.addSubview(lockIcon) - lockIcon.layoutChain - .top(17) - .centerX() - - view.addSubview(viewedCountLab) - viewedCountLab.layoutChain - .bottom(17) - .edgesHorzontal() - - return view - }() - - lazy var viewedCountLab: UILabel = { - let label = UILabel() - label.font = .systemFont(ofSize: 12, weight: .medium) - label.textColor = .white - label.textAlignment = .center - return label - }() - - override init(frame: CGRect) { - super.init(frame: frame) - contentView.addSubview(iconView) - contentView.addSubview(lockView) - - iconView.layoutChain - .edges() - - lockView.layoutChain - .edges() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - -} - -// MARK: - ScheduleListPopCell -class ScheduleListPopCell: UITableViewCell { - - var disposeBag = DisposeBag() - - func configure(_ model: ScheduleModel) { - nameLab.text = model.nick_name + " 的行程路线" - monthLab.text = getDateInterval2String(date: "\(model.timestamp/1000)", dateFormat: "MM月") - editBtn.isHidden = !model.is_own - followBtn.isHidden = model.is_own - followBtn.isSelected = model.is_follow ? true : false - - let groupNames = model.groups.map { $0.group_name } - // addTags 内部立即用 frame.width 排标签,先给个预估宽度避免算错 - if !groupNames.isEmpty { - let w = contentView.frame.width > 0 ? contentView.frame.width : UIScreen.main.bounds.width - tagListView.frame.size.width = w - 170 - } - tagListView.removeAllTags() - tagListView.addTags(groupNames) - tagListView.tagViews.forEach { - $0.layer.cornerRadius = 2 - } - tagListView.invalidateIntrinsicContentSize() - - guard let pointModel = model.points.last else { return } - dateLab.text = getDateInterval2String(date: "\(pointModel.expected_timestamp/1000)", dateFormat: "MM.dd") - } - - override init(style: CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - selectionStyle = .none - backgroundColor = .clear - setupSubviews() - } - - private func setupSubviews() { - contentView.addSubview(bgView) - bgView.addSubview(cornerView) - cornerView.addSubview(nameLab) - cornerView.addSubview(monthLab) - cornerView.addSubview(dateLab) - cornerView.addSubview(tagListView) - cornerView.addSubview(editBtn) - cornerView.addSubview(followBtn) - - bgView.layoutChain - .top(15).bottom(15) - .edgesHorzontal(15) - - cornerView.layoutChain.edges() - - monthLab.layoutChain - .top(15) - .left(11) - .width(35) - - dateLab.layoutChain - .topToBottomOfView(monthLab, offset: 4) - .leftToView(monthLab) - .width(35) - - editBtn.layoutChain - .top(15) - .right(10) - .width(70) - .height(28) - - nameLab.layoutChain - .top(15) - .leftToRightOfView(monthLab, offset: 15) - - tagListView.layoutChain - .leftToRightOfView(dateLab, offset: 15) - .bottom(15) - .rightToLeftOfView(editBtn, offset: -10) - - nameLab.layoutChain.bottomToTopOfView(tagListView, offset:-5) - - followBtn.layoutChain - .topToView(editBtn) - .rightToView(editBtn) - .width(70) - .height(28) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - 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 func prepareForReuse() { - super.prepareForReuse() - disposeBag = DisposeBag() - } - - lazy var bgView: UIView = { - let view = UIView() - view.backgroundColor = .clear - view.layer.shadowColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.05).cgColor - view.layer.shadowOffset = CGSize(width: 0, height: 0) - view.layer.shadowOpacity = 1 - view.layer.shadowRadius = 8 - return view - }() - - lazy var cornerView: UIView = { - let view = UIView() - view.backgroundColor = .white - view.cornerRadius = 10 - return view - }() - - lazy var monthLab: UILabel = { - let label = UILabel() - label.textColor = ThemeManager.shared.color.titleAuxColor - label.font = .systemFont(ofSize: 14, weight: .medium) - return label - }() - - lazy var dateLab: UILabel = { - let label = UILabel() - label.textColor = ThemeManager.shared.color.subTitleColor - label.font = .systemFont(ofSize: 12, weight: .regular) - return label - }() - - lazy var nameLab: UILabel = { - let label = UILabel() - label.textColor = ThemeManager.shared.color.titleAuxColor - label.font = .systemFont(ofSize: 14, weight: .medium) - return label - }() - - lazy var editBtn: UIButton = { - let btn = UIButton() - btn.isHidden = true - btn.setTitle("编辑", for: .normal) - btn.titleLabel?.font = .systemFont(ofSize: 12, weight: .medium) - btn.setTitleColor(UIColor(hexStr: "#0F2846"), for: .normal) - btn.backgroundColor = UIColor(hexStr: "#EEFAFF") - btn.borderWidth = 0.5 - btn.borderColor = UIColor(hexStr: "#16B3FF") - btn.cornerRadius = 14 - return btn - }() - - lazy var followBtn: UIButton = { - let btn = UIButton() - btn.isHidden = true - btn.setTitle("关注", for: .normal) - btn.setTitle("取消关注", for: .selected) - btn.titleLabel?.font = .systemFont(ofSize: 12, weight: .medium) - btn.setTitleColor(UIColor(hexStr: "#16B3FF"), for: .normal) - btn.backgroundColor = .white - btn.borderWidth = 0.5 - btn.borderColor = UIColor(hexStr: "#16B3FF") - btn.cornerRadius = 14 - return btn - }() - - lazy var tagListView: TagListView = { - let view = TagListView() - view.textFont = UIFont.systemFont(ofSize: 8, weight: .regular) - view.textColor = UIColor(hexStr: "#B78C56") - view.tagBackgroundColor = UIColor(hexStr: "#FFF3E4") - view.paddingX = 6 // 水平内边距 - view.paddingY = 6 // 垂直内边距 - view.alignment = .left // 对齐 - view.translatesAutoresizingMaskIntoConstraints = false - return view - }() -} diff --git a/QuickLocation/Service/OrderService.swift b/QuickLocation/Service/OrderService.swift deleted file mode 100644 index c5479dbb..00000000 --- a/QuickLocation/Service/OrderService.swift +++ /dev/null @@ -1,44 +0,0 @@ -// -// OrderService.swift -// QuickLocation -// -// Created by 八条 on 2026/6/17. -// - -import RxSwift -import Moya - -struct OrderService { - static let disposeBag = DisposeBag() - -// /// 充值内容 -// /// - Parameters: -// /// - type: 类型 member -// static func rechargeInfo(type: String) -> Observable { -// let api = OrderAPI.rechargeInfo(type: type).multiTarget -// return APIProvider.request(token: api) -// .map(VipExpenseResponse.self) -// .asObservable() -// } - - /// 支付参数 - /// - Parameters: - /// - goodsId: 商品ID - /// - payType: alipay、weixin - /// - source: center - /// - extra: 额外参数 - static func orderPayParams(goodsId: String, payType: String, source: String="center", extra: [String:Any]=[:]) -> Observable { - let api = OrderAPI.orderPayParams(goodsId: goodsId, payType: payType, source: source, extra: extra).multiTarget - return APIProvider.request(token: api) - .map(ResponseModel.self) - .asObservable() - } - - /// Apple 内购通知 - static func appleNotify(receipt: String, productId: String, transactionId: String) -> Observable { - let api = OrderAPI.appleNotify(receipt: receipt, productId: productId, transactionId: transactionId).multiTarget - return APIProvider.request(token: api) - .map { _ in () } - .asObservable() - } -} diff --git a/QuickLocation/UIKit/Pop/PayResultPopVC.swift b/QuickLocation/UIKit/Pop/PayResultPopVC.swift deleted file mode 100644 index a2220759..00000000 --- a/QuickLocation/UIKit/Pop/PayResultPopVC.swift +++ /dev/null @@ -1,281 +0,0 @@ -// -// PayResultPopVC.swift -// QuickLocation -// -// Created by 八条 on 2026/6/17. -// - -import UIKit -import RxSwift -import RxCocoa -import URLNavigator - -class PayResultPopVC: DLCustomPopVC { - - var disposeBag = DisposeBag() - - // MARK: - Accessor - public var confirmBlock: (() -> Void)? - public var cancelBlock: (() -> Void)? - - public var status: Bool? { - didSet { - guard let status = status else { return } - logoImgView.image = UIImage(named: status ? "Popup/success" : "Popup/failure") - } - } - public var titleText: String? { - didSet { - titleLab.text = titleText - } - } - public var contentText: String? { - didSet { - contentLab.text = contentText - } - } - public var cancelText: String? { - didSet { - closeBtn.setTitle(cancelText, for: .normal) - } - } - public var confirmText: String? { - didSet { - confirmBtn.setTitle(confirmText, for: .normal) - } - } - - private func setupSubviews() { - contentBgView.addSubview(logoImgView) - contentView.addSubview(headerBgImg) - - if titleText != nil, - titleText?.isEmpty == false { - contentView.addSubview(titleLab) - } - - if contentText != nil, - contentText?.isEmpty == false { - contentView.addSubview(contentLab) - } - - if cancelText?.isEmpty == false || confirmText?.isEmpty == false { - contentView.addSubview(stackView) - } - - closeBtn.isHidden = !(cancelText?.isEmpty == false) - confirmBtn.isHidden = !(confirmText?.isEmpty == false) - } - - private func setupLayout() { - logoImgView.layoutChain - .centerX() - .top(-44) - .width(88) - .height(88) - - headerBgImg.layoutChain - .edges(excludingEdge: .bottom) - .heightToWidth(100/315) - - var tempView: UIView? - if titleText != nil, - titleText?.isEmpty == false { - titleLab.layoutChain - .top(69) - .edgesHorzontal(20) - tempView = titleLab - } - - if contentText != nil, - contentText?.isEmpty == false { - - if let tempView = tempView { - contentLab.layoutChain - .edgesHorzontal(20) - .topToBottomOfView(tempView, offset: 20) - } else { - contentLab.layoutChain - .top(53) - .edgesHorzontal(20) - } - tempView = contentLab - } - - guard let tempView = tempView else { return } - if cancelText?.isEmpty == false || confirmText?.isEmpty == false { - stackView.layoutChain - .topToBottomOfView(tempView, offset: 30) - .left(20) - .right(20) - .bottom(15) - - confirmBtn.layoutChain - .height(50) - - closeBtn.layoutChain - .height(50) - } - } - - // MARK: - UI - private lazy var bgView: UIView = { - let view = UIView() - view.backgroundColor = .black.withAlphaComponent(0.5) - return view - }() - - lazy var popView: UIView = { - let view = UIView() - view.backgroundColor = .clear - return view - }() - - lazy var popBgView: UIView = { - let view = UIView() - view.backgroundColor = .white - view.cornerRadius = 30 - return view - }() - - lazy var logoImgView: UIImageView = { - let view = UIImageView() - view.backgroundColor = .clear - return view - }() - - lazy var headerBgImg: UIImageView = { - let view = UIImageView(image: UIImage(named: "Popup/header_bg")) - view.contentMode = .scaleAspectFill - return view - }() - - lazy var titleLab: UILabel = { - let label = UILabel() - label.font = .systemFont(ofSize: 20, weight: .bold) - label.textColor = UIColor(hexStr: "#1A1A1A") - label.textAlignment = .center - label.numberOfLines = 0 - return label - }() - - lazy var contentLab: UILabel = { - let label = UILabel() - label.font = .systemFont(ofSize: 14, weight: .medium) - label.textColor = UIColor(hexStr: "#767676") - label.textAlignment = .center - label.numberOfLines = 0 - return label - }() - - lazy var stackView: UIStackView = { - let view = UIStackView(arrangedSubviews: [confirmBtn, closeBtn]) - view.spacing = 10 - view.axis = .vertical - view.alignment = .fill - view.distribution = .fill - return view - }() - - lazy var confirmBtn: UIButton = { - let btn = UIButton(type: .custom) - btn.setTitle("是", for: .normal) - btn.setTitleColor(.white, for: .normal) - btn.titleLabel?.font = .systemFont(ofSize: 16, weight: .medium) - btn.setBackgroundImage(UIImage(named: "Common/button_bg_2"), for: .normal) - btn.cornerRadius = 25 - btn.addTouchBlock { [weak self] _ in - self?.dismiss(animated: true, completion: { - self?.confirmBlock?() - }) - } - return btn - }() - - lazy var closeBtn: UIButton = { - let btn = UIButton(type: .custom) - btn.setTitle("否", for: .normal) - btn.setTitleColor(UIColor(hexStr: "#16B3FF"), for: .normal) - btn.titleLabel?.font = .systemFont(ofSize: 16, weight: .medium) - btn.backgroundColor = .clear - btn.addTouchBlock { [weak self] _ in - self?.dismiss(animated: true, completion: { - self?.cancelBlock?() - }) - } - return btn - }() - - // MARK: - Lifecycle - override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { - super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) - popStyle = .center - centerCornerRadius = 30 - } - - public required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - public override func viewDidLoad() { - super.viewDidLoad() - - setupSubviews() - setupLayout() - } -} - -public extension UIViewController { - /// 显示弹窗 - /// - Parameters: - /// - status: 支付状态 true false - /// - title: 标题 - /// - message: 文本内容 - /// - confirmText: 确认按钮文案 - /// - confirmBlock: 确认按钮点击回调 - /// - cancelText: 取消按钮文案 - /// - cancelBlock: 取消按钮点击回调 - func showPayResultPop(showCloseBtn: Bool = true, - status: Bool, - title: String?=nil, - message: String?=nil, - confirmText: String?=nil, - confirmBlock: (() -> Void)?=nil, - cancelText: String?=nil, - cancelBlock: (() -> Void)?=nil) { - if title == nil && message == nil { return } - let vc = PayResultPopVC() - vc.titleText = title - vc.status = status - vc.contentText = message - vc.confirmText = confirmText - vc.confirmBlock = confirmBlock - vc.cancelText = cancelText - vc.cancelBlock = cancelBlock - vc.closeBtn.isHidden = !showCloseBtn - vc.dimmingClick = showCloseBtn - present(vc, animated: true) - } - - static func showPayResultPop(showCloseBtn: Bool = true, - status: Bool, - title: String?=nil, - message: String?=nil, - confirmText: String?=nil, - confirmBlock: (() -> Void)?=nil, - cancelText: String?=nil, - cancelBlock: (() -> Void)?=nil) { - if title == nil && message == nil { return } - let vc = PayResultPopVC() - vc.titleText = title - vc.status = status - vc.contentText = message - vc.confirmText = confirmText - vc.confirmBlock = confirmBlock - vc.cancelText = cancelText - vc.cancelBlock = cancelBlock - vc.closeBtn.isHidden = !showCloseBtn - vc.dimmingClick = showCloseBtn - UIViewController.topMost?.present(vc, animated: true) - } -}