From ff8eb522de8346e7657fad7489ddb5cab4fa51d1 Mon Sep 17 00:00:00 2001 From: linshujie Date: Mon, 17 Aug 2026 18:31:16 +0800 Subject: [PATCH] =?UTF-8?q?IM=E8=81=8A=E5=A4=A9=E9=A1=B5=20=E5=8F=91?= =?UTF-8?q?=E9=80=81=E4=BD=8D=E7=BD=AE=EF=BC=88=E9=80=89=E6=8B=A9=E4=BD=8D?= =?UTF-8?q?=E7=BD=AE=E9=A1=B5=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- QuickLocation.xcodeproj/project.pbxproj | 20 + .../Contents.json | 22 + .../remove_member_search@2x.png | Bin 0 -> 673 bytes .../remove_member_search@3x.png | Bin 0 -> 1559 bytes .../Contents.json | 22 + .../remove_member_selected@2x.png | Bin 0 -> 574 bytes .../remove_member_selected@3x.png | Bin 0 -> 1128 bytes .../Contents.json | 22 + .../remove_member_unselected@2x.png | Bin 0 -> 651 bytes .../remove_member_unselected@3x.png | Bin 0 -> 1366 bytes .../IM/at.imageset/Contents.json | 8 + .../Assets.xcassets/IM/at.imageset/at@2x.png | Bin 0 -> 753 bytes .../Assets.xcassets/IM/at.imageset/at@3x.png | Bin 0 -> 1877 bytes .../IM/camera.imageset/Contents.json | 8 + .../IM/camera.imageset/camera@2x.png | Bin 0 -> 751 bytes .../IM/camera.imageset/camera@3x.png | Bin 0 -> 1402 bytes .../IM/emoji_input.imageset/Contents.json | 8 + .../IM/emoji_input.imageset/emoji@2x.png | Bin 0 -> 1320 bytes .../IM/emoji_input.imageset/emoji@3x.png | Bin 0 -> 3521 bytes .../IM/gallery.imageset/Contents.json | 8 + .../IM/gallery.imageset/gallery@2x.png | Bin 0 -> 663 bytes .../IM/gallery.imageset/gallery@3x.png | Bin 0 -> 1327 bytes .../IM/keyboard.imageset/Contents.json | 4 +- .../IM/keyboard.imageset/Icons_Photo@2x.png | Bin 1800 -> 0 bytes .../IM/keyboard.imageset/Icons_Photo@3x.png | Bin 2056 -> 0 bytes .../IM/keyboard.imageset/keyboard@2x.png | Bin 0 -> 1226 bytes .../IM/keyboard.imageset/keyboard@3x.png | Bin 0 -> 3239 bytes .../IM/location.imageset/Contents.json | 8 + .../IM/location.imageset/location@2x.png | Bin 0 -> 737 bytes .../IM/location.imageset/location@3x.png | Bin 0 -> 1372 bytes .../IM/location_pin.imageset/Contents.json | 8 + .../location_pin.imageset/location_pin@2x.png | Bin 0 -> 1010 bytes .../location_pin.imageset/location_pin@3x.png | Bin 0 -> 1789 bytes .../location_recenter.imageset/Contents.json | 8 + .../location_recenter@2x.png | Bin 0 -> 886 bytes .../location_recenter@3x.png | Bin 0 -> 2154 bytes .../IM/member.imageset/Group_1613@2x.png | Bin 963 -> 591 bytes .../IM/member.imageset/Group_1613@3x.png | Bin 1441 -> 1268 bytes .../IM/reply.imageset/Contents.json | 8 + .../IM/reply.imageset/reply@2x.png | Bin 0 -> 563 bytes .../IM/reply.imageset/reply@3x.png | Bin 0 -> 1235 bytes .../IM/send.imageset/Contents.json | 8 + .../IM/send.imageset/send-2@2x.png | Bin 0 -> 498 bytes .../IM/send.imageset/send-2@3x.png | Bin 0 -> 1050 bytes .../IM/setting.imageset/Group_1614@2x.png | Bin 981 -> 581 bytes .../IM/setting.imageset/Group_1614@3x.png | Bin 1471 -> 1300 bytes .../IM/voice_input.imageset/Contents.json | 8 + .../IM/voice_input.imageset/voice@2x.png | Bin 0 -> 1203 bytes .../IM/voice_input.imageset/voice@3x.png | Bin 0 -> 2885 bytes .../Mine/feedback_add.imageset/Contents.json | 8 + .../Mine/feedback_add.imageset/add@2x.png | Bin 0 -> 212 bytes .../Mine/feedback_add.imageset/add@3x.png | Bin 0 -> 351 bytes .../Contents.json | 8 + .../header@2x.png | Bin 0 -> 48956 bytes .../header@3x.png | Bin 0 -> 109065 bytes .../Contents.json | 8 + .../icon@2x.png | Bin 0 -> 9412 bytes .../icon@3x.png | Bin 0 -> 23323 bytes QuickLocation/Manager/App/RouterManager.swift | 8 +- .../Section/Group/GroupChat/GroupChatVC.swift | 917 +++++++++++++++++- .../Group/GroupChat/GroupChatView.swift | 834 +++++++++++----- .../Group/GroupChat/GroupChatViewModel.swift | 122 ++- .../Group/RemoveMember/RemoveMemberVC.swift | 46 +- .../Group/RemoveMember/RemoveMemberView.swift | 482 ++++----- .../RemoveMember/RemoveMemberViewModel.swift | 25 +- .../Section/Mine/About/AboutVC.swift | 2 +- .../Mine/Feedback/FeedbackSuccessView.swift | 88 ++ .../Section/Mine/Feedback/FeedbackVC.swift | 168 ++++ .../Section/Mine/Feedback/FeedbackView.swift | 398 ++++++++ 69 files changed, 2753 insertions(+), 531 deletions(-) create mode 100644 QuickLocation/Assets.xcassets/Group/remove_member_search.imageset/Contents.json create mode 100644 QuickLocation/Assets.xcassets/Group/remove_member_search.imageset/remove_member_search@2x.png create mode 100644 QuickLocation/Assets.xcassets/Group/remove_member_search.imageset/remove_member_search@3x.png create mode 100644 QuickLocation/Assets.xcassets/Group/remove_member_selected.imageset/Contents.json create mode 100644 QuickLocation/Assets.xcassets/Group/remove_member_selected.imageset/remove_member_selected@2x.png create mode 100644 QuickLocation/Assets.xcassets/Group/remove_member_selected.imageset/remove_member_selected@3x.png create mode 100644 QuickLocation/Assets.xcassets/Group/remove_member_unselected.imageset/Contents.json create mode 100644 QuickLocation/Assets.xcassets/Group/remove_member_unselected.imageset/remove_member_unselected@2x.png create mode 100644 QuickLocation/Assets.xcassets/Group/remove_member_unselected.imageset/remove_member_unselected@3x.png create mode 100644 QuickLocation/Assets.xcassets/IM/at.imageset/Contents.json create mode 100644 QuickLocation/Assets.xcassets/IM/at.imageset/at@2x.png create mode 100644 QuickLocation/Assets.xcassets/IM/at.imageset/at@3x.png create mode 100644 QuickLocation/Assets.xcassets/IM/camera.imageset/Contents.json create mode 100644 QuickLocation/Assets.xcassets/IM/camera.imageset/camera@2x.png create mode 100644 QuickLocation/Assets.xcassets/IM/camera.imageset/camera@3x.png create mode 100644 QuickLocation/Assets.xcassets/IM/emoji_input.imageset/Contents.json create mode 100644 QuickLocation/Assets.xcassets/IM/emoji_input.imageset/emoji@2x.png create mode 100644 QuickLocation/Assets.xcassets/IM/emoji_input.imageset/emoji@3x.png create mode 100644 QuickLocation/Assets.xcassets/IM/gallery.imageset/Contents.json create mode 100644 QuickLocation/Assets.xcassets/IM/gallery.imageset/gallery@2x.png create mode 100644 QuickLocation/Assets.xcassets/IM/gallery.imageset/gallery@3x.png delete mode 100644 QuickLocation/Assets.xcassets/IM/keyboard.imageset/Icons_Photo@2x.png delete mode 100644 QuickLocation/Assets.xcassets/IM/keyboard.imageset/Icons_Photo@3x.png create mode 100644 QuickLocation/Assets.xcassets/IM/keyboard.imageset/keyboard@2x.png create mode 100644 QuickLocation/Assets.xcassets/IM/keyboard.imageset/keyboard@3x.png create mode 100644 QuickLocation/Assets.xcassets/IM/location.imageset/Contents.json create mode 100644 QuickLocation/Assets.xcassets/IM/location.imageset/location@2x.png create mode 100644 QuickLocation/Assets.xcassets/IM/location.imageset/location@3x.png create mode 100644 QuickLocation/Assets.xcassets/IM/location_pin.imageset/Contents.json create mode 100644 QuickLocation/Assets.xcassets/IM/location_pin.imageset/location_pin@2x.png create mode 100644 QuickLocation/Assets.xcassets/IM/location_pin.imageset/location_pin@3x.png create mode 100644 QuickLocation/Assets.xcassets/IM/location_recenter.imageset/Contents.json create mode 100644 QuickLocation/Assets.xcassets/IM/location_recenter.imageset/location_recenter@2x.png create mode 100644 QuickLocation/Assets.xcassets/IM/location_recenter.imageset/location_recenter@3x.png create mode 100644 QuickLocation/Assets.xcassets/IM/reply.imageset/Contents.json create mode 100644 QuickLocation/Assets.xcassets/IM/reply.imageset/reply@2x.png create mode 100644 QuickLocation/Assets.xcassets/IM/reply.imageset/reply@3x.png create mode 100644 QuickLocation/Assets.xcassets/IM/send.imageset/Contents.json create mode 100644 QuickLocation/Assets.xcassets/IM/send.imageset/send-2@2x.png create mode 100644 QuickLocation/Assets.xcassets/IM/send.imageset/send-2@3x.png create mode 100644 QuickLocation/Assets.xcassets/IM/voice_input.imageset/Contents.json create mode 100644 QuickLocation/Assets.xcassets/IM/voice_input.imageset/voice@2x.png create mode 100644 QuickLocation/Assets.xcassets/IM/voice_input.imageset/voice@3x.png create mode 100644 QuickLocation/Assets.xcassets/Mine/feedback_add.imageset/Contents.json create mode 100644 QuickLocation/Assets.xcassets/Mine/feedback_add.imageset/add@2x.png create mode 100644 QuickLocation/Assets.xcassets/Mine/feedback_add.imageset/add@3x.png create mode 100644 QuickLocation/Assets.xcassets/Mine/feedback_success_header.imageset/Contents.json create mode 100644 QuickLocation/Assets.xcassets/Mine/feedback_success_header.imageset/header@2x.png create mode 100644 QuickLocation/Assets.xcassets/Mine/feedback_success_header.imageset/header@3x.png create mode 100644 QuickLocation/Assets.xcassets/Mine/feedback_success_icon.imageset/Contents.json create mode 100644 QuickLocation/Assets.xcassets/Mine/feedback_success_icon.imageset/icon@2x.png create mode 100644 QuickLocation/Assets.xcassets/Mine/feedback_success_icon.imageset/icon@3x.png create mode 100644 QuickLocation/Section/Mine/Feedback/FeedbackSuccessView.swift create mode 100644 QuickLocation/Section/Mine/Feedback/FeedbackVC.swift create mode 100644 QuickLocation/Section/Mine/Feedback/FeedbackView.swift diff --git a/QuickLocation.xcodeproj/project.pbxproj b/QuickLocation.xcodeproj/project.pbxproj index 33e8c25b..61fcf7d3 100644 --- a/QuickLocation.xcodeproj/project.pbxproj +++ b/QuickLocation.xcodeproj/project.pbxproj @@ -321,6 +321,9 @@ 55B218A13024A00100784708 /* CancelAccountView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55B218A13024A00100784707 /* CancelAccountView.swift */; }; 55B218A13024A0010078470A /* MemberInfoVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55B218A13024A00100784709 /* MemberInfoVC.swift */; }; 55B218A13024A0010078470C /* MemberInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55B218A13024A0010078470B /* MemberInfoView.swift */; }; + 55B220013031000100784801 /* FeedbackVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55B220003031000100784800 /* FeedbackVC.swift */; }; + 55B220033031000100784803 /* FeedbackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55B220023031000100784802 /* FeedbackView.swift */; }; + 55B220053031000100784805 /* FeedbackSuccessView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55B220043031000100784804 /* FeedbackSuccessView.swift */; }; 55B218B13024B00100784722 /* FeatureIntroVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55B218B13024B00100784721 /* FeatureIntroVC.swift */; }; 55B218B13024B00100784724 /* FeatureIntroView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55B218B13024B00100784723 /* FeatureIntroView.swift */; }; 55B219A2302A000100784751 /* UnlockRequestPopView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55B219A1302A000100784750 /* UnlockRequestPopView.swift */; }; @@ -731,6 +734,9 @@ 55B218A13024A00100784707 /* CancelAccountView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CancelAccountView.swift; sourceTree = ""; }; 55B218A13024A00100784709 /* MemberInfoVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MemberInfoVC.swift; sourceTree = ""; }; 55B218A13024A0010078470B /* MemberInfoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MemberInfoView.swift; sourceTree = ""; }; + 55B220003031000100784800 /* FeedbackVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedbackVC.swift; sourceTree = ""; }; + 55B220023031000100784802 /* FeedbackView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedbackView.swift; sourceTree = ""; }; + 55B220043031000100784804 /* FeedbackSuccessView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedbackSuccessView.swift; sourceTree = ""; }; 55B218B13024B00100784721 /* FeatureIntroVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeatureIntroVC.swift; sourceTree = ""; }; 55B218B13024B00100784723 /* FeatureIntroView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeatureIntroView.swift; sourceTree = ""; }; 55B219A1302A000100784750 /* UnlockRequestPopView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnlockRequestPopView.swift; sourceTree = ""; }; @@ -1285,6 +1291,7 @@ 30EFF3CB2FDA667A00EB35D4 /* MyProfile */, 30EFF3BC2FD9585200EB35D4 /* Account */, 55B218A13024A00100784710 /* About */, + 55B220063031000100784806 /* Feedback */, 55B218A13024A00100784711 /* CancelAccount */, 30EFF3D42FDA8EF200EB35D4 /* EmergencyContact */, 30EFF3E32FDAA92200EB35D4 /* PrivacyPolicy */, @@ -1973,6 +1980,16 @@ path = MemberInfo; sourceTree = ""; }; + 55B220063031000100784806 /* Feedback */ = { + isa = PBXGroup; + children = ( + 55B220003031000100784800 /* FeedbackVC.swift */, + 55B220023031000100784802 /* FeedbackView.swift */, + 55B220043031000100784804 /* FeedbackSuccessView.swift */, + ); + path = Feedback; + sourceTree = ""; + }; 55B218B13024B00100784720 /* Explore */ = { isa = PBXGroup; children = ( @@ -2390,6 +2407,9 @@ 55B218A13024A00100784708 /* CancelAccountView.swift in Sources */, 55B218A13024A0010078470A /* MemberInfoVC.swift in Sources */, 55B218A13024A0010078470C /* MemberInfoView.swift in Sources */, + 55B220013031000100784801 /* FeedbackVC.swift in Sources */, + 55B220033031000100784803 /* FeedbackView.swift in Sources */, + 55B220053031000100784805 /* FeedbackSuccessView.swift in Sources */, 30A87A622FEE724D0095E7C6 /* CreateBubbleTiemView.swift in Sources */, 30DC185A2FD11E7A0041DCD1 /* WebOperations.swift in Sources */, 30A87A642FEE75520095E7C6 /* CreateBubbleTipsView.swift in Sources */, diff --git a/QuickLocation/Assets.xcassets/Group/remove_member_search.imageset/Contents.json b/QuickLocation/Assets.xcassets/Group/remove_member_search.imageset/Contents.json new file mode 100644 index 00000000..f0dc1121 --- /dev/null +++ b/QuickLocation/Assets.xcassets/Group/remove_member_search.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "remove_member_search@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "remove_member_search@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/QuickLocation/Assets.xcassets/Group/remove_member_search.imageset/remove_member_search@2x.png b/QuickLocation/Assets.xcassets/Group/remove_member_search.imageset/remove_member_search@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..1c1151a73bdbd7150b8b6773868bc7f55fda8859 GIT binary patch literal 673 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dy=L38~T!C~$L&N;}^H;4}1tga( zTLxq-S+ZpL^5rX5tXRK({o=)ofg(Tvlmd!C*lX9W1u|BzUcGYV$~9}&K-icfKv^^? zxEde>C<`$G!iJMT1~MCB2$3SIg8$3{`LHC&FPMRagGWF_LPkMZSw%%%L*KyI+TPjS z-P=DrIzB!*Jv+a+y1u!+yMOZZ>9glAU%h_)=Iy)pA3lEi{N?Mn?>~P2`u*qcznA2j zRWdLz+IqS;hDb3nn>)T;JEGm=|VJF7l^w-(p$aih`|4tj5Rs zwwV|-ZmX?M&d6Mwv?4n^)5|+sG576fLs#9(Bdn=kc3ci>mrf1s$X&Wd(|$^F)A}o% z6F+U)8T6`W;wO`ekX3H+m30?GS9z_lnO-tQ%Q$eJ^t!1DVlp1K?%KrV`6x^A zL1?5dThu1ySGU4@K5h{*u)e5g{UlPl_MX?RwDOr^TOamxoZI@4&v0H!=2^)@m&?appTC#Ra9F>@+QYy->h~{+%_b|nes!n!uE^?sYW{xr+}qsY y#p|zh86LMNNpqn zflzZi;ouJ5n16mMil7FFR2vZp1s7Lm!ZC1MUtdp1NC36Gyc~c)AfQkvy}i9W9*;_; z(&_Z(=4N2k*4Baw6fTzwpt`!6$z%e6wW_L$#bSXYgTa7YQ&R(#%F0SMn++@(fELKG zLKg%;US0=B4u=D#0jr{-0x-A~1OUUy0DuMB0RUYlf+TpL1uC#)6Ci^Y7=UACE*u4p z@-DmuD*vg=2jF^eEYxKT0qz6leC5g%xFK8#W&q1SvPOCF{}_hlmxoE9Ls7o*D@FdI ze_Qg3jIWta+y{TD`w{N=lZXup3W^&yDk&+eY~GAg+p4avv3MOiD^lNlDAf&d#}-n_F01QgWk|N~O{0w-`(oi_Na8 zt*vipV+B>?sdwL)D3Ht{I28W)Gym&b}HZd_dJv%o)|MuPc_X`W378jRS z#NyRe$rtIGVEVuS_*Cj09qb62S`S(!r%x&&+Q(PMM85a#;hsD|(zB4}cedHFi}Ss_ zy>KLVRYHiH+cq~EDJVaJra{Tb%#L{2LhrFisgGN)S$2Co+3=!7BE8e=x3tVbV~A(a*Gjfwq=)yGp+_Qvc9Em9>)2X~{!2&mga6*M2cC|s=@G>tHlr7izQsoJ3Ou7X@ch!>RMXoma=B4Nj(?6d!<9&o3q2| zndyQQIW?)37KaUOMcTIuq9 z6`d1J;w1k5#!oMx&c5(rIC1%UJiDMwHzvQsAc|0kk8+HTRq-LsCU2SgsM^peMBeQV zRN-|BQKMa@uMT`X>UCa!rm$*{kysk+B{FC_&YNRt`js(EZ#rET$j!&85=3 znYM0Bh}mER(W`0BFeA>p61B7KXT!bZ(9#NT!*ODxnN}#iZBgP+`oPDk(Hc`H{TUIY zK*OxCrXd<5ao!@iWs!@;okq2O2)^oGpvy-*p)I$&vox}Vt30kLf;xJ}M9<7Ioqx-` zr^G%X+GcE>xpJ3_-^4uIB4&m%ZWuZQV#r0p7ky+4=gdyZOWeU&)ytxkq`q?0qd6l< z4xZd~`j*rxZ1CXz8oYMGYwW17;P#-6aABY@b+956<+r?HakdpBqNg-l-qTa;zi->G yaM&s&H$0+oS7+0#3dY;xrjqf6i_h8Xoq~FarAcwRh7f#?2*+c1hidzP#J>Uf>Szl9 literal 0 HcmV?d00001 diff --git a/QuickLocation/Assets.xcassets/Group/remove_member_selected.imageset/Contents.json b/QuickLocation/Assets.xcassets/Group/remove_member_selected.imageset/Contents.json new file mode 100644 index 00000000..4cd3c3a8 --- /dev/null +++ b/QuickLocation/Assets.xcassets/Group/remove_member_selected.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "remove_member_selected@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "remove_member_selected@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/QuickLocation/Assets.xcassets/Group/remove_member_selected.imageset/remove_member_selected@2x.png b/QuickLocation/Assets.xcassets/Group/remove_member_selected.imageset/remove_member_selected@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..7ce66406865d87f70f6cab3430fcdb282f44ba4e GIT binary patch literal 574 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 B?M(mx literal 0 HcmV?d00001 diff --git a/QuickLocation/Assets.xcassets/IM/at.imageset/Contents.json b/QuickLocation/Assets.xcassets/IM/at.imageset/Contents.json new file mode 100644 index 00000000..04ec9aef --- /dev/null +++ b/QuickLocation/Assets.xcassets/IM/at.imageset/Contents.json @@ -0,0 +1,8 @@ +{ + "images" : [ + { "idiom" : "universal", "scale" : "1x" }, + { "filename" : "at@2x.png", "idiom" : "universal", "scale" : "2x" }, + { "filename" : "at@3x.png", "idiom" : "universal", "scale" : "3x" } + ], + "info" : { "author" : "xcode", "version" : 1 } +} diff --git a/QuickLocation/Assets.xcassets/IM/at.imageset/at@2x.png b/QuickLocation/Assets.xcassets/IM/at.imageset/at@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..51d41bd9b884ac6c863e7ba1a918dfc8f58802b6 GIT binary patch literal 753 zcmeAS@N?(olHy`uVBq!ia0vp^G9b*s3?yAI>n{UR#{zspT!Hlep$`uG%iaR|#IYpE zFPMRagGWF_LPlOeSw&r2-@w?!+}hsR-P=DnIzBl)zqq`*zPY`-fAaL%^B1pPzj^!a z{fCdAK7aZ8?fZ|PzkdJu`|r0}T!IV?j59r5977}|V-I#aT}ohZcxWu~LS^fohAxdo zs!H3RC@~-3|M{Q(RkvkVzkhtV#oTkVO||U3cc15Zuaa^lEGA9+ zLNwQuaFotH)E&pnd^T&!vRjQF;v23NcNFhkCX!mk5IXm882`ehk*$})W0~Vim>i`G z)+d+k`o$9S+BWA4%dcN2&V{URSUK--kbc4nTd&@j*B7pYvM~SUt9={Xv20gE)vDYD zi;FX|r#Y0av74y#rPWFIh2TfG>;3-uV$;q$UT(SMalByW?#+I>OWD&it(x5~SZA!e zVsI-vO-gR{Nw<22@+|g6lTWAdcAVdLbk4fcxP=B`^Iz9=$v5v)o1*1xD!(Pkt9p9# zf`2`g<(^V!!+s>MFu)<1tP-i3MMW`1Cd OGkCiCxvXk2`Q8BS`@d=4Z$tkI6=^2?>**UrS z1%*Y$C8cHM6_r&rwRQCkP0cN>?H!%nJ-vPX6DLicK6BRWxeFF9TD)}G@)avrtzNrf zpipFMx^^404%Z{NND z@aglHuiw7^`1$MipTGYeZJ)J(fr0s~r;B5Vgk;@M9#g$~Ukl}yuKS;X+- z)YK;||5i=xW1ilfa;Av6al4M!toMvksSynClU^znJWTYQHaGA=kF#br(*YsLod?#o z2I&`6%~>)>tf$iJqzzMxjFA`P`I?j5b1DLY3e7J}T{wl)o_TFowcw6_OGMcAZSt(r zVUfAgktz2eS2DA@;WXb#-Yri&RvoMGResfwu#@Mx>H}#{*#rHLRj(#r$#7A=U>JDp zQ1pSN4Crx8l+!W=e zE3kU%7bds8LOR(s4a=i~uKGUM?j(7+=0Kun@PC$FpHfn;RT`}G3;mU2ZVsk%_o@%bV z#r(xi$#P$B(d_SPniD7c9nYJ7y42%T7L(KOoJ&vio0ojq^CxWr%l&&oxiU<*R7821 z{*|jfUGqvk??bmy_PKcs0(O?_!KHQwVil8X85XNWPs)9{t$BA=ZkKlS#+N^hUN%mR zQ`lkZ-1c`fhryKxS8AuoOC8EM7kX$(ykXPx)h1!zw(T=Gw$Ns&&kliO9ouv@&TZ5< znWbOxYOdp>8u`@M+x{psK61LNYi)i-f9CctQ$u;tlf|;^81qGq(%SvDsAh3 zGaF8FnlF~!vuE);f#lY^>Z?lDe~Fy!$7|rVmJWavAZATyEEr?C+cM<08185@gg zIVc!7$Y@z=XgI5>IVfm3s2f_V={u?DIVfpa1En+!98`6kRg9gKjU1HpomC8-mGvBy zO&rvXoK+1RfZ`fPj%o(ZKrI@E&Kd?z>L#vg#tv%6E~1Wr0%0K=mN51_%Mo1Stbr3gQA)0xdNLiZ}ypzh>m_0rYcVNswPK0}~4e z7Z;C!kg$k^l(dYTf`XE=ikg;=j-G*$v8kD*m9>qHor8muvx}>nhnJU+Ur=yJSY%Xm zTtZS(N?KY*R(4KaK~Zr@X+=e4Rdr2W!y2hQix?OfqdZ+4LnI{c9?Ud993aAa;qn!M z;FXG|BCeWJT{FBgdkjOW|NUQ|7+JgXJFBnVZR!7$H%or|u~axg*Q7}c<^Axe6q=dGr>`HZ=f4Njd&5p|n7GbAy`U^1^n zYFbcRU{X-Y-L4r=4$fHqc29$Tt6J`7gJl^j7p?a?Ey6Q>R{sqDT%KbbQ#JZ$2nR~G zJq-A`@XAVyj@p2V051`F0e=x!jm;wG1-^@@YIut%9x-)g?()Cbv|~ZXr;exbn&%Yy zR>~-rIXq=q#FD3AcfgS&(hv)KhgvPZ(Ho9reKu5gMPtpuWgK@ld%AqYxs@j!5@ z)0Sx+K(WDEFT@I#QLEHaM3JBlA}Cr!(h4)yR%AM*Z)y9@x9`pS-uM6gznM3)`;ro) zd5&I=EEbEWiJ?=#9>aW#*h!@VM++4g#-ly8nDJy|G5(Y$jD)w7GeNMiBKi*f>5R( zA{Z1S$JM}5C{w|}kpRpEAf|#aMg@Ze!+?Qtn!$o0K@y;u!GdJ4K#0*m`#*321uEc* zpa2kz#9S@NfpDS70N-4#tpX4ExhW+vm1SegX0z?=Ih;j{9UL8&!_(Wx*Y|xtzJGvVg%A>nU<3&a3n{sk<^R{d;=I3wSR!~r|y|Adr zWGddVqolN~th{_@MP=o#s_Mk62OqImw!Io!k>=s~>Uv(rk{lLi0CK|`nw;GN_H<6@HW4BF(kOvy@qx=-nqBw?1{5k$ri)!t%U(c3NloE7kgK zU&!O{+D`Z?B@x@gmWDpx>E%k^cw&$2&+&SyE6qLJ*mJz^X~x|k-sUS$A0~K>R%>-r z`oM~Pb(R~Y++BjnDg8zrw2c?wu?PXFU)75H#P{s_2T?(->3I$eHey(0|(1z3$9U5NnS+ zc(>f-vggh%Z@Hx9zD)I|Uy0d8BmP@TJR3%wlXZt}mW}XZZ%dlKu%nG*192Up@{Ci1 zaWdz7R!!qXbp3DESEH2%T-)Az-*wm}_sApH9`}3w^1L_KKF*!k;B};4vHf&>&6Pm^ z{fCk>JTLOkaRP@n)G3Bak9A3%+>8gieot^+J86cC$@8b^{^7;+c4x~kH-FsWh?aEC#;q32H*A}pS{mq ziJ4s=1xXY7^IZf{mZ5lve_%d(LwS_lua=?iOa8{j7RBZ&E^+>EF7ISk!`=%xTt7cp zJ5Nk^uWr`J?0T^BH5H|WZ^mt-B6nNe*qwIw{kR5?Q^DL{a?C9&I1<0TFSMNPHeGdP zbE{`)OqpU iU`8@FNWU(}=MEZ;}bI(7dFz@34 literal 0 HcmV?d00001 diff --git a/QuickLocation/Assets.xcassets/IM/emoji_input.imageset/Contents.json b/QuickLocation/Assets.xcassets/IM/emoji_input.imageset/Contents.json new file mode 100644 index 00000000..e21a556a --- /dev/null +++ b/QuickLocation/Assets.xcassets/IM/emoji_input.imageset/Contents.json @@ -0,0 +1,8 @@ +{ + "images" : [ + { "idiom" : "universal", "scale" : "1x" }, + { "filename" : "emoji@2x.png", "idiom" : "universal", "scale" : "2x" }, + { "filename" : "emoji@3x.png", "idiom" : "universal", "scale" : "3x" } + ], + "info" : { "author" : "xcode", "version" : 1 } +} diff --git a/QuickLocation/Assets.xcassets/IM/emoji_input.imageset/emoji@2x.png b/QuickLocation/Assets.xcassets/IM/emoji_input.imageset/emoji@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..293206bc69561095083cbbafe212c81cad83a2ea GIT binary patch literal 1320 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 literal 0 HcmV?d00001 diff --git a/QuickLocation/Assets.xcassets/IM/gallery.imageset/gallery@3x.png b/QuickLocation/Assets.xcassets/IM/gallery.imageset/gallery@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..d8dc80a5bc5d784c9b421c236a29c28439c4c079 GIT binary patch literal 1327 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 Z_J3GQSHnVo>}LP~002ovPDHLkV1m2gOe_EZ literal 0 HcmV?d00001 diff --git a/QuickLocation/Assets.xcassets/IM/location.imageset/Contents.json b/QuickLocation/Assets.xcassets/IM/location.imageset/Contents.json new file mode 100644 index 00000000..ea76a428 --- /dev/null +++ b/QuickLocation/Assets.xcassets/IM/location.imageset/Contents.json @@ -0,0 +1,8 @@ +{ + "images" : [ + { "idiom" : "universal", "scale" : "1x" }, + { "filename" : "location@2x.png", "idiom" : "universal", "scale" : "2x" }, + { "filename" : "location@3x.png", "idiom" : "universal", "scale" : "3x" } + ], + "info" : { "author" : "xcode", "version" : 1 } +} diff --git a/QuickLocation/Assets.xcassets/IM/location.imageset/location@2x.png b/QuickLocation/Assets.xcassets/IM/location.imageset/location@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..21867da8d7c80f1d77335cd5855e692a0c111d49 GIT binary patch literal 737 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-sPXc^GT!AzgIB02UDJVEd85@gg zIjE~!tEiYO7&yr3+Q?{Gsu??|7}_f9St$Ue46T)nt$|Xiy3Wc*4odpY8v4#)1PF6LhK{NR4l2e@>V^(#2F_~wPAWzY8ivjq22MbgYDUhghE5s=4jKk78YV94 zMowymuBwL4swU1rEgC>%1Qc{uHF8!rbW}42G8{DwUDQpS)r}m1dO_x!xM%=%fm8ym zb_TN5je+7o5oe%wpaP&`psc#F3rNJoC1g^rB+!#SB|(0{3`{I+99%rSd;)?(BBEjv zQgRAPDr#yPS~@y<`UXZOre+qFRyMYF4h{}Z&MvNQZtfmFegQ$jAz|UsaS17DSvh$H zMI~ir6*YAYn{O^Z$iTpu;OXKRA|ZM8;Onqk4ic;vgnbr^h^|$La@D-$wo!bQ)6xgM z2`A4~{{O!5^wC*AC;71b+hu;Q^KG-A{<|%9Y!Qx2O}%!0$iKq%ApGS%1Lc=t4?b!p z9{jB56?@6`cma2t&PQoK`^Z<;GPl0`=xOSmBKMi2lDR5YdHJ%JOO;Z-YWmj8Z2cYV zWt*b9<%(y+|E6Hq?5-Z)s9lY%ZOcMiOMG67_hd)0Pxxi>#j1xlDtyAf3l&WtT#`95 zosyXnosxN8&O4^u!Y-BUkt~(P>$W2EPiu+yYVOC}Yo$G=Z+RA~b0sM1zQR@wmFSAi zlLKxviv(S2{+pFsze3}MfFys+Bf-e{okuJ;DY@#)Dn0LuV}5e=<>G7&i3^X#Tqh>2 z{K72b7qNfM^sEqaq-Z!xRLSb6{LxUq|r`00P*xsb|%(?g7d*__r_r19@caI@S zFZA^F-tWuzn{A?Of-7UTLL1&69Q0D%ad6lWzEBLf*0Bcnj-5rTzr zCRhp9oP=a$B#RO>q+lS5fk;|L(h{6SaTdWCSOFj`gzFKELnsa*SqS5R5K21az>JbQ zgy0aIg`K@98H19XlmI{$!D$57AruXh91I!>1|=9s$)PwcrC5N1Nd_ipnBZWXg-G3d zn#0?B8V3PyB#RJ?lg7am=yEnX>j4c&BY=i82b1JXbU&=8V#{3!uw;E(~00QEl& z0D)~M&7lj{z%cb6#NifpLYyZKt4)D?Gq}`_a$}N-=fW2V1g`Vk+}u4p7c3MC7cKT$ z;=R;Iw0y-%-&L#p{QLs~Rf~MQYyp4BO=vN8jY4= zS&rj$`q;Sm_=JSS#KfdzgCQlwXi7DkKS)bU+mN1~k+Er0W>!{qPHt{)UVgsCvbo@+ z!lEr77nhWjmX>YZwynJ4lkJ~=R#{oKqq?Sc=gDi;2Y5VwdmI~+x?<(@)iGvWwx8SY z+bu^;wi~!4L7YDJw?y_i)z>QRYitU!u4$1TjLJQHv+d7!=QfsOHNQn{{_$YDyfWbC zG3*y*=1f(@>vtb!>hJb>uWSDHVwYx^e`Rjf@l!8H&RmI(;T{hyT3X|JVZX&bkknkf zfL@<<$N$o~URH2Bhpg_hHNRbG4?mc{q)q9gy3*(?Z$tVoe_`9b(Kf&2>DGHKMfFFt z!QV|U{wd>?sxTq-s(CD`ef)VlG_mEpo%zaBPM6J%x-WmFtiJJ}|4xT0b!=*&enCd_ zut{ka#Dt$d))`b$QRP}2`mj>W4YJER&TnXKDT>EVm77{dUqIoC-jq2XX4gYF{z$*! z&@h_!+RYI7jf%-u@XcIHzjnnx9vYh>z*;zOUR6|s(C19P;l63sug+^OCL2!GBNNug za;vEOmhqy;Am=&U_3Zd<7tY-(@4ken8;&38FY8{5N}kdR2=%M)u^RmwCR;aj_M9LK zAFqB=6rbMNH0IOiUWa(8J5FQ`clOM3Q$_xs&)+0XjRbW+`2mE2h| z^L%!wpe@BHnpC&ip7pu7pB4G1?Rh(SVFtDjto4Aut{JuE2|JFyu;2aF%g_H*^3SCf zXlmr7%kt^Ju0_vRjns}d{vj>REjN8xZCSL@Tx0hhN7MLt-ODWK^b|8+eRjl{ zP)J=~IW3~nrrny-W}AFBwVvo6C-=sOS$7YG?2T2?jb+iv$#3pv7hqNP!5ORz^|m$c z@;GlkaNB&DA3ZQ+&k1qM%n_H9-u20c80E6p2I-Ey6Sq>XPbe{AmmoP*bp6$X_M?Zj wZ)RYTEid4H>myA_fqF7hJyDgt-u0YipQbWHL-rOA@*Qtv9GArQ(ph!?0%#S|SpWb4 literal 0 HcmV?d00001 diff --git a/QuickLocation/Assets.xcassets/IM/location_pin.imageset/Contents.json b/QuickLocation/Assets.xcassets/IM/location_pin.imageset/Contents.json new file mode 100644 index 00000000..7ac2b095 --- /dev/null +++ b/QuickLocation/Assets.xcassets/IM/location_pin.imageset/Contents.json @@ -0,0 +1,8 @@ +{ + "images" : [ + { "idiom" : "universal", "scale" : "1x" }, + { "filename" : "location_pin@2x.png", "idiom" : "universal", "scale" : "2x" }, + { "filename" : "location_pin@3x.png", "idiom" : "universal", "scale" : "3x" } + ], + "info" : { "author" : "xcode", "version" : 1 } +} diff --git a/QuickLocation/Assets.xcassets/IM/location_pin.imageset/location_pin@2x.png b/QuickLocation/Assets.xcassets/IM/location_pin.imageset/location_pin@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..c5262f79a46d98a88b146cf0fa2337c414ec68e0 GIT binary patch literal 1010 zcmeAS@N?(olHy`uVBq!ia0vp^Euha|NnZWz&xkd zv6q(2d;hEc_{4wpnMHefj=8ifI_a}7Vx9TyuSJIQJ>8srCi5DHKeS)*W#|ZSkJTUu8vi zyuQ>)hG*{boNkV|J?Rn~ z|C30;BfE+`#ccvoQUzY0R;~TuF!QQoj>`0&1I(q@ST?SVF=FL6$y8BU?`*W8UnJOP zQjSWd|0l*tQA2&sZ&xMm*0$YNogRT@<$uuO6g@?hfZOsOq?{@}-vX>(-c-{h>z=DfCz z&%f7lTgu1RUkb8)xAIqW9$vPqV2=)SXYA5{Iq?$Oa$=LJ-Crc#zAb1tC+7U_puJ_R z%JU}ec)0D({t)>)e9G&z4|ZhlTK!Wl;UN7D<6G&^~$JF b&;NJ5ir3?x?Y$y8pzP-9>gTe~DWM4f@V3SO literal 0 HcmV?d00001 diff --git a/QuickLocation/Assets.xcassets/IM/location_pin.imageset/location_pin@3x.png b/QuickLocation/Assets.xcassets/IM/location_pin.imageset/location_pin@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..3a83f0f13c2e9344943262a7ac3f5abb8f829e0e GIT binary patch literal 1789 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 literal 0 HcmV?d00001 diff --git a/QuickLocation/Assets.xcassets/IM/member.imageset/Group_1613@2x.png b/QuickLocation/Assets.xcassets/IM/member.imageset/Group_1613@2x.png index 6396614f6305f0df32f120c08277250163782e30..4f58035d81ac11f87e7b7b6920107028b078de8c 100644 GIT binary patch literal 591 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-s>jHd2T!AzLgM)&CgQ%8+f`NmA zmV=6(gNA{Fx{0Hjp`(V8o2s#!ma&_ecHvZ{NND@aglHZ$Ezi`u*qczs;9xo?&2M6!&y-4DmSrc4~C+Ap?Qd+g+^s7sO1X zR20lTR|jdTW&ZmwFPzGiv-RfN9{#?^l{Uru+VAF+$v%(Y@1?u%(lR%#$7{3xDVc{o zjh*p*siR6Q!x^4cnhZrUHy92Gq_Bp3+nO%sz;AQhveQ&lKwD8ryVLL!7BC@KPpezZ~qmHh~cXoZTX zAX=cJ$R9!bMvIjZ?MA7&=e*9na}~AgIDL;{-o59X@1E_RC)z`3fP_0)j(113-1Q~X z5h|0pB2mPHKp3a+4t3-qg0HwCm!O-Gj6frK{5y?79gvLcjUuXZJ@t^+^iRd)C~3G0 z9g0fnjyo&{O|UO+XhRS889Gjb$|DEXwp;U$sm)+Qku)b z7-Twhk(6Pne`K@Q(Vcbe5Ft;CUpX1A_p`dg-@ubF~W`{Txa>iydmcx3X^P?Y}lj-W_%lWu%$PTBcw5>~joH8U2v6`Hm6g`&{ ze93{)SWXX&;cHBY9*P1~Y3)6&XwVB+br?Tst*?j0+aAcrC#~@vp{ABVrK+Wy+pLzC zBoAtDN?55~U@YC&UcJC@a~GCTBe(D)^fD^6lp>0T$5u@EheA`)(P&49JE=IBYC+V+ z!Sq(8*O??bL?{CvRXENR{CxXZF%o$v#Oo5P*9luu%Jl94Y^9Ee1##Js)%qx$bI}0adP4(ax$pKRi+x; zWvXF62)tpwA3R{=1}Eb=6WxziE~}4x74+~;;1_Wx@W(fPB*+VF`mAYc$r*H%`#q3P lWr2M0UvOto1y;7+`wIoduQP?^;LZR5002ovPDHLkV1mlo&zt}N diff --git a/QuickLocation/Assets.xcassets/IM/member.imageset/Group_1613@3x.png b/QuickLocation/Assets.xcassets/IM/member.imageset/Group_1613@3x.png index 7cbba75d2bd19467fc7d7cde1f657b2b5cd0d44e..02fabeb636702572aebf7ceb01a68de9f6e4c974 100644 GIT binary patch literal 1268 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 diff --git a/QuickLocation/Assets.xcassets/IM/reply.imageset/Contents.json b/QuickLocation/Assets.xcassets/IM/reply.imageset/Contents.json new file mode 100644 index 00000000..59d21f57 --- /dev/null +++ b/QuickLocation/Assets.xcassets/IM/reply.imageset/Contents.json @@ -0,0 +1,8 @@ +{ + "images" : [ + { "idiom" : "universal", "scale" : "1x" }, + { "filename" : "reply@2x.png", "idiom" : "universal", "scale" : "2x" }, + { "filename" : "reply@3x.png", "idiom" : "universal", "scale" : "3x" } + ], + "info" : { "author" : "xcode", "version" : 1 } +} diff --git a/QuickLocation/Assets.xcassets/IM/reply.imageset/reply@2x.png b/QuickLocation/Assets.xcassets/IM/reply.imageset/reply@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..974e36604266b366eb946423b2f1d173dbd86b49 GIT binary patch literal 563 zcmeAS@N?(olHy`uVBq!ia0vp^G9b*s3?yAI>n{URTLOGST!Hlep$1-P?^6W2+qxvk zFPMRagGWF_MnPFcU0X-r*xcUP-8(!wJ~=%*zqq=&y?gTX+4C1KU%h_w_TBprA3uHm z^7Y&IA3uNn{`2?Wt4hxH0*(3X>Eak7A-VS8O{XRY2G$GKEw`Tu;xU$OoQp(HwkA2jah<(3kaxQa5w1uGJ?6B|^zCW(Fw|dQg9v2Y# z`OdwzOHWmmHSG4=FTUF7D=1RP>sevwD;;vHd0{p)Kl{8V0d3M=M;EcCpO0em)QPa% zQ4ksJJZrpuQJJ@+@OzJFcQ*M`w3WZ(sk!Nt35epEY~# zf+b6rtysNg-TDoix9`}wYxmxRhYlY(dhGa#Q>V{exODl-^&2;D-@E_l$PExc0Owz)o2m1}als=_T%tf+m$Ni3RW#U5>)j0?5T|SBkE5>dK$RCTP7!X>(XJ-;ymV znO9h9(yqPnTXJ_%=Vu3b<0W|~sxlwRT{zk!u6JVI1sC%Ro>wz?uf;6yEIweoZlc;Y z$BpGP-L^WkY&zm>9}+s*q(XT?+#;Qq?rm?Qnk=W49lqpw)Gj4-|MEDckfu`{qRSUN z{OvaP`qKl~G(;UUa^=$8jP5;m@%p>_{*or>fb-! zh;0|;%66^pNnwdfUGH&h{&l74^#x`7WTT!c$4FW{YMNLZzL+`csQLbF)1m?{*dM+d Wp>g2*p6kHG%i!ti=d#Wzp$Pz85;K$l literal 0 HcmV?d00001 diff --git a/QuickLocation/Assets.xcassets/IM/send.imageset/Contents.json b/QuickLocation/Assets.xcassets/IM/send.imageset/Contents.json new file mode 100644 index 00000000..2e0394e3 --- /dev/null +++ b/QuickLocation/Assets.xcassets/IM/send.imageset/Contents.json @@ -0,0 +1,8 @@ +{ + "images" : [ + { "idiom" : "universal", "scale" : "1x" }, + { "filename" : "send-2@2x.png", "idiom" : "universal", "scale" : "2x" }, + { "filename" : "send-2@3x.png", "idiom" : "universal", "scale" : "3x" } + ], + "info" : { "author" : "xcode", "version" : 1 } +} diff --git a/QuickLocation/Assets.xcassets/IM/send.imageset/send-2@2x.png b/QuickLocation/Assets.xcassets/IM/send.imageset/send-2@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..4548c7a881f00081847728f1a8f42ad5c735f191 GIT binary patch literal 498 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k3?#4J%UA`Zx&nMcT!Hle!2!ORXY>MHqgxW> z7tFxI!6P6dA)}z8p{;Li@9gd$93GvVo?qYG-aUQx{Kd;xuiw7^`03}b-+%u8n{gVa zFHqwvPZ!4!3CXhuUq>}Lh_GI;ZRkv8>(fkKxbWoD9ryo#{q@A|#D()w-2acA`EGEM z^Ks9UR90zq8<90J;S!Hq+MDL)-zhYYXZ1CfxZ|s|=kelnNpYFa4c9)oTz+{dsO_3x zM%RN)B`%MrG7Ac9S`t`XG)qZA;9f`jt)^uh94$*(c&BdCXJSfpUA#5zyc|c1=*J6@ z;yGspIkGu_{rPd~)=%FX7Yua2X|^9ZJb}y3NJ^+DF#20&PmrYbqr^Mv)|@(VH!f}n z(3IZEKD*p3DZ+NsN1olv+UY(YTFpPTXe#EH%~)pqEc%bzS{OJ8$$p9 literal 0 HcmV?d00001 diff --git a/QuickLocation/Assets.xcassets/IM/send.imageset/send-2@3x.png b/QuickLocation/Assets.xcassets/IM/send.imageset/send-2@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..574604c3a5912a84a3a3cb9b113f1cbf84b012b4 GIT binary patch literal 1050 zcmeAS@N?(olHy`uVBq!ia0vp^W+2SL3?z5Yp7oxAfw3^aC&U%V{XYum7y=zll{0~X zUR4t07tFxO#LU9V#?HaX#m&RZFCZi=A|@>>C$FHWtf8%=tEX>ZXl!b3VQFP;>)_(* z;o}z=79Nw3l9`oPP*GLi(Ad<{*51+8J8{y~8MEdsTD)TI`psLm@7T5X(BY#ePMtn; z?)uH!_wGM>{N(Ag=PzEqdj00pmv7&H{QCXp@4x337Sg~ZaL?1lF+@W0?ZMaamjW2r z9!&Rid^lsJX3#XT%&;ukB%Z#vjY6S+nD} z-wbHG|6r2$(o=^vc7~eSwEC}7Sdn&IVAtuk*ArxGeYbY;F8D9``i@G9cXY_A8-@o; zveulAoWK*ZGVM5nv37*I5u3{Ml_47$kH{WuyCjmL9I_Iu=+4$O$FwIa6F`b~s59^H zJkRs#8Ay?Bl1SY|X;rp8HcT`8dMDX5@%gN~{QhI&j7Z0uJhQ&qYP}2iWL%pR8SqSP zp@3cS|I7MbHou&|J52s+3@X}+I`NaFR-7A zYgwrJYr>|?j9FznpNp2bPTzUjmOZ!jeuVlv*9G~Pp4zuMmMG5ocW(c^r5C22xVb&0 kw2$e2{F0jN2uyDbp00i_>zopr0HR=_TmS$7 literal 0 HcmV?d00001 diff --git a/QuickLocation/Assets.xcassets/IM/setting.imageset/Group_1614@2x.png b/QuickLocation/Assets.xcassets/IM/setting.imageset/Group_1614@2x.png index 30e5d7ca81a20b6b0db2661c8411f9c1ba72a6c2..047f032ff0027bb62077bb441f580e0e72395c42 100644 GIT binary patch literal 581 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-slLLH0T!AzLgM)&CgO-+qf`NmY zv4et^gNmMmhJk~Mv6He9NJPujQQ5>n)xbf+$W7JQO~cex&CpfL&{f08Mbp?t-NZ%1 z*je4gO~b@h)5sOX1tKF?O=DLLV^>WRpfXpW6o_pMR0)#R1gQZ_0ZFhjkOGi6NYKXR zhBMGn1|>m$!3-=MJOUyTG78En8rnJr#^(0U&hFm+@yY4g)%BC7&tJTJ`RetXx9{G6 z{`&3vkH7zBdN{wDfq~J`)5S5wWxD(9e@AL&-)Z` zt6AX5p3g_m?cq|~pY8FFchQUd;2F(t2ByyG!(V>Mwj-^Jaft8Vs>5RgIt@ii*TrO#< zs6RX|yu(>~(vwoJZ*eYne70yR#&*8gxMpF{v9AYwjy>vYo3bcY@$kdg000A=NklB9S1L zh#yGD9>fv}LIsJPA0lY!LZZde)sZySjV}G1d#UnXdCI9&Rqi?Gedjy(EKh`qOElH# z?$=-hJ;6g~p!l*V3)?8^dQ{_3TIckm1bO^v#9Gxg$HRa9gtgS*dT2tNf1jbs>STAp zTs&7El3)n_e;~(-aB)j<+hrFzBmeocD^4>D?Ovx?hdZjj97i=u^Jr2k6aXtYY64Yg zr%zTfR?|zR0h_S{-L%dwVTR4FCntmhEMe2tXn{{tM$<9VAI~mjxEJJv0+53wlD&F} z9O4XD9&U4xFe&>P33%>rxd2ef05!j~2{p!`)`Tra|3exSOngD?^;#wp|LsRpXHiUl3hM@CIxDGG%Vs|Z_+Q!Td8dfXre z!OnDYRwt^alrnuOD+Fo$D{``bc%0E%i+y&<`<9~h`YeZjycrsVjq)jn*eIYQ&Ce>< z9@ag=kLmM}Hn_-%><)U-DrRw0K*y>ISPD?Xln(?TSL*o;R!B}E4=n5vX8}yq11|8GuVPBD_H>wa_sctGH2H`zgZ&~ekiu*ZeM!i>jB`l#_O~ZZ zGLye4T@}ovx8$KRz_KS!u+M5Cx0=RC(M37f*v!3u*ak7Vh-Tv;S~-C|R#ArhNQ&V# zv4=B|M~E)rmD26fD92<9*%_x;XF9|{?R0*~@LQ--4EPuqup;_3Dg0e7H-&lw9CP}KFN>@|0@tMN*Wq6}j|JszKlOeGIH;0p__0Gx00000NkvXXu0mjf Db*{&S diff --git a/QuickLocation/Assets.xcassets/IM/setting.imageset/Group_1614@3x.png b/QuickLocation/Assets.xcassets/IM/setting.imageset/Group_1614@3x.png index de9dc0e47874e18dd400b2c7ebad019b1824aec0..63881e65251f250e2b770a424053aa2a0e772134 100644 GIT binary patch literal 1300 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY3?!3`ol6-Q7`FxZgt!8^V9>x23IfK)#wseF z3Jwl3mX_jrZhCrdT3Qb3*4FCQeoDqJ1_lml#=csnUYf@4YWhwp=AL@yp30_nI;L(K z1`Zk)9_nUpdS-5_CeAv>o*HJ(YQ{kIZo0;9Iz}#9rtX?1Zt6xJYKHD=X71XC?y9D) zT0mstsbTJ>X5g%5>Y;7wtYzY^X6&M2foec1U4aTf#+teS)c|b)vO!va>cLzMpu>P%pj}`okTW1^fO>(tpz6`tK(|4a zK^P!gz>2}TKrRGo1Pg*3gD?c_DHIW~O0WX``V~FEXq#9PF_9}pNE8XgfD6`PQd zl$?@VTvAor(AeDE-rm*S-9K^Cj9Ig0&z`$@>C)xPS8U$AYu~V|J zzjW#Hl`Ge8-?@AL(c>r2UcP(%oNm;y|&QB_2~)Gg%`J4dbfLN&wM#+z4pnT_jdma<8H@&wu!ra zd2@XBd-F?|F8!0d>6dQD(pq{hXUVyYZ?m4&2tRsvR(H1k`cx&;ZL3ZSd|!L_l+%%k zyX|-Ce>sz=z^dA;w%E>Epzs;@Vy3@OFND41Hau3<)iKi`xlCMp;mV9grt;FbcQ3<5 zYBbvB^(nAETrd2%Ta5K!S%zUu2)F%-7QVx-TR+skczJ8#rT4clJpSRhH2?U*mxfc_ z7QU96s^<_cIhE(ds)d&-Gd5MOFiB|^`+dQTRsOeCG<%xnkE`V(S(2<*W$(TVmAg@0 z%O}|T{(D8j)w{Q&=65gg^UDu13u~OwWq9hEEuYH7$6GaKZ&E&I=Q{JLtB|ct%1W6g zt;y|M6gNtqI;70TvMsQCleotj_nXIfJ)*X0d{#8HPkk2YAr+?aSsBP|44!aBH~5)* zQr)RADTST8oMy^*{?xdg)%fHXTdJMPwp-jh*z_+d@(Gfh{YqY|mJFRM=s$*av?UplHb5)nPMn%x9+2L=OB`oBa zr6pc2ne40ZXy?%x6V?meI`x~m=T`}n;MVz)seIEESl#Zrbo{=Sm!_oj`kK`DR<+eR z9=^}Mnm_w=NA`&6+1bms-*kAjX>Mt&z!U4aH$A+6pZ~+C_d%2|{pt8-=)z4*} HQ$iB}Hwou? literal 1471 zcmV;w1wi_VP)U7Jk9NFvx zTg|pc)W88s_F?(41yM7mvsDx*G2GS34Nx%ZPJ!gZ@Vuw@-g~^fFV}PadH4RFk8{rR zoZs^t#cCiy&7>l=6b~qIGUiLv)}Rfe@Kd>(syLLGN1U!w1v+tSYM!B0kuH4kRF1!K zi_Z}>Qc;Z7^XAen_%SX_OyUA_hvVvM^ctAJuc6MJHACY_(aLaHsE#9m8{+$Q&jMF6 zQq)IjzlmPQr0J$pTZ05!^X@DT_8MJ8j?NFl>{*W1gk7DOka20PFt;HYa|L>+WtOfypa=|OKIb2lNaT>#>nPGHk zWufCh4mAk0E8A(k{zCL~!PjIY+ll9?mRhM5jo6AD88`MwpDETuO~o(V!J#Oi!AcP*H)C)8ltf|K#8Hn<7PeRWiERC?i^_O zc7h2w#)H)sql1M;474|_S;;{~805ivH#P^0W{aEBjT{TH+;sY$-_jsRiE-dnaoZbR zX)-407mIPmpe}aQD+zg%^hdN8r~&PCi8W!5t|CQoL{f~&U(MPwZN4kn47i%AF_h2; z2nd0zsxQ*K_AsmD>=~LvtX5a0=)HnrlfYZ3hW62-DL~J_N%UeU#ENW-5+_}vc8tkf zgmKnG%fsbd$#lX*L&rrm5x*|5Vkzv8;k-cqMGwx?Irz<$26Q#Dim-j*OU0;OpqNzL zgJ$ezxr!r_I;dWh9Y1YjxxRSC;aNbN*jW*++NDmZkglV81WnG}qKMCf?ksKoogAYr z!-!aGK{%?rgo`0vl}oK>UcQU1M<2(lgag_>P4c~I?2jtsT7^>l!?E|K(LBJ>AB6+0 zEV`H|`u!-B5!{Ckj{O#0Q!C@>fN+44=wc#!E=DQn4r=1qm?b++a1#~|CLlYIi|a&m zO|?L{r+}3M!7zQaL`Gc6_?=^Z%N=yuIG}2d-elY548ux;7U}(IG&gh27KJYHkG<}D zMV`pHa+Bk2SS*FO&L9PCSu|GmCgCu5U#UBkUxL-P^jogJiClQc%D~`FDU!Y^SfxqzKQs>l$X%*^l z3Ox|5E*~(kO2!{j8dRlt}YSovfChL_jO{rcG0sHHLOB)Tw4hue^GOd4RI+6A1DsK4V$* z^`~%^Z?jy9afrIISIR?q_~LO$w2m=8Sd1d1XV{9O&>)8x*T01CyH&9t*-oR_#pZxL z&9%Omk?`I1rZe6FE$5==rfDqac$1=~pq6heOMl3IEuZlF+$8@;4sE9WRE;X^(7f4B zIe{_27gk{(fe!JU+Y&N@1g#8R7&d9351-3@H2Z;L$LyQfpG`AgY77bd)w2_$kh!Rh zxrO^Vst+dxlU3Ru(bn*1DOKoC@+%~su{eM#{3>`Upz6MOdYnGSkik#v$P6Ci-Xy$@ zU|6p=V3O~CEc7LMlky+L9`UCGADKPtWo%r0kELnp(JGvX*{g2~m&kX+A4c4RIGiVO zlx?u-Ih-;H{G#@(FFum{wRIR05Av_62nkBe!;zcL2|UPZ^K!X)IUNe|4QoQFH_htV Z^dDjKf6!?4OuPU9002ovPDHLkV1k|e*eU=3 diff --git a/QuickLocation/Assets.xcassets/IM/voice_input.imageset/Contents.json b/QuickLocation/Assets.xcassets/IM/voice_input.imageset/Contents.json new file mode 100644 index 00000000..9832aa90 --- /dev/null +++ b/QuickLocation/Assets.xcassets/IM/voice_input.imageset/Contents.json @@ -0,0 +1,8 @@ +{ + "images" : [ + { "idiom" : "universal", "scale" : "1x" }, + { "filename" : "voice@2x.png", "idiom" : "universal", "scale" : "2x" }, + { "filename" : "voice@3x.png", "idiom" : "universal", "scale" : "3x" } + ], + "info" : { "author" : "xcode", "version" : 1 } +} diff --git a/QuickLocation/Assets.xcassets/IM/voice_input.imageset/voice@2x.png b/QuickLocation/Assets.xcassets/IM/voice_input.imageset/voice@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..9a8a3c3dced6f1c4717210a3219481b3fccbe28e GIT binary patch literal 1203 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 QK!1iQL@Pp#`N`OS1KOaqL;wH) literal 0 HcmV?d00001 diff --git a/QuickLocation/Assets.xcassets/Mine/feedback_add.imageset/Contents.json b/QuickLocation/Assets.xcassets/Mine/feedback_add.imageset/Contents.json new file mode 100644 index 00000000..9d7523d6 --- /dev/null +++ b/QuickLocation/Assets.xcassets/Mine/feedback_add.imageset/Contents.json @@ -0,0 +1,8 @@ +{ + "images" : [ + { "idiom" : "universal", "scale" : "1x" }, + { "filename" : "add@2x.png", "idiom" : "universal", "scale" : "2x" }, + { "filename" : "add@3x.png", "idiom" : "universal", "scale" : "3x" } + ], + "info" : { "author" : "xcode", "version" : 1 } +} diff --git a/QuickLocation/Assets.xcassets/Mine/feedback_add.imageset/add@2x.png b/QuickLocation/Assets.xcassets/Mine/feedback_add.imageset/add@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..9ff1fec291ff44c2e95f2c5961282a4a0aeb5329 GIT binary patch literal 212 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeE3?v1%WpM*3p#Yx{S0Fuq{`{3ISFT>Y8c42M zwMta<5gSmHwIs+dn1Q2z`s*ioq33`CIi4<#ArXh)Ufa!kKtX^d(5}pnlSSk~1Cv1B zfsUf_Vz2#UItHBKbLh* G2~7YLCQ&W` literal 0 HcmV?d00001 diff --git a/QuickLocation/Assets.xcassets/Mine/feedback_add.imageset/add@3x.png b/QuickLocation/Assets.xcassets/Mine/feedback_add.imageset/add@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..caada6eb52748273d9f3e64b5f4664c3fb04fc9f GIT binary patch literal 351 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 KQt{a+=>GwukAuqq literal 0 HcmV?d00001 diff --git a/QuickLocation/Assets.xcassets/Mine/feedback_success_header.imageset/header@3x.png b/QuickLocation/Assets.xcassets/Mine/feedback_success_header.imageset/header@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..714b126e973f3dfbc93a0b1e64ca35ff463a77be GIT binary patch literal 109065 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[+mC*Pl zYzG^12h`gFB@G-~$7SxT_Zy1cW3X%1Xd1glsDM9Rzx&~aQd?ptg!mtvUH(%2_gva1 z=zd&(Bwx>pf7I>ojhD9jxIG>IluXf#@2Wgrv}EyD08KGnlRO%}o|46*T^8T2=Yb26E%ytFBD(@73BaU8W048F+p!x514u&oVx~xaN=Rgr@ND+OTPb$y~)( z0ZC5j%$E6KxOSGesT~fqrA0P>dfK|(6HZUZuvG{6cD}V&C$?bN)%MUM1t+`3`ZC!))j9I4>w&MTA%XcGLOpnN7! zDlu+Vu8Rn-oP2^JAj`E6(#_AnO_&ngWuxa%QKH!<7}7kCu>_;Qk}Qr_kn+Hx6xf#9 zIdHnbt{3?MU?74a3-s=g+Cb~ZTM97s5GGB4Qn4bbMj>j_UmEqP#?CRFLZoHtK~g1l z6{A$`-Cj>4A2|6O>(?+xvKUlE-a}0kJ2vA#+I+VKNJJz6fa@J0n+e? zLI||(s@_;R209^NZEg=T7Ju@|C-h?gKkg+l0K0zlBj6JSuYLq4J|1;_e*Zp=gQZTg z2s3Wwi&C<9|GpyLbo~4zi}LRW06sP2ewX(ZkOR8dW#oSK*=IBjmS#Y$xd?2ejY$^2 zkuHl4^X9He`@fWA5xB0)qNgoHV=qHt=<_eWpef|E3IZBmU3EQILmh7e#Z)PY;9USu zehb|FHUNAZPw-oXr+o3Z73R|M!o^tz0^8D4>YNM#e|)^Fq3*Fa)_3)s2HyZ4{rZB& z>l^pqkRa;#BFMhBzjO)@D-e|jTWdYl9Y{yPHimQ>l(GB^3^)^FT2Oe{ZYlTGlCluk zDR8w_sH=+$1mr_e%gilKTZ|T|qQ82L)5!_&bblb*sn3YDRo{NEfXXu4zHor~DO=Ns z5xS~%>g(doy33)UfHna3iuIa_v#j|1P|#X|BtMX`9R+bPV*u+F*4jfIt3J4b%_@z9 zs*+q6Jrj?}c!dHvG5{;AkSj>I%2vpW94oAVOr{X3HB#0(s|ldwJAS`&23B5?FT3_& zBhGj_&RXMj8*?$Lr~nWsHf?(TJi{1VI|8bMl{(E-{R7T4LnZ4_#R?cQbTUBzh|^g3 z!IeLUw3QCprHGNLHC@iGY1*ytGEXu!*c$ik4n!p=4cETXYuqsGTxU87jxA1d*H#U8 zPc7fTew`Md`uxmLi0$&T4#TC9-bdKkbgPVJ@ z_*Orh3(GE_ymj+WIFB&N7&64z2h!esi52^3dt-e6-T4LG6mYTt)R0@nYv!NVT7oLR zyuOU&K-)!QSm4S)M#Xkd8vJCZ(i&H8n-7}Ib^;*ZE3=8IHey6E)`lc_{a*9ml@dXf zOI{Gx>t5f5PVCZD;;`H(qNISN&HBpx5?Tb5e88#yy{0}J9@x`?9pk%9ZPdmR{gK9j z(`bGMs7kU_w6BewrGzi@vmvSfXr_uVq>5tEv003&69Yi* zdA3hR7`*2$S-cN=9^mbpBw2KU*EiW^@yiFGci$axR{R=B7Ucx#Q4750R}kxiv_}9| zUxfC*U)MWhPCUE4Jp$so?-7g8dP^B^n6Xhe>@97`Va7Oasn;c*kOWX8ljDUF!6EKS zm-rfr<7aXrxTtp400p+g1@%d+*FDhykeeYDJdk|)zNFBwE{pZ$)sD^vw0-90!*&el zpN{UEV^2pFy)v+qmiC3afPC(JIu4Z_Z$AiTHvOH^k53#>m%|2Oz8Y9_TS$FiV^xFF z#L`-AS9Pd>HHt$)8m}Dyg!%CgV9L49eu~9fjn<(msqE#l8k8x{DBaYHTTrqpX>5lI zfyY$B>^zKGDl7*|S>`DyoB?6!NEXd{S<7&f1q_DPN$K2^RGLjxkn9yoDHV*&`bv(I!D$K#O*m*g z`;c60^?yJ5g8D${cku{+?~Q@KSG{%oyTkb`KwanI!bV;*H6u$<1@tZA~W`RktBYRPlgjy2hSg;Gz0>HCjkmbk% zi=AO*-UBVCz-|kiNN#Go+u~Gh-(uVHRT@vZc;^Z2X`Hy~P*|}yYC;*cb2l4D3aH|O z0$L&w+-y2yz%G#6%YELiS9+EgG%Dd+ud&Ag(IFtL*H|46U4g0&MI8s09MC3BCB`vR zyO_z0S3rn>>bwzHNq}@|tg-Sf#To-hQxd(30%}1|i&Tu*KqOfLFAIt?F}3 z(nL^Mkxn^D6R|BT3d)M&G!dmLKFm~~lQa?1=DkEL5`ioQD<#Vvr>DX?`9j7ls|Y1z z|2qJ?l4G~m9~EhtqKm1_qQySB;1KZp&rja_;c2k?p*aC2A;f>{^#5xj`s-KNr0p4~xxmSOlI6>op}=eD_`8@xzB53#FP4 zAL3@zf=?br%m2-cY6_2Y&2UXI7PSSe*Et?fp6~X_vM1(uXTG^)rPkHcBiRE3EZJ|o zVf}H!(Kb{+YfqPLEvrGW+MlMOwa1)mPITXr2!`{TIg7P(@&hQLui zS^Rf+HP%TxvG)|&^&HS=MzH~~-}J!}WNqLUFlo><3TS!`f$Q%7S|WHT=vW)UlIAf? zvqoP5nqgY0|6S$*-GQ`UcV&Os5&8P0c;0?xKtmK&hH(&8p`;{Bh2C!nz>P6rRvzZ8 zeGYJ%(R|oytTVd|Xl~N!2oM<|a2DLd8Q-m0IWwE__Gj_CKU`~oq>f5Li2ugv_cyNq z(yR7jG2DxnEBZj(bzK&((_T84MZB0|&@G624lavx+OIzc;d{Ud9?)~CxD4RC0RFub zKYkd|y?ekzg~skd#`hF5Gh?_&?grZvfQ~J`>=I-D?-yTC>p*A#vPniu11xvFmm;X% zI-=O|bz1TyAg}A-UEs+RV0%|FT2FyD6{RI(*-x`o-#YU6SC9Z~cRm3od&Px;JzY`H z!OsJ(d_{!KSg*B`>#SrRmjHgx0&xyN8ngCWWclZZX{JmthaV_)gw`oe6p00(jZaQh zUEeKQQ^4Qu_SCxhVcHlyM^42)ob~;_>7gqp*4FC#oJ`7Ty&3oX)5C;^pshDGSk7uK z%_mkUxt7ZeSFB`;ty1})T}E%8&g_(_DAV=f4G4Ikm|a&08$VHe@#Sx^J<#@s(r&6O`x(#$znUo%OF|wp|J(c z=dfr3p`K)Mrpw}UlPvaJ7W&pkfp}7$0U3?c0 z@b48C)A4t0jHcFlS#kSf9LTlISg+l~a-;b9-A#b^t1mtark7uR2VdYHy|K^8-FoF$ z7kUqN9y}SjH-5RG>1sISb$A&(rB(@e7kKjI+eQpKz6+#JpV^Lr-sWFjwGBeTz|JmH z^~?e=m*gt`l80MzX{kOay08F}z5O+{>jmx^uxmfpXu?qZ9cV{>;B*JLx@_aKop}38v|an$c6Wg;@Cwg*=e~Uwk`E+VK%pYCy0l$7E5w5q7c1WUUP+WB2Z!@%Nz-jGM24{FPdNb^iFB?tI;npz*fQzRQX+CNjT#(PH?~TR2?0yQ&-E|8I%61nvsI}yL zuK^b(i{-?xDa>WXm@hWn!3IhDt091Wr$bLhCE&w$M`tsg`n1WPj(-cuM7i6y0K#3^ z)}At35B4asDo0L!*FO2;WR5P-2kbmD!4kuk>lU!lgqB)+wO6#1j&E?X&7YQ3s4FGA;iychFv(SwO*j7*XXV zC96iXQa}X;la&H7p4U2F0k~A}-&v*NGA{`$Aj^Sfm5M6wB#U>{K9_k(W}G=%M-Al6 zbEt}v5}}T-q>711g|B~AToRDA@3(_bRB<*Xi~0)vS^T{po_GM#zw`j4zkM~UeAQmH zS8b$ue)y(b7H_T?w2pr~C|7i#)?AmxBbzB%{20J5@BWei;C;N0U*H#tp)%qR-p4OK z{RQ5~`@jdVVxL5CN&D4jzakd|4NC-d_ydX3MhY?i0R1jwcJsgf{B!byBA*7)jK4S8 z<;(9Wx561r*RzMd!o&CQ`wAA_!#zB7;(Kb^Y{zOceNV~%Ohlz;*$;-bgsB4&$6k0?9>fDKL=iSIz<;-8npS-5bU+ru)q8V>Ojy`IbSK) zTc4d+&!-NMQou74L@D~|@DB&Vnc92>Xv_7s%jqfd?QfOw#0hrTDJ-Mo1<2-9F;gDr zz+ztzHXCfb_IW<5K{NK`Z~_$joJN*SdAGWMGpq|Hxd9YrsyP;yYdbaKhWr1_L`-F*)9?o#bn~5S?$fq4J}miwX0_eq!}11K9~1q+z@@BsU2RQ z*m-+l$o>ZG0QZ;9XXH*V002Z+Bkp|zMie?cY?U1Ebl7k2uw5V})u74SPK^I!G0T+i zCh|A|Lgm^ww61CNkeiW#bq;F$l9tJ9O?XpG){9cym>~=7pi;NF%)_I8XZ*GhBMLqb zCekv(RIxkdk@d5Dx#WWxP7H!+JNesef4cgkKVKvJb3mX0$vQ|vi2u^*_itYTq*v`# zd(~dGAslyIm&H$R-m}J8;znqf0lVHpu}^PVviJdpWs3jmv(HE~T7Ua_M!H_s z9629m_F39~^B|=;<+XfnghTOn@h%?WAw67xxt<^*7!tv+zIaU6Swl6qdyKE>OK009 z61od%GJ(5_lX}vvo9g1}g;Ya5E^smVIlMwdgB5>O{D!;T0BJ)7g&&@839n<6(K6eY zmu28x6lE0fog}DSK&G7d&KBI$!!{zHY!3j!)0}on{&#}TwGRMx+Y`L4Vvj=bsCF;_ zlwFATr2C@?suN(iu&>(S=ebVoLc_?(9VS##!6CD~mhsw1^NY35op02s&xKuH(VxL& z`TMPLP*6<0zdp2G%;Lhn+|1&_Yfrl7>moPr%Phzv`>lYLR=l;vg;&UtTZM*m1>RPk zF-)ix_z8gb z2HXvMQ0rr5UnpZC-rKC*Hy^61`&M;TclBP?{d>+K z=T`Nt>Z;pYJ$T=G?|0Sgl3`2BOG}tF%}Kw%%Nh0hE^0@<-oE;_)K{#kyRj6mn(eFJ zRSkcHN_*eDI6DXT_CBs+_xdf|jHSxQa}&TB05vKKD&PiiV-9}cQ8O&f6tC#`Q0cNm=Rm`l;-~dLZ%Ym8ew^y>-?_srEiv5IZ z`SthAzlk+_p^1!S{OF7VHh^_2CZ)FltOKjZ0hA?OcRZWl7Y?O0I*b@qRl8zWwY5qS zL}D~CV^*!A_ExJ(Yt@JZwHpay)}EzQ&7yYg+BIvdRlnEwmp}5?`?>d=bD#5^=bq%f zH`r2NChN$X3Fk%sCH`ou%|`V)*@H^zm+D$oU9zdIiTXRvh}6?Z5lYkvlnYh!s76Nn z`j>u-S5*uT5fEMYCBN_gQft%cqxGC#p7$xa&XTeDy5lXWq?OLEzS- zH(g=EU42RSi-Tv{i+_L2GvWB+(mPTqC4rCZ_((O+kuSHydKoMp&9i{?phj2=sz$Ot zU*&Y3&ZXc?zk>RzURiMPtuB|wx7-D)H?`-#cv*M>8Ig+9p}_Tvez=9JV5D?|@#Ko+ z(yr`mA}Gtf6@{1$LEJwRls>w#*FmMj@}EA;d46=*C3x9jhpsWC*no1QQEC_D7RC_F zec+vq3T#wr_HV4P^rsOZ3@&0-2*9<&t$gvSq_+voQ!%d9b?H#l#-Gh@QLoofBo0dI zN>pX4pK)JbI#gLW^t}nC;+j$>9jHDRoqZ&C=-uC*;)N8A>?a66XxYOFJyj^Z{@8YO^RZ(*k@>5}G$|yzO5Y0{zC^RHaEIq$$;rvUjYoc| zsOwQY+p=5saA2VMK#Y7NxiK-e!O%$Y&yFIu zCWhe#9^X4~56@*Tcj^kb@od8jOTUepAJea0EeQqL?;y2=zd7m-@PU)cYXB7$sEs zNA?j4mGOdg*i&FB#b*;Y;V|%`v*|q!8_!lFv4*w@VBTb;G2X~5cA~NoWI7cl?bz4T zurT09^OL=V&X>Q$@{Unl8|LfD71t9jcVfC8{gqC-;8!c}`nS6;9S57r@)}3&TAKXy z;wMPq24>N748sY^H)$s#;}5Ja@_wfZ>!t=f;jf0X+v zWVvMM!&bAy7MzPK{U{x<9g<{c+RQv1I#V+m$)oo}gGM*k_4;VSOkz2xcviT0UZ$74 z#_K@1Oie+rezcF=_Vv2weW68RarfIlAJd*{BtV+h?<@kR&N!5c>?Rk=DfCs5Ymt3Z zpma)oq|2l|hN8Hkb<^&_m8ClF;7hFgpeT^4t?F?4xaY5vf>E9))&piQFuIm4=9Gox z1*+&Thu<~Q7=s^Ysv&6QOeRWhHg^>oP{$uB%Ei1~$T3vXJ!*2b9OBA}mgxA|I=cjx zPnM`U{UTf$m>0~mE1%!5`RfG@jEhwGsz4ZBhC1RWv#Q=jb?&-%VT!WqhV}JjNjXea zuNxLrZa}Z`kajw{bMjexYL2R@vH+-Yb%9%VNVi`=94#$7tSahOEN||T+CY^gpxds? z(Z>qW?a;-WPB<+N_cUc+cNMgWvhH^iGnw^EN+`>x-F$HEfM*YI>C5`_EHUg5vYyo3jeYW*Ol9Y`X<%=kf%B}Pvx~{Z^7OZqPd>x zhEe+nVo%LL9r^3h2>fEj2*$$eL+QbvxZ2}{$#|rmT&IrC!irgth*j) z*fmRa2SoSPDbO6CL`rM+iOsFXb(RBOyNn>;ULo5apY~+l;iuGJ?Z7*#D$UOu4R7C$ z!c#oKeHZkiFOQu1BU5+wG5nNFOp}U>H`zlq@%V72P4oeh^((~5N#&kjGn2+d%)Dj; zq==Ww$ha|J-?7>EJWR;R^v=DQ`Iqzfg@r2VKRWjdr#MEc9_wXfc6FwUuIZQd4=lg1 z^hBiQ+UIb?e&CTY6<;*hB~Q~n>=$AOPyKcOb-&a{Q95X;5g-3%w#XM1?>994vR=i5 zxkt88*`cFXH&f$KE?OJ?3O?0gXhb&OVZDRXRTRPK6_fvN&eIPkPcddHs~^zl`sE}l znBmEHDn3{ABCot@YBGbMs!`f?q`|mn+;1B7cF`oJU@3VayXZVoI@>}V#hUO{-CV)` zJjFiIV!dDJgRv$XniI((zDw4}RMP99H9bXSwUPrmH=vS)nx zlF#Xw6lM`DTk!qx+->iKhlYVGG*ky`G?>=h`N;{2ZQ)ff`b71M24EFuQIV+X>mTmZ zB;93u>o_p$>)2v5~8CxoBV$FZ1e=%hZp8`o0Xx;?xJD z>5HSL@Y0hAo1&>=Xw16$>s*&x)$x(nXj zM3dR13O6~ad}5#%(sS-%1*B773Dr0 zpY`e$4VnZkQN8;zg*xC!NO*MQh*=m*eu%5X7$l_@sEWVu=|6{I_rW<>*Q*bfgFztcix~ zsWr@ThQ_(jpd7mH`&55CjwdQ&cx%E@Lc%qL#w~@*|E59=4K(fSnP0trqFi5Wekb0q zobpk^Ki~jconD&N;iDk^)tOazzRkC$Hp8~d63?L|8@6#b_a0&wo<|q=I&tSp$&;b& z#NKDd2*!#+p?VynT65D|0b1Snu;I|7EHll=)r^OS99!`$$!dym{Ss&XS|)lOZESvb zVp=8~PJ3~Sg|)BCJihTwe2*G`5`R^J_3*7;ML~QP(ujx+ym~k{Yn#C8#~%W}eHjT4 z=qa6gBmfJg8!*QYC6kxx$0kW$3lZ>C!kk9xJWl*HxpS{)RJU|zxEl23&aZ&l`fJO6 zw^EbX8kK7J**M!VVl=jt&o5=BleyPI6M>%eAk{3-p|*@|18$+4WnB8U zk^8S}H?MMi26BEVRT%k-2<~? zgeQ}MH&CU9r^~l7kzc_*lLltVSAB@1R+I1A{-% z{(g~49C38auALRI+YF4wy^?frFXA>H9QI`k!ITF2Uht>n?NeOqiBR%{Gq%+gRY*>OUj`l3`YxgbsKyw11rykY1>BOGr)lokRd zW@XnHp=K0MG%nWLU2V@@-LKh@2pTcD)Xwx(-`H$o7-!M1L-ELD>9x$PPKt+beu`7R z{!{y&io&wLtUK0Ivex~1%8t${0}{g>`Z^s>(%iZURSGFmb~e^)4PmPyldo#_yIw9^ zzkF_JT{Zul)^g?Y2ybnANOW{=K_G8M-7UTPz7d4MOG*FB^BE=ar4?nHXKXhS1%C0L z{M$0h{w{1K(00D?Z*I6m9UTAsaOUL$D5&h%}*&R9uGJ*;TGmcT@^ zu=Fc$L?Rn5$0n47R<~Ed+DGZEwG3TVrFrJg2pYAdl*N3haV*T&Ib&-&vM*|m@aY~1 zt8lEhtI6G6*^vEiUGO;~tuVV%wx}vV7ww@>H`M)1cVulXr=l?sZUvfvg-it1FCx5K5RN*Z>=~TwVV-Q*>Rx911HS@RBlOsWchD_ zUWtlNy|x0TX^P?G(5nP4-^0j2VE;Vw%2&KM@eAf*GJG287(V59ZMaI4$7;jrjfVzW zOlg!4_1zDAN%{s36}E!Apgvu0V|{9`wUUuwn(c~QqerrO!ovs$*Uqx19Uq$JdV=I76fkyOVuGqLsn^SW^9BTNCw`|hcHpak}J)U+nIGEMMUl=vrqZ@XnMWR?=r zcg+4;fEYMe&x7Fa1ai)nih#fz4xP#v>w98O_)9~{2xa3lA8G*FD zUBS}t(uFm?Bj#1bPz;G0UWt&u_o&`^r(9btzAWHdIBK=2mTI8-?^jhSE->%84AjC+ zj}SavJ_KJi{cM&F&JE+QvJ0}fa$detg-A}px2j=6_pCQH%Vwcl*ou6{88GKN2gS z4o|->xehxymyF72DcD6$L!ubR|Ni!``P)tFdecY%2Va7gszy!)dF`DrUTBA>apT#K z!9*j>kOSH+mbcP8Q3j&%nSl=xciNU9fY@Nl35+Ki%?%aGRdO3#9MUhyQZ9PZ+acLj zvGKkmCh*Q^wB?YjAgAmH8WZ`5#6S7xr;J=)h4#J z3GI5ZSGIR_=&ydD=d~;|M8ePBMsb?X>QP<P}x&IuRL(YaK&w@BdBF)!Qr-f3R%0VIC+LvzNQ)iO0GH zjy9?SOiM?D68FeyBCeor!C!l$lE+2Vr@%P?3|FiqNwpm5O#JYK7%nZL9LcG%*S1vI zuxsQu<`%WdBFZ>b=#VI3=JSMU2tz~zKX-|14HZ{t2v|5^MH@|1$2(?iS891;z8=i` zKnT8pBOX0GSS=JsCJN%MIx#xfX~#EmlM2rjVF|wk5kZ|OLtfHo*-+05)T=PNMxM`C_{u0entr@V6<_(ivsYZz zi1ghNB%d|06_LH;Z9G!F!Ee^i0fh`CY5)4B-6noYXw<@@&YMf8GLdor87r?xT`gIu zjHwfWrzhrcMxw+*N&O-+Tw22|L&kPSUv!Ty1!W@`N5{ifY;aGC{?_EGv*dX}vyZQt z=A|+GjHDQzqcA(Qq96$>9v=dF&DK8x7#9OJ{arNB2v<&{I)w`y!%$vd>{dX z(i88Pz?qL1+(k(W(&aTN8xq3|X`%D0_p>5V;?|v+G@i8uYH;c{`?=qMq;1aHK0Hg1!CE}ZRnK8e{d0TzfSc7p)8NZneG2^L$&wSs zi(apKd%|;8PMn=9zGs>>8gq!PO-4(0>iFzOP%-F*?CG&69*dUnUj$~zd|XkTCP!cx zmC?pW3bKx%&(Z3}q{@YDI0RD4N;tr^9nw|?ww>&_rAU(~#`JIE4V&|R)o}K7jQ8L^ ztJdr=Z9Hm@+Bnj*)UbjY#mn&js6=3(>Z|eMM@d92!gQE&A{$H2r$qW2A;Muu?0ENw z47q~)n8oErQCp9W8@XFJT6%)m?=>i7-X^3lPL=L4=g7`M3$}~7ej=< zHuPVb0evW)k~*Ffi3#CRuk`G2o`eYFhf;(eh-yTOKj7D@lS5)_J*Wa*P$h^1g(r#VZ1T_XZ*F)1hUb6|4Rv)|j>?1k<Q$Ds^$U+7ik*xze_A`PVeMErS13_lGvxCS_nWD_2K8gN*4 zj3WkO3CBp{^mGAO9%-+Y*g|LFmcW;8?9((mzxwFIYFNX{bDPegYdW7!J4`Qy?7=9M zW5I|vXlZ}=J>+^*BsAIw1A!@I{g=;nTe`~o8{KPa*vt1YLxsZo2wlR+|ZXLp-@3XYK@u*e~MHKujKYM14dq?J76j00nMgFf1qQ!FMSK5T0M8hCvNXQN- z)2?=I1JRNXxb?vKUbF+WyYyEBCLyr%fuphi=CspG6i}aKA_7%jmH*@Z?u$oZb|0hW z!9!F!E(@fSGF@!~>}$y0HWkAiZ)Ur{_$W@1|ERq}5Rt|LnQR&A!wkLP?Q|}2QcJ9Z zXjmi=ca!y|aJlZU>4`==9zB+0wY>$fu!Jqus^VF;VDm3QzEZ%|z7#98G1Cg*_&Ynx zuj!OvvIO<8b!d2jL?>q&(KLnm)^uQLJATN~f+j&ynz9R%+e@qKXgBc3c0grSQY&v9 zMRe$_l!1dy?5AQqi<Na(lZ6Zi#j~#ePOA7e8c^>vg$1bHtcA zp4OIA)~1!ovc}=R|54!ijfwo95TcpK%X1$3Bl;k6fXA-p2q5EDsWHPGg%*t1CrYHLkmO5+~B z`JwLeW9wq%g)ypeejovI5I$T8kQVm=Y8DEdVgxoRCKh|K217s!k|>Hc?g_GBUO?B3YS%sD#< znvDcUset~fOMD<)x~E;OE3#Zv08VYa1eW`b)Mqk zSiY>=@qCYJcMw7ni_zPAJjXw4c56?9{{|eh0U=>jD`{emZ(1^t;Q}NvBOf3*zz^;6 z#SrQA{L2{-&Do@!teq;zGw%;`+Yj{@Or8+dLeM%l%;4yO z766qps3J`yCo(aGk*|xv8uCKIx>HA1rK^Na4|OZ)lNG;W@BG?wWO$}pEnFFl#~v42 zP83|w8W)xij*8=pC>u%>zor!b&ZPr&ztiJPOvl>}Z>f^AC!5y$L83y}QZmWk4i$D~ zYhsxjHX)}8$eWJR;al80m(BSv2H~ec8A2llfI;?+QtBXD&A1#V^)b%Uh5F^QzsK$P z@SyMfFf}!`^QY$Y?^S2$;xo4kQUMKX9f1McAn_MP>kZf>MD>ar@Y?lnQt?+@5Mc!G&s|@1n7zB!Iy3b`AXM9N<(N-^ z!X_`VxVq8*%nV}5(*WOkuNoxE9rU%t3h=NMkthH^<3yZ2kaqO80`$Z|$KbQh0aRAs zUZDR*h5&=t1#8|`YkCB^un#7JMztV+-$B>0&bej@hv{IC4U!X;4%sGywo(r{W!z%* zmSov91%PH%TmPSw@P^J3Ghh}%21E}Jk3mz*hjucj^b*lL(% zpUmv@-N@FdV;KNK7(lSkj|v0$nKO?Q007qos5Fu(-s4+olaMKMX|ssVv>BHhJ)u4u zmQES-GGxzAt!eGQRVVnWDyHdg9-(_{6M8;|v$kFclqqjVKcX*Vh8{E8_ zSc@V#&m374>v~IcFU)(4fm+a13+$%~Kj7C)XUyd!&hKNwf;p0mBX*5qk8oAKX}Xn5 z8E*2^^7L-Yp!4IGU{dT)ij}RcE$45~?}5Jb_tQTw{b|g-!`uX?2H2?=#t;TTKnuNU z7HUTZ{N1E$kX#{0#8u^1yHJelzEQ@^`GA^gLbf*(khVx@_FK*~e50jK-1HJ1Kqg%2 zEWBL|d=V`R&LxQg*FpfrbK3p1z~pDpV(|-!ZHs_(0b+*x-m7;Pav*e16$6wqJ{q0f zS0iD-WV%h%y1A_@k(M*ZJ2;tkHzIBOh`Q*n#T#nz6|@7hv$N&Lk%qztG2sngOSCS$ zKg1ABjCfh`9_3rMv1_A}5SN zg@gnS6AUFWN__KHenz?C!O%IFbA^jJO7Z%Q8ww;^U?Ww}$6fuO%z_zGMwEdm)bYZ| zL;*yzEt%MquLrnN?ZPan)Q70bn28Iw8c*zHXn&~$E{7;iiL*eEI zYuh%V(ZB|VqaERWoy)h2ANKCuI~I^J#fm9?ZO`n5VIg# zdUeqZqA_Jn*7WZqPoB;_kXj<=ZFY9KV(-ZI`Rf0t4CyN0Ow}6xxys%?5vCpA)0TJ7S!L`P3I6iu)S&S8c_}$Ls7!jGHZ<|5 z6i6vx50522qh_>*z~;b(5iTOl{nlz?vQ7%^UGAovKT1dZ0;}66^!TS3sz*U4tgSh1)M8U+quNGc!>U=4uoDAf}~Onv{jCAHb# zqbo6(my2DtwR~EBk=2jae;>+U)Lg2MoXC`xyIRuD4BXyJ!lxpL(O84g_UBloW{yrHl9qM$ImR7a61*bT^DOs19=a{rRf)&gll zVnGzvml@9Wa2`y!vd@&mS+ryQU+hF+v;A~H;fU~%DI2;`<}r2}#J4kaRC;_>{ywAH zq$mtdI$=MPr;ESw7X{Q!u4Wd(*6I~v!~pcNSc}KaqNKMj`NP)Q!}(@jjD&M=d@uVoSmJy zA4fvDOZmAS{8Jf#d1m8yht=Ld1rUTg+=wKkX$84qtM71zy8na_%#{!`K>-MUq*{|F zJ$l(V0f-s(J6;kQtCW%*UUE1}+*I`pD^UWjSVFhr$wfU^CS|!`P2O@b6{c|q2M3$O z2D}NKp7dkCCgT1dZY*FJF{=wD`)85Fr^9q))QYc*?n^|Z9O{E7zUFQR#qf#ye>c+N z{AlIu{Kx4Xr(<{r|BT=NSGEO;#tTrICwf@e8NgFBxJMCOs}*tqZ0D~8V`d@impZM; zgMp4My;_sVMK_90Nf9rOOcBr`%!D!cSku5XRs$|Z6%A04_%O*3FLM3P#X54RSlc6 z)&haqvVZpauVez?n}f=TXnv-XP|Bx-+;d_iD1CIX6~vK));Bk~aqx|B*xNTMK+1<| zV|+UMkl6q+z{}N~AhQ%D891(EWj=PeQ8b)*s!FF23kbU|6TcB)ASXE7pmbCO5+I{Jy1 zmsif7sHLT4{eM+76b~TtjNcN=H^&bfdkGpDz@Zp#xAm zni5G<;6UKhIXZDUD-mlAMK<@nahCXiKr6r_x=4nPKp2k^iJ~9c-AFfjiH}dCc*QXk z!H(|l1&FG*KVSd<8d^s@1<3l03!WrX^JlAjV42aFReRL|3c-2p$$;aP10^p;gEOkV zZh^{(X>NeuBgj|_#EH!RXaf1*Dk+}JPisG7BZarsnoznl7FiCl0?+RhUBEc5*CnhBOvNlk z5zvbQom)KT*v)5LzHh#%gEq6Dcilx?WDnQvcPbp@`}QtW$7xyyle=@=qJp+$k>VNM a=T~M7HiG9v(jJ0m`$o~N0{~g8v literal 0 HcmV?d00001 diff --git a/QuickLocation/Assets.xcassets/Mine/feedback_success_icon.imageset/Contents.json b/QuickLocation/Assets.xcassets/Mine/feedback_success_icon.imageset/Contents.json new file mode 100644 index 00000000..6402a56a --- /dev/null +++ b/QuickLocation/Assets.xcassets/Mine/feedback_success_icon.imageset/Contents.json @@ -0,0 +1,8 @@ +{ + "images" : [ + { "idiom" : "universal", "scale" : "1x" }, + { "filename" : "icon@2x.png", "idiom" : "universal", "scale" : "2x" }, + { "filename" : "icon@3x.png", "idiom" : "universal", "scale" : "3x" } + ], + "info" : { "author" : "xcode", "version" : 1 } +} diff --git a/QuickLocation/Assets.xcassets/Mine/feedback_success_icon.imageset/icon@2x.png b/QuickLocation/Assets.xcassets/Mine/feedback_success_icon.imageset/icon@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..024d5ce0584322a2990a56b8bc1395d6c73de243 GIT binary patch literal 9412 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%0D-o2ov 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 G1pgmdY$|^M literal 0 HcmV?d00001 diff --git a/QuickLocation/Manager/App/RouterManager.swift b/QuickLocation/Manager/App/RouterManager.swift index 501db0fe..702ec6c1 100644 --- a/QuickLocation/Manager/App/RouterManager.swift +++ b/QuickLocation/Manager/App/RouterManager.swift @@ -81,6 +81,8 @@ enum Route: String { case phoneReportDetail = "phoneReportDetail" /// 关于我们 case about = "about" + /// 意见反馈 + case feedback = "feedback" /// 成员信息 case memberInfo = "memberInfo" /// 注销账号 @@ -384,6 +386,11 @@ extension AppRouter: AppRouterProtocol { AboutVC() } + // MARK: - 意见反馈 + AppRouter.register(Route.feedback) { _, _ in + FeedbackVC() + } + // MARK: - 成员信息 AppRouter.register(Route.memberInfo) { _, parameters in MemberInfoVC(userInfo: parameters) @@ -430,4 +437,3 @@ extension AppRouter: AppRouterProtocol { } } - diff --git a/QuickLocation/Section/Group/GroupChat/GroupChatVC.swift b/QuickLocation/Section/Group/GroupChat/GroupChatVC.swift index 987bfeb2..0074b314 100644 --- a/QuickLocation/Section/Group/GroupChat/GroupChatVC.swift +++ b/QuickLocation/Section/Group/GroupChat/GroupChatVC.swift @@ -15,6 +15,12 @@ import AudioToolbox import HXPHPicker import IQKeyboardManagerSwift import MJRefresh +import CoreLocation +import SwiftyUserDefaults +#if !targetEnvironment(simulator) +import AMapNaviKit +import AMapSearchKit +#endif final class GroupChatVC: BaseViewController { @@ -26,6 +32,7 @@ final class GroupChatVC: BaseViewController { /// mention 列表:首行 @所有人 + 成员 private var mentionRows: [(userId: String?, nickname: String)] = [] private var isMentionPickerVisible = false + private var cameraPicker: ImagePicker? /// 加载更早历史前记录,用于保持阅读位置 private var pendingOffsetRestore: (oldHeight: CGFloat, oldOffset: CGFloat)? @@ -76,8 +83,11 @@ final class GroupChatVC: BaseViewController { IQKeyboardManager.shared.resignOnTouchOutside = false // 非圈主 会员权益拦截 - guard viewModel.groupId.contains(AppContextManager.shared.userId) == false else { return } - rootView.disableIMView.isHidden = AppContextManager.shared.vip > 1 + let isCircleOwner = viewModel.groupId.contains(AppContextManager.shared.userId) + let canSend = isCircleOwner || AppContextManager.shared.vip > 1 + rootView.disableIMView.isHidden = canSend + rootView.quickActionBar.isUserInteractionEnabled = canSend + rootView.quickActionBar.alpha = canSend ? 1 : 0.35 } override func viewWillDisappear(_ animated: Bool) { @@ -121,6 +131,7 @@ final class GroupChatVC: BaseViewController { .filter { $0.state == .began } .subscribe(onNext: { [weak self] _ in self?.rootView.dismissAllPanels() + self?.bubbleMenu?.dismiss() }) .disposed(by: disposeBag) @@ -128,6 +139,7 @@ final class GroupChatVC: BaseViewController { rootView.tableView.rx.itemSelected .subscribe(onNext: { [weak self] _ in self?.rootView.dismissAllPanels() + self?.bubbleMenu?.dismiss() }) .disposed(by: disposeBag) } @@ -339,6 +351,8 @@ final class GroupChatVC: BaseViewController { if let c = cell as? VoiceReceivedMsgCell { return c.menuAnchorView } if let c = cell as? ImageSendMsgCell { return c.menuAnchorView } if let c = cell as? ImageReceivedMsgCell { return c.menuAnchorView } + if let c = cell as? LocationSendMsgCell { return c.menuAnchorView } + if let c = cell as? LocationReceivedMsgCell { return c.menuAnchorView } return cell.contentView } @@ -350,7 +364,11 @@ final class GroupChatVC: BaseViewController { let menu = ChatBubbleActionMenu() bubbleMenu = menu - menu.onQuote = { [weak self] in + menu.onMention = { [weak self] in + guard let self else { return } + self.insertMention(userId: msg.senderId, nickname: msg.senderName, replaceTriggerAt: false) + } + menu.onReply = { [weak self] in guard let self = self, let oim = self.viewModel.oimMessage(forClientMsgID: msg.id) else { DLToast.showError(text: "无法引用该消息") @@ -359,11 +377,9 @@ final class GroupChatVC: BaseViewController { self.viewModel.setPendingQuote(oim) self.rootView.textField.becomeFirstResponder() } - menu.onRevoke = { [weak self] in - self?.viewModel.revokeMessage(clientMsgID: msg.id) - } + menu.onDismiss = { [weak self] in self?.bubbleMenu = nil } let anchor = menuAnchorView(in: cell) -// menu.show(in: rootView, anchor: anchor, showRevoke: msg.isSelf) + menu.show(in: rootView, anchor: anchor, canMention: !msg.isSelf) } // MARK: - Mention @@ -510,9 +526,8 @@ final class GroupChatVC: BaseViewController { }) .disposed(by: disposeBag) - // ➕按钮 Observable.merge( - rootView.addBtn.rx.tap.asObservable(), + rootView.galleryBtn.rx.tap.asObservable(), rootView.voiceRecordView.addBtn.rx.tap.asObservable() ) .subscribe(onNext: { [weak self] in @@ -521,6 +536,20 @@ final class GroupChatVC: BaseViewController { self.showAlbum() }) .disposed(by: disposeBag) + + rootView.cameraBtn.rx.tap + .subscribe(onNext: { [weak self] in + self?.rootView.dismissAllPanels() + self?.showCamera() + }) + .disposed(by: disposeBag) + + rootView.locationBtn.rx.tap + .subscribe(onNext: { [weak self] in + self?.rootView.dismissAllPanels() + self?.showLocationPicker() + }) + .disposed(by: disposeBag) rootView.sendBtn.rx.tap .subscribe(onNext: { [weak self] in @@ -548,7 +577,7 @@ final class GroupChatVC: BaseViewController { rootView.voiceRecordView.isHidden = !show let offset: CGFloat = show ? 252 : 0 UIView.animate(withDuration: 0.25) { - self.rootView.bottomBar.layoutChain.bottom(show ? offset - self.rootView.bottomBar.dl.height : kSafeBottomMargin + 20) + self.rootView.bottomBar.layoutChain.bottom(show ? offset - self.rootView.bottomBar.dl.height : kSafeBottomMargin) self.rootView.voiceRecordView.layoutChain.bottom(offset - 252) } scrollToBottom() @@ -599,6 +628,37 @@ final class GroupChatVC: BaseViewController { self.present(pickerController, animated: true, completion: nil) } + private func showCamera() { + guard UIImagePickerController.isSourceTypeAvailable(.camera) else { + DLToast.showError(text: "当前设备不支持拍照") + return + } + let picker = ImagePicker() + picker.imageDidPicked = { [weak self] image in + DispatchQueue.main.async { + self?.sendImageMessage(image) + } + } + cameraPicker = picker + picker.showCamera() + } + + private func showLocationPicker() { + let picker = ChatLocationPickerVC() + picker.onPickedLocation = { [weak self] location in + self?.viewModel.sendLocation(location) + } + navigationController?.pushViewController(picker, animated: true) + } + + private func showLocationDetail(_ location: ChatLocationPayload?) { + guard let location else { + DLToast.showError(text: "无法读取位置信息") + return + } + navigationController?.pushViewController(ChatLocationDetailVC(location: location), animated: true) + } + // MARK: - Voice Recording private var audioRecorder: AVAudioRecorder? private var recordFileURL: URL? @@ -701,11 +761,12 @@ final class GroupChatVC: BaseViewController { private func requestGroupInfoByKey() { GroupService.groupInfoByKey(viewModel.groupId).subscribe { response in guard let model = response.model else { return } + self.viewModel.groupModel = model self.viewModel.memberList = response.list - self.rootView.groupNameLabel.text = model.name + self.rootView.groupNameLabel.text = "\(model.name)(\(response.list.count))" self.rootView.groupAvatarView.image = model.groupIcon self.rootView.reviewBtn.isHidden = !model.is_owner - self.rootView.reviewDotView.isHidden = response.reviewCount == 0 +// self.rootView.reviewDotView.isHidden = response.reviewCount == 0 }.disposed(by: disposeBag) } @@ -759,6 +820,20 @@ final class GroupChatVC: BaseViewController { self?.showBigImage(imgUrlList: [msg.imageUrl], currentPage: 0, projectiveView: cell.photoView) } return cell + case let .locationSend(msg): + let cell: LocationSendMsgCell = tableView.dequeueReusableCell(for: indexPath) + cell.configure(msg) + cell.onLocationTap = { [weak self] in + self?.showLocationDetail(msg.location) + } + return cell + case let .locationReceived(msg): + let cell: LocationReceivedMsgCell = tableView.dequeueReusableCell(for: indexPath) + cell.configure(msg) + cell.onLocationTap = { [weak self] in + self?.showLocationDetail(msg.location) + } + return cell case let .notification(text, showTime, timestamp), let .revoked(text, showTime, timestamp): let cell: NotificationMsgCell = tableView.dequeueReusableCell(for: indexPath) @@ -809,10 +884,12 @@ extension GroupChatVC: UITableViewDelegate { } func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - guard tableView === rootView.mentionTableView else { return } - tableView.deselectRow(at: indexPath, animated: true) - let row = mentionRows[indexPath.row] - insertMention(userId: row.userId, nickname: row.nickname) + if tableView === rootView.mentionTableView { + tableView.deselectRow(at: indexPath, animated: true) + let row = mentionRows[indexPath.row] + insertMention(userId: row.userId, nickname: row.nickname) + return + } } } @@ -931,3 +1008,811 @@ extension GroupChatVC: PhotoPickerControllerDelegate { } } + +// MARK: - 群聊位置选择 +private struct ChatLocationSuggestion { + let name: String + let address: String + let coordinate: CLLocationCoordinate2D +} + +#if !targetEnvironment(simulator) +private final class ChatCurrentLocationAnnotation: NSObject, MAAnnotation { + var coordinate: CLLocationCoordinate2D + + init(coordinate: CLLocationCoordinate2D) { + self.coordinate = coordinate + super.init() + } +} + +private final class ChatCurrentLocationAnnotationView: MAAnnotationView { + private let avatarContainer: UIView = { + let view = UIView() + view.backgroundColor = .white + view.layer.cornerRadius = 14 + view.layer.shadowColor = UIColor.black.cgColor + view.layer.shadowOffset = CGSize(width: 0, height: 2) + view.layer.shadowRadius = 5 + view.layer.shadowOpacity = 0.16 + return view + }() + private let avatarImageView: UIImageView = { + let view = UIImageView() + view.contentMode = .scaleAspectFill + view.clipsToBounds = true + view.layer.cornerRadius = 10 + return view + }() + private let statusOuterView: UIView = { + let view = UIView() + view.backgroundColor = .white + view.layer.cornerRadius = 8 + view.layer.shadowColor = UIColor.black.cgColor + view.layer.shadowOffset = CGSize(width: 0, height: 1) + view.layer.shadowRadius = 2 + view.layer.shadowOpacity = 0.16 + return view + }() + private let statusInnerView: UIView = { + let view = UIView() + view.backgroundColor = UIColor(hexStr: "#56DC42") + view.layer.cornerRadius = 5 + return view + }() + + override init!(annotation: MAAnnotation!, reuseIdentifier: String!) { + super.init(annotation: annotation, reuseIdentifier: reuseIdentifier) + backgroundColor = .clear + canShowCallout = false + isUserInteractionEnabled = false + bounds = CGRect(x: 0, y: 0, width: 56, height: 72) + centerOffset = CGPoint(x: 0, y: -29) + + addSubview(avatarContainer) + avatarContainer.addSubview(avatarImageView) + addSubview(statusOuterView) + statusOuterView.addSubview(statusInnerView) + + avatarContainer.frame = CGRect(x: 0, y: 0, width: 56, height: 56) + avatarImageView.frame = avatarContainer.bounds.insetBy(dx: 4, dy: 4) + statusOuterView.frame = CGRect(x: 20, y: 57, width: 16, height: 16) + statusInnerView.frame = statusOuterView.bounds.insetBy(dx: 3, dy: 3) + } + + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } + + func configure() { + let avatar = AppContextManager.shared.avaterIcon + avatarImageView.image = avatar.size == .zero ? UIImage(named: "Common/default_avatar") : avatar + } +} +#endif + +final class ChatLocationPickerVC: BaseViewController { + override var isNavigationBarHidden: Bool { true } + + var onPickedLocation: ((ChatLocationPayload) -> Void)? + private var rootView: ChatLocationPickerView! + private var currentCoordinate: CLLocationCoordinate2D? + private var selectedLocation: ChatLocationSuggestion? + private var suggestions: [ChatLocationSuggestion] = [] + private var searchWorkItem: DispatchWorkItem? + + #if !targetEnvironment(simulator) + private let searchAPI = AMapSearchAPI() + private var currentLocationAnnotation: ChatCurrentLocationAnnotation? + #endif + + override func loadView() { + rootView = ChatLocationPickerView(frame: UIScreen.main.bounds) + view = rootView + } + + override func viewDidLoad() { + super.viewDidLoad() + rootView.resultTableView.dataSource = self + rootView.resultTableView.delegate = self + rootView.backBtn.addTarget(self, action: #selector(handleBack), for: .touchUpInside) + rootView.confirmBtn.addTarget(self, action: #selector(confirm), for: .touchUpInside) + rootView.recenterBtn.addTarget(self, action: #selector(recenterToCurrentLocation), for: .touchUpInside) + rootView.searchField.addTarget(self, action: #selector(searchChanged), for: .editingChanged) + rootView.searchField.addTarget(self, action: #selector(search), for: .editingDidEndOnExit) + setupMap() + } + + override func viewDidDisappear(_ animated: Bool) { + super.viewDidDisappear(animated) + if isMovingFromParent || isBeingDismissed { + #if !targetEnvironment(simulator) + rootView.cleanupMap() + #endif + } + } + + @objc private func handleBack() { + navigationController?.popViewController(animated: true) + } + + @objc private func confirm() { + guard let selectedLocation else { + DLToast.showError(text: "请选择位置") + return + } + onPickedLocation?(ChatLocationPayload(name: selectedLocation.name, + address: selectedLocation.address, + latitude: selectedLocation.coordinate.latitude, + longitude: selectedLocation.coordinate.longitude)) + navigationController?.popViewController(animated: true) + } + + @objc private func searchChanged() { + searchWorkItem?.cancel() + let workItem = DispatchWorkItem { [weak self] in self?.search() } + searchWorkItem = workItem + DispatchQueue.main.asyncAfter(deadline: .now() + 0.35, execute: workItem) + } + + @objc private func search() { + let keyword = rootView.searchField.text?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" + guard !keyword.isEmpty else { + loadNearbyPOIs() + return + } + #if !targetEnvironment(simulator) + let request = AMapPOIKeywordsSearchRequest() + request.keywords = keyword + request.city = "" + request.offset = 20 + if let currentCoordinate { + request.location = AMapGeoPoint.location(withLatitude: CGFloat(currentCoordinate.latitude), + longitude: CGFloat(currentCoordinate.longitude)) + } + searchAPI?.aMapPOIKeywordsSearch(request) + #else + rootView.emptyLabel.isHidden = false + rootView.emptyLabel.text = "模拟器无法搜索地图地点" + #endif + } + + @objc private func recenterToCurrentLocation() { + guard let currentCoordinate else { + DLToast.showError(text: "暂无当前位置") + return + } + #if !targetEnvironment(simulator) + rootView.mapView.setCenter(currentCoordinate, animated: true) + #endif + selectMapCenterLocation(currentCoordinate, placeholderName: "当前位置") + } + + private func setupMap() { + if let latitude = Defaults[\.currentLatitude], let longitude = Defaults[\.currentLongitude] { + let coordinate = CLLocationCoordinate2D(latitude: latitude, longitude: longitude) + if CLLocationCoordinate2DIsValid(coordinate) { + currentCoordinate = coordinate + } + } + #if !targetEnvironment(simulator) + searchAPI?.delegate = self + rootView.mapView.delegate = self + rootView.mapView.showsUserLocation = false + let coordinate = currentCoordinate ?? CLLocationCoordinate2D(latitude: 39.9042, longitude: 116.4074) + rootView.mapView.setCenter(coordinate, animated: false) + rootView.mapView.setZoomLevel(15, animated: false) + if let currentCoordinate { + addCurrentLocationAnnotation(at: currentCoordinate) + selectMapCenterLocation(currentCoordinate, placeholderName: "当前位置") + } + #else + rootView.emptyLabel.isHidden = false + rootView.emptyLabel.text = "请在真机上选择地图位置" + #endif + loadNearbyPOIs() + } + + private func loadNearbyPOIs() { + #if !targetEnvironment(simulator) + guard let currentCoordinate else { + rootView.emptyLabel.isHidden = false + rootView.emptyLabel.text = "暂无当前位置,可直接在地图上选择" + return + } + let request = AMapPOIAroundSearchRequest() + request.location = AMapGeoPoint.location(withLatitude: CGFloat(currentCoordinate.latitude), + longitude: CGFloat(currentCoordinate.longitude)) + request.radius = 1500 + request.offset = 20 + searchAPI?.aMapPOIAroundSearch(request) + #endif + } + + private func updateSuggestions(_ values: [ChatLocationSuggestion]) { + suggestions = values + keepSelectedLocationInSuggestions() + rootView.resultTableView.reloadData() + rootView.emptyLabel.isHidden = !suggestions.isEmpty + } + + private func select(_ location: ChatLocationSuggestion, recenterMap: Bool) { + selectedLocation = location + keepSelectedLocationInSuggestions() + rootView.selectedNameLabel.text = location.name.isEmpty ? "已选位置" : location.name + rootView.selectedAddressLabel.text = location.address.isEmpty ? "暂无详细地址" : location.address + rootView.selectedPanel.isHidden = false + rootView.confirmBtn.isEnabled = true + rootView.emptyLabel.isHidden = true + rootView.resultTableView.reloadData() + #if !targetEnvironment(simulator) + if recenterMap { + rootView.mapView.setCenter(location.coordinate, animated: true) + } + #endif + } + + private func selectMapCenterLocation(_ coordinate: CLLocationCoordinate2D, placeholderName: String = "正在获取地点...") { + guard CLLocationCoordinate2DIsValid(coordinate) else { return } + let placeholder = ChatLocationSuggestion(name: placeholderName, + address: "正在获取地址...", + coordinate: coordinate) + select(placeholder, recenterMap: false) + requestReverseGeocode(for: coordinate) + } + + private func keepSelectedLocationInSuggestions() { + guard let selectedLocation else { return } + if let index = suggestions.firstIndex(where: { coordinatesMatch($0.coordinate, selectedLocation.coordinate) }) { + suggestions[index] = selectedLocation + } else { + suggestions.insert(selectedLocation, at: 0) + } + } + + private func coordinatesMatch(_ lhs: CLLocationCoordinate2D, _ rhs: CLLocationCoordinate2D) -> Bool { + abs(lhs.latitude - rhs.latitude) < 0.000_001 && abs(lhs.longitude - rhs.longitude) < 0.000_001 + } + + #if !targetEnvironment(simulator) + private func requestReverseGeocode(for coordinate: CLLocationCoordinate2D) { + let request = AMapReGeocodeSearchRequest() + request.location = AMapGeoPoint.location(withLatitude: CGFloat(coordinate.latitude), longitude: CGFloat(coordinate.longitude)) + request.requireExtension = true + searchAPI?.aMapReGoecodeSearch(request) + } + + private func addCurrentLocationAnnotation(at coordinate: CLLocationCoordinate2D) { + if let currentLocationAnnotation { + currentLocationAnnotation.coordinate = coordinate + return + } + let annotation = ChatCurrentLocationAnnotation(coordinate: coordinate) + currentLocationAnnotation = annotation + rootView.mapView.addAnnotation(annotation) + } + #endif +} + +extension ChatLocationPickerVC: UITableViewDataSource, UITableViewDelegate { + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { suggestions.count } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell(withIdentifier: "ChatLocationSuggestionCell", for: indexPath) + let value = suggestions[indexPath.row] + var content = cell.defaultContentConfiguration() + content.text = value.name + content.secondaryText = value.address + content.textProperties.font = .systemFont(ofSize: 15, weight: .medium) + content.secondaryTextProperties.font = .systemFont(ofSize: 12) + content.secondaryTextProperties.color = UIColor(hexStr: "#8A8A8A") + cell.contentConfiguration = content + cell.accessoryType = selectedLocation?.coordinate.latitude == value.coordinate.latitude + && selectedLocation?.coordinate.longitude == value.coordinate.longitude ? .checkmark : .none + cell.tintColor = UIColor(hexStr: "#16B3FF") + return cell + } + + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + tableView.deselectRow(at: indexPath, animated: true) + rootView.searchField.resignFirstResponder() + select(suggestions[indexPath.row], recenterMap: true) + } +} + +#if !targetEnvironment(simulator) +extension ChatLocationPickerVC: AMapSearchDelegate, MAMapViewDelegate { + func onPOISearchDone(_ request: AMapPOISearchBaseRequest!, response: AMapPOISearchResponse!) { + let values = response.pois.compactMap { poi -> ChatLocationSuggestion? in + guard let point = poi.location else { return nil } + let coordinate = CLLocationCoordinate2D(latitude: point.latitude, longitude: point.longitude) + guard CLLocationCoordinate2DIsValid(coordinate) else { return nil } + return ChatLocationSuggestion(name: poi.name ?? "", + address: poi.address ?? poi.district ?? "", + coordinate: coordinate) + } + updateSuggestions(values) + } + + func onReGeocodeSearchDone(_ request: AMapReGeocodeSearchRequest!, response: AMapReGeocodeSearchResponse!) { + guard let point = request.location else { return } + let coordinate = CLLocationCoordinate2D(latitude: point.latitude, longitude: point.longitude) + guard let selectedLocation, coordinatesMatch(selectedLocation.coordinate, coordinate) else { return } + let poi = response.regeocode?.pois?.first + let location = ChatLocationSuggestion(name: poi?.name ?? response.regeocode?.formattedAddress ?? "已选位置", + address: poi?.address ?? response.regeocode?.formattedAddress ?? "", + coordinate: coordinate) + select(location, recenterMap: false) + } + + func aMapSearchRequest(_ request: Any!, didFailWithError error: Error!) { + if let reGeocodeRequest = request as? AMapReGeocodeSearchRequest, + let point = reGeocodeRequest.location { + let coordinate = CLLocationCoordinate2D(latitude: point.latitude, longitude: point.longitude) + if let selectedLocation, coordinatesMatch(selectedLocation.coordinate, coordinate) { + select(ChatLocationSuggestion(name: "已选位置", address: "", coordinate: coordinate), recenterMap: false) + } + return + } + rootView.emptyLabel.isHidden = false + rootView.emptyLabel.text = "地点加载失败,请重试或在地图上选择" + } + + func mapView(_ mapView: MAMapView!, regionDidChangeAnimated animated: Bool, wasUserAction: Bool) { + guard wasUserAction else { return } + let center = CGPoint(x: mapView.bounds.midX, y: mapView.bounds.midY) + let coordinate = mapView.convert(center, toCoordinateFrom: mapView) + selectMapCenterLocation(coordinate) + } + + func mapView(_ mapView: MAMapView!, viewFor annotation: MAAnnotation!) -> MAAnnotationView! { + guard annotation is ChatCurrentLocationAnnotation else { return nil } + let identifier = "ChatCurrentLocation" + guard let view = (mapView.dequeueReusableAnnotationView(withIdentifier: identifier) as? ChatCurrentLocationAnnotationView) + ?? ChatCurrentLocationAnnotationView(annotation: annotation, reuseIdentifier: identifier) else { return nil } + view.annotation = annotation + view.zIndex = 10 + view.configure() + return view + } +} +#endif + +private final class ChatLocationPickerView: UIView { + #if !targetEnvironment(simulator) + lazy var mapView: MAMapView! = { + let map = MAMapView() + map.showsCompass = false + map.showsScale = false + map.zoomLevel = 15 + return map + }() + #endif + + let backBtn: UIButton = { + let button = UIButton(type: .custom) + button.setBackgroundImage(UIImage(named: "Common/back"), for: .normal) + button.backgroundColor = .clear + button.extendEdgeInsets = UIEdgeInsets(top: 20, left: 18, bottom: 20, right: 20) + return button + }() + let recenterBtn: UIButton = { + let button = UIButton(type: .custom) + button.setImage(UIImage(named: "IM/location_recenter"), for: .normal) + button.backgroundColor = .white + button.layer.cornerRadius = 10 + button.layer.shadowColor = UIColor.black.cgColor + button.layer.shadowOffset = CGSize(width: 0, height: 2) + button.layer.shadowRadius = 6 + button.layer.shadowOpacity = 0.12 + return button + }() + let centerPinView: UIImageView = { + let view = UIImageView(image: UIImage(named: "IM/location_pin")) + view.contentMode = .scaleAspectFit + view.isUserInteractionEnabled = false + return view + }() + let searchField: UITextField = { + let field = UITextField() + field.placeholder = "搜索地点、商圈或道路" + field.font = .systemFont(ofSize: 14) + field.clearButtonMode = .whileEditing + field.returnKeyType = .search + field.backgroundColor = UIColor(hexStr: "#F3F3F3") + field.cornerRadius = 11 + field.leftView = UIView(frame: CGRect(x: 0, y: 0, width: 16, height: 36)) + field.leftViewMode = .always + return field + }() + let resultTableView: UITableView = { + let table = UITableView(frame: .zero, style: .plain) + table.backgroundColor = .white + table.separatorColor = UIColor(hexStr: "#EEEEEE") + table.rowHeight = 74 + table.register(UITableViewCell.self, forCellReuseIdentifier: "ChatLocationSuggestionCell") + table.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: kSafeBottomMargin, right: 0) + return table + }() + let emptyLabel: UILabel = { + let label = UILabel() + label.font = .systemFont(ofSize: 13) + label.textColor = UIColor(hexStr: "#8A8A8A") + label.textAlignment = .center + label.numberOfLines = 0 + label.isHidden = true + return label + }() + let selectedPanel: UIView = { + let view = UIView() + view.backgroundColor = .white + view.layer.cornerRadius = 24 + view.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner] + view.clipsToBounds = true + return view + }() + let selectedNameLabel: UILabel = { + let label = UILabel() + label.font = .systemFont(ofSize: 16, weight: .semibold) + label.textColor = UIColor(hexStr: "#282828") + return label + }() + let selectedAddressLabel: UILabel = { + let label = UILabel() + label.font = .systemFont(ofSize: 12) + label.textColor = UIColor(hexStr: "#8A8A8A") + label.lineBreakMode = .byTruncatingTail + return label + }() + let confirmBtn: UIButton = { + let button = UIButton(type: .custom) + button.setTitle("确认", for: .normal) + button.setTitleColor(.white, for: .normal) + button.titleLabel?.font = .systemFont(ofSize: 14, weight: .medium) + button.setBackgroundImage(UIImage(named: "Common/button_bg_2"), for: .normal) + button.cornerRadius = 8 + return button + }() + + override init(frame: CGRect) { + super.init(frame: frame) + backgroundColor = UIColor(hexStr: "#EFF7F8") + setupUI() + } + + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } + + private func setupUI() { + #if !targetEnvironment(simulator) + addSubview(mapView) + mapView.layoutChain.edges(excludingEdge: .bottom).bottom(250 + kSafeBottomMargin) + addSubview(centerPinView) + #endif + addSubview(backBtn) + addSubview(recenterBtn) + addSubview(confirmBtn) + addSubview(selectedPanel) + selectedPanel.addSubview(searchField) + selectedPanel.addSubview(resultTableView) + selectedPanel.addSubview(emptyLabel) + selectedPanel.addSubview(selectedNameLabel) + selectedPanel.addSubview(selectedAddressLabel) + + backBtn.layoutChain.top(kStatusBarHeight + 12).left(18).width(32).height(32) + recenterBtn.layoutChain.left(13).bottomToTopOfView(selectedPanel, offset: -24).width(38).height(38) + confirmBtn.layoutChain.right(14).width(50).height(30).centerY(backBtn) + selectedPanel.layoutChain.edgesHorzontal().bottom().height(290) + searchField.layoutChain.top(13).edgesHorzontal(15).height(38) + resultTableView.layoutChain.topToBottomOfView(searchField, offset: 13).edgesHorzontal(0).bottom() + emptyLabel.layoutChain.centerX().centerY().edgesHorzontal(40) + selectedNameLabel.isHidden = true + selectedAddressLabel.isHidden = true + #if !targetEnvironment(simulator) + centerPinView.layoutChain.centerX(mapView).centerY(mapView, offset: -28).width(34).height(56) + #endif + } + + #if !targetEnvironment(simulator) + func cleanupMap() { + mapView?.delegate = nil + mapView?.removeFromSuperview() + mapView = nil + } + #endif +} + +// MARK: - 群聊位置详情 +final class ChatLocationDetailVC: BaseViewController { + override var isNavigationBarHidden: Bool { true } + + private let location: ChatLocationPayload + private var rootView: ChatLocationDetailView! + private var currentCoordinate: CLLocationCoordinate2D? + #if !targetEnvironment(simulator) + private let routeSearch = AMapSearchAPI() + private var routeOverlays: [MAPolyline] = [] + #endif + + init(location: ChatLocationPayload) { + self.location = location + super.init(nibName: nil, bundle: nil) + } + + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } + + override func loadView() { + rootView = ChatLocationDetailView(frame: UIScreen.main.bounds) + view = rootView + } + + override func viewDidLoad() { + super.viewDidLoad() + rootView.backBtn.addTarget(self, action: #selector(handleBack), for: .touchUpInside) + rootView.nameLabel.text = location.name.isEmpty ? "位置" : location.name + rootView.addressLabel.text = location.address.isEmpty ? "暂无详细地址" : location.address + setupLocation() + } + + override func viewDidDisappear(_ animated: Bool) { + super.viewDidDisappear(animated) + if isMovingFromParent || isBeingDismissed { + #if !targetEnvironment(simulator) + rootView.cleanupMap() + #endif + } + } + + @objc private func handleBack() { navigationController?.popViewController(animated: true) } + + private func setupLocation() { + if let latitude = Defaults[\.currentLatitude], let longitude = Defaults[\.currentLongitude] { + let coordinate = CLLocationCoordinate2D(latitude: latitude, longitude: longitude) + if CLLocationCoordinate2DIsValid(coordinate) { + currentCoordinate = coordinate + let distance = CLLocation(latitude: latitude, longitude: longitude) + .distance(from: CLLocation(latitude: location.latitude, longitude: location.longitude)) + rootView.distanceLabel.text = "距离你约 \(chatDistanceText(distance))" + } + } + if currentCoordinate == nil { + rootView.distanceLabel.text = "暂未获取当前位置" + } + #if !targetEnvironment(simulator) + rootView.mapView.delegate = self + rootView.mapView.showsUserLocation = false + routeSearch?.delegate = self + rootView.mapView.setCenter(location.coordinate, animated: false) + rootView.mapView.setZoomLevel(15, animated: false) + addAnnotations() + requestRoutes() + #else + rootView.mapHintLabel.isHidden = false + #endif + } + + #if !targetEnvironment(simulator) + private func addAnnotations() { + let target = MAPointAnnotation() + target.coordinate = location.coordinate + target.title = "target" + rootView.mapView.addAnnotation(target) + if let currentCoordinate { + let current = ChatCurrentLocationAnnotation(coordinate: currentCoordinate) + rootView.mapView.addAnnotation(current) + rootView.mapView.showAnnotations([target, current], animated: true) + } + } + + private func requestRoutes() { + guard let currentCoordinate else { + rootView.drivingLabel.text = "驾车 暂无当前位置" + rootView.walkingLabel.text = "步行 暂无当前位置" + return + } + let origin = AMapGeoPoint.location(withLatitude: CGFloat(currentCoordinate.latitude), longitude: CGFloat(currentCoordinate.longitude)) + let destination = AMapGeoPoint.location(withLatitude: CGFloat(location.latitude), longitude: CGFloat(location.longitude)) + let driving = AMapDrivingRouteSearchRequest() + driving.origin = origin + driving.destination = destination + driving.strategy = 0 + routeSearch?.aMapDrivingRouteSearch(driving) + let walking = AMapWalkingRouteSearchRequest() + walking.origin = origin + walking.destination = destination + routeSearch?.aMapWalkingRouteSearch(walking) + } + #endif +} + +#if !targetEnvironment(simulator) +extension ChatLocationDetailVC: AMapSearchDelegate, MAMapViewDelegate { + func onRouteSearchDone(_ request: AMapRouteSearchBaseRequest!, response: AMapRouteSearchResponse!) { + guard let path = response.route?.paths?.first as? AMapPath else { return } + let text = chatDurationText(TimeInterval(path.duration)) + if request is AMapDrivingRouteSearchRequest { + rootView.drivingLabel.text = "驾车 约\(text)" + drawDrivingRoute(path) + } else if request is AMapWalkingRouteSearchRequest { + rootView.walkingLabel.text = "步行 约\(text)" + } + } + + func aMapSearchRequest(_ request: Any!, didFailWithError error: Error!) { + if request is AMapDrivingRouteSearchRequest { + rootView.drivingLabel.text = "驾车 路线加载失败" + } else if request is AMapWalkingRouteSearchRequest { + rootView.walkingLabel.text = "步行 路线加载失败" + } + } + + private func drawDrivingRoute(_ path: AMapPath) { + routeOverlays.forEach { rootView.mapView.remove($0) } + routeOverlays.removeAll() + var coordinates: [CLLocationCoordinate2D] = [] + for step in path.steps { + guard let polyline = step.polyline else { continue } + for point in polyline.split(separator: ";") { + let values = point.split(separator: ",") + guard values.count == 2, let longitude = Double(values[0]), let latitude = Double(values[1]) else { continue } + coordinates.append(CLLocationCoordinate2D(latitude: latitude, longitude: longitude)) + } + } + guard coordinates.count > 1 else { return } + var mutableCoordinates = coordinates + if let overlay = MAPolyline(coordinates: &mutableCoordinates, count: UInt(coordinates.count)) { + rootView.mapView.add(overlay) + routeOverlays.append(overlay) + } + } + + func mapView(_ mapView: MAMapView!, viewFor annotation: MAAnnotation!) -> MAAnnotationView! { + if annotation is ChatCurrentLocationAnnotation { + let identifier = "ChatLocationDetailCurrent" + guard let view = (mapView.dequeueReusableAnnotationView(withIdentifier: identifier) as? ChatCurrentLocationAnnotationView) + ?? ChatCurrentLocationAnnotationView(annotation: annotation, reuseIdentifier: identifier) else { return nil } + view.annotation = annotation + view.zIndex = 10 + view.configure() + return view + } + guard annotation is MAPointAnnotation else { return nil } + let identifier = "ChatLocationDetailPin" + guard let view = mapView.dequeueReusableAnnotationView(withIdentifier: identifier) + ?? MAAnnotationView(annotation: annotation, reuseIdentifier: identifier) else { return nil } + view.annotation = annotation + view.image = UIImage(named: "IM/location_pin") + view.centerOffset = CGPoint(x: 0, y: -28) + return view + } + + func mapView(_ mapView: MAMapView!, rendererFor overlay: MAOverlay!) -> MAOverlayRenderer! { + guard let polyline = overlay as? MAPolyline else { return nil } + let renderer = MAPolylineRenderer(polyline: polyline) + renderer?.strokeColor = UIColor(hexStr: "#16B3FF") + renderer?.lineWidth = 4 + return renderer + } +} +#endif + +private final class ChatLocationDetailView: UIView { + #if !targetEnvironment(simulator) + lazy var mapView: MAMapView! = { + let map = MAMapView() + map.showsCompass = false + map.showsScale = false + map.zoomLevel = 15 + return map + }() + #endif + + let backBtn: UIButton = { + let button = UIButton(type: .custom) + button.setImage(UIImage(named: "Common/back"), for: .normal) + button.backgroundColor = .white + button.cornerRadius = 18 + return button + }() + let mapHintLabel: UILabel = { + let label = UILabel() + label.text = "请在真机查看地图" + label.font = .systemFont(ofSize: 13) + label.textColor = UIColor(hexStr: "#7F8794") + label.textAlignment = .center + label.isHidden = true + return label + }() + let nameLabel: UILabel = { + let label = UILabel() + label.font = .systemFont(ofSize: 19, weight: .semibold) + label.textColor = UIColor(hexStr: "#262626") + return label + }() + let addressLabel: UILabel = { + let label = UILabel() + label.font = .systemFont(ofSize: 13) + label.textColor = UIColor(hexStr: "#858585") + label.numberOfLines = 2 + return label + }() + let distanceLabel: UILabel = { + let label = UILabel() + label.font = .systemFont(ofSize: 13) + label.textColor = UIColor(hexStr: "#16B3FF") + label.textAlignment = .center + label.backgroundColor = UIColor(hexStr: "#F4F5F6") + label.cornerRadius = 8 + return label + }() + let drivingLabel: UILabel = routeLabel(icon: "驾", color: UIColor(hexStr: "#16B3FF")) + let walkingLabel: UILabel = routeLabel(icon: "步", color: UIColor(hexStr: "#21B573")) + private let routeStack: UIStackView = { + let stack = UIStackView() + stack.axis = .horizontal + stack.alignment = .fill + stack.distribution = .fillEqually + stack.spacing = 8 + return stack + }() + + override init(frame: CGRect) { + super.init(frame: frame) + backgroundColor = UIColor(hexStr: "#EAF2F3") + setupUI() + } + + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } + + private func setupUI() { + #if !targetEnvironment(simulator) + addSubview(mapView) + mapView.layoutChain.edges() + #endif + addSubview(mapHintLabel) + addSubview(backBtn) + let card = UIView() + card.backgroundColor = .white + card.layer.cornerRadius = 20 + card.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner] + addSubview(card) + card.addSubview(nameLabel) + card.addSubview(addressLabel) + card.addSubview(routeStack) + routeStack.addArrangedSubview(distanceLabel) + routeStack.addArrangedSubview(drivingLabel) + routeStack.addArrangedSubview(walkingLabel) + + backBtn.layoutChain.top(kStatusBarHeight + 10).left(15).width(36).height(36) + mapHintLabel.layoutChain.centerX().centerY().edgesHorzontal(40) + card.layoutChain.edgesHorzontal().bottom().height(210 + kSafeBottomMargin) + nameLabel.layoutChain.top(22).left(20).right(20) + addressLabel.layoutChain.topToBottomOfView(nameLabel, offset: 8).left(20).right(20) + routeStack.layoutChain.topToBottomOfView(addressLabel, offset: 18).edgesHorzontal(20).height(32) + } + + #if !targetEnvironment(simulator) + func cleanupMap() { + mapView?.delegate = nil + mapView?.removeFromSuperview() + mapView = nil + } + #endif + + private static func routeLabel(icon: String, color: UIColor) -> UILabel { + let label = UILabel() + label.text = "\(icon) 路线计算中" + label.font = .systemFont(ofSize: 12, weight: .medium) + label.textAlignment = .center + label.textColor = color + label.backgroundColor = color.withAlphaComponent(0.1) + label.cornerRadius = 8 + return label + } +} + +private func chatDistanceText(_ distance: CLLocationDistance) -> String { + distance >= 1000 ? String(format: "%.1fkm", distance / 1000) : "\(Int(distance))m" +} + +private func chatDurationText(_ duration: TimeInterval) -> String { + let minutes = max(1, Int(ceil(duration / 60))) + return minutes >= 60 ? "\(minutes / 60)小时\(minutes % 60)分钟" : "\(minutes)分钟" +} diff --git a/QuickLocation/Section/Group/GroupChat/GroupChatView.swift b/QuickLocation/Section/Group/GroupChat/GroupChatView.swift index cc231cc4..e0641823 100644 --- a/QuickLocation/Section/Group/GroupChat/GroupChatView.swift +++ b/QuickLocation/Section/Group/GroupChat/GroupChatView.swift @@ -11,6 +11,7 @@ import RxCocoa import Lottie import AVFoundation import SwiftDate +import MapKit enum VoiceRecordState { case began @@ -37,12 +38,16 @@ struct ChatMessage { var atUserIDs: [String] = [] var atNicknames: [String] = [] var isAtAll: Bool = false + var isCircleOwner: Bool = false + var location: ChatLocationPayload? = nil func with(avatar: UIImage? = nil, showTime: Bool? = nil, isUploading: Bool? = nil, imageUrl: String? = nil, - quotePreview: QuotePreview? = nil) -> ChatMessage { + quotePreview: QuotePreview? = nil, + isCircleOwner: Bool? = nil, + location: ChatLocationPayload? = nil) -> ChatMessage { ChatMessage( id: id, isSelf: isSelf, @@ -60,14 +65,16 @@ struct ChatMessage { quotePreview: quotePreview ?? self.quotePreview, atUserIDs: atUserIDs, atNicknames: atNicknames, - isAtAll: isAtAll + isAtAll: isAtAll, + isCircleOwner: isCircleOwner ?? self.isCircleOwner, + location: location ?? self.location ) } /// 正文 attributed(含 @ 高亮) func attributedContent(isOutgoing: Bool) -> NSAttributedString { - let baseColor: UIColor = isOutgoing ? .white : UIColor(hexStr: "#333333") - let atColor: UIColor = isOutgoing ? UIColor(hexStr: "#E8F8FF") : UIColor(hexStr: "#16B3FF") + let baseColor: UIColor = isOutgoing ? UIColor(hexStr: "#293445") : UIColor(hexStr: "#293445") + let atColor: UIColor = isOutgoing ? UIColor(hexStr: "#0086C4") : UIColor(hexStr: "#0086C4") let result = NSMutableAttributedString( string: content, attributes: [ @@ -102,6 +109,7 @@ class GroupChatView: UIView { var bottomBarBottomConstraint: NSLayoutConstraint? /// 语音录制回调 var onVoiceRecordState: ((VoiceRecordState) -> Void)? + var onLocationTap: (() -> Void)? private var emojiPlaybackGeneration = 0 private var quoteBarHeightConstraint: NSLayoutConstraint? @@ -130,7 +138,7 @@ class GroupChatView: UIView { mentionPickerView.isHidden = true if !excludeTextField { textField.resignFirstResponder() } UIView.animate(withDuration: 0.25) { - self.bottomBar.layoutChain.bottom(kSafeBottomMargin + 20) + self.bottomBar.layoutChain.bottom(kSafeBottomMargin) self.voiceRecordView.layoutChain.bottom(-252) } } @@ -175,24 +183,24 @@ class GroupChatView: UIView { // MARK: - Setup private func setupUI() { - backgroundColor = UIColor(hexStr: "#F5FBFB") addSubview(navBgView) addSubview(navBarView) navBarView.addSubview(backBtn) navBarView.addSubview(groupAvatarView) navBarView.addSubview(groupNameLabel) - navBarView.addSubview(onlineStatusLabel) +// navBarView.addSubview(onlineStatusLabel) navBarView.addSubview(rightIconsView) - rightIconsView.addSubview(reviewBtn) +// rightIconsView.addSubview(reviewBtn) rightIconsView.addSubview(memberBtn) rightIconsView.addSubview(settingBtn) - rightIconsView.addSubview(reviewDotView) +// rightIconsView.addSubview(reviewDotView) addSubview(tableView) addSubview(chatWarningView) addSubview(quoteBar) addSubview(mentionPickerView) + addSubview(quickActionBar) addSubview(bottomBar) addSubview(disableIMView) bottomBar.addSubview(bottomBarCornerView) @@ -203,8 +211,10 @@ class GroupChatView: UIView { bottomBar.addSubview(voiceBtn) bottomBar.addSubview(textField) bottomBar.addSubview(emojiBtn) - bottomBar.addSubview(addBtn) bottomBar.addSubview(sendBtn) + quickActionBar.addSubview(galleryBtn) + quickActionBar.addSubview(cameraBtn) + quickActionBar.addSubview(locationBtn) quoteBar.addSubview(quoteBarLabel) quoteBar.addSubview(quoteBarCloseBtn) @@ -220,53 +230,53 @@ class GroupChatView: UIView { .height(kNaviHeight) backBtn.layoutChain - .top(kStatusBarHeight + 12) + .top(kStatusBarHeight + 8) .left(7) - .width(24).height(24) + .width(32).height(32) groupAvatarView.layoutChain .centerY(backBtn) .leftToRightOfView(backBtn, offset: 5) - .width(32).height(32) + .width(30).height(30) groupNameLabel.layoutChain - .topToView(groupAvatarView) .leftToRightOfView(groupAvatarView, offset: 8) + .centerY(groupAvatarView) - onlineStatusLabel.layoutChain - .topToBottomOfView(groupNameLabel, offset: 2) - .leftToView(groupNameLabel) +// onlineStatusLabel.layoutChain +// .topToBottomOfView(groupNameLabel, offset: 2) +// .leftToView(groupNameLabel) rightIconsView.layoutChain .centerY(backBtn) - .right(15) - .height(24) + .right() + .height(32) - reviewBtn.layoutChain - .left().centerY() - .width(24).height(24) +// reviewBtn.layoutChain +// .left().centerY() +// .width(24).height(24) - reviewDotView.layoutChain - .topToView(reviewBtn, offset: -2) - .leftToRightOfView(reviewBtn, offset: -6) - .width(8) - .height(8) - - memberBtn.layoutChain - .leftToRightOfView(reviewBtn, offset: 20) - .centerY() - .width(24).height(24) +// reviewDotView.layoutChain +// .topToView(reviewBtn, offset: -2) +// .leftToRightOfView(reviewBtn, offset: -6) +// .width(8) +// .height(8) settingBtn.layoutChain - .leftToRightOfView(memberBtn, offset: 20) + .right(14) .centerY() - .width(24).height(24) - .right() + .width(32).height(32) + + memberBtn.layoutChain + .left() + .centerY() + .width(32).height(32) + .rightToLeftOfView(settingBtn, offset: -10) tableView.layoutChain .topToBottomOfView(navBarView) .edgesHorzontal() - .bottomToTopOfView(bottomBar) + .bottomToTopOfView(quickActionBar) chatWarningView.layoutChain .topToBottomOfView(navBarView) @@ -274,7 +284,7 @@ class GroupChatView: UIView { quoteBar.layoutChain .edgesHorzontal(15) - .bottomToTopOfView(bottomBar, offset: -6) + .bottomToTopOfView(quickActionBar, offset: -6) quoteBarHeightConstraint = quoteBar.heightAnchor.constraint(equalToConstant: 0) quoteBarHeightConstraint?.isActive = true @@ -293,16 +303,39 @@ class GroupChatView: UIView { mentionPickerContentView.layoutChain.edges() mentionTableView.layoutChain.edges() + + quickActionBar.translatesAutoresizingMaskIntoConstraints = false + galleryBtn.translatesAutoresizingMaskIntoConstraints = false + cameraBtn.translatesAutoresizingMaskIntoConstraints = false + locationBtn.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + quickActionBar.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 10), + quickActionBar.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -10), + quickActionBar.bottomAnchor.constraint(equalTo: bottomBar.topAnchor, constant: -10), + quickActionBar.heightAnchor.constraint(equalToConstant: 40), + galleryBtn.leadingAnchor.constraint(equalTo: quickActionBar.leadingAnchor), + galleryBtn.topAnchor.constraint(equalTo: quickActionBar.topAnchor), + galleryBtn.bottomAnchor.constraint(equalTo: quickActionBar.bottomAnchor), + cameraBtn.leadingAnchor.constraint(equalTo: galleryBtn.trailingAnchor, constant: 11), + cameraBtn.topAnchor.constraint(equalTo: quickActionBar.topAnchor), + cameraBtn.bottomAnchor.constraint(equalTo: quickActionBar.bottomAnchor), + locationBtn.leadingAnchor.constraint(equalTo: cameraBtn.trailingAnchor, constant: 11), + locationBtn.trailingAnchor.constraint(equalTo: quickActionBar.trailingAnchor), + locationBtn.topAnchor.constraint(equalTo: quickActionBar.topAnchor), + locationBtn.bottomAnchor.constraint(equalTo: quickActionBar.bottomAnchor), + galleryBtn.widthAnchor.constraint(equalTo: cameraBtn.widthAnchor), + cameraBtn.widthAnchor.constraint(equalTo: locationBtn.widthAnchor) + ]) bottomBar.layoutChain - .edgesHorzontal(15) + .edgesHorzontal(10) .height(50) - .bottom(kSafeBottomMargin + 20) + .bottom(kSafeBottomMargin) disableIMView.layoutChain .edgesHorzontal(15) .height(50) - .bottom(kSafeBottomMargin + 20) + .bottom(kSafeBottomMargin) bottomBarBottomConstraint = bottomBar.jh_constraint(.bottom, toAttribute: .bottom, otherView: bottomBar.superview, relation: .equal) @@ -313,18 +346,13 @@ class GroupChatView: UIView { .width(28).height(28) sendBtn.layoutChain - .right(19).centerY() - .width(76).height(34) - - addBtn.layoutChain - .rightToLeftOfView(sendBtn, offset: -10) - .centerY() - .width(28).height(28) + .right(10).centerY() + .width(56).height(40) emojiBtn.layoutChain - .rightToLeftOfView(addBtn, offset: -10) + .rightToLeftOfView(sendBtn, offset: -8) .centerY() - .width(28).height(28) + .width(30).height(30) textField.layoutChain .leftToRightOfView(voiceBtn, offset: 10) @@ -358,12 +386,22 @@ class GroupChatView: UIView { let iv = UIImageView() iv.image = UIImage(named: "Common/navBar_bg_2") iv.contentMode = .scaleAspectFill + iv.isHidden = true return iv }() lazy var navBarView: UIView = { let view = UIView() - view.backgroundColor = .clear + view.backgroundColor = UIColor(hexStr: "#F5F5F5") + + let line = UIView() + line.backgroundColor = UIColor(hexStr: "#E6E6E6") + view.addSubview(line) + line.layoutChain + .edgesHorzontal() + .height(0.5) + .bottom() + return view }() @@ -377,7 +415,7 @@ class GroupChatView: UIView { lazy var groupAvatarView: UIImageView = { let iv = UIImageView() iv.contentMode = .scaleAspectFill - iv.cornerRadius = 16 + iv.cornerRadius = 8 iv.clipsToBounds = true iv.backgroundColor = UIColor(hexStr: "#E0E0E0") return iv @@ -422,12 +460,16 @@ class GroupChatView: UIView { lazy var memberBtn: UIButton = { let btn = UIButton(type: .custom) btn.setImage(UIImage(named: "IM/member"), for: .normal) + btn.backgroundColor = .white + btn.cornerRadius = 11 return btn }() lazy var settingBtn: UIButton = { let btn = UIButton(type: .custom) btn.setImage(UIImage(named: "IM/setting"), for: .normal) + btn.backgroundColor = .white + btn.cornerRadius = 11 return btn }() @@ -486,6 +528,8 @@ class GroupChatView: UIView { tv.register(VoiceReceivedMsgCell.self) tv.register(ImageSendMsgCell.self) tv.register(ImageReceivedMsgCell.self) + tv.register(LocationSendMsgCell.self) + tv.register(LocationReceivedMsgCell.self) tv.register(NotificationMsgCell.self) tv.rowHeight = UITableView.automaticDimension tv.contentInset = UIEdgeInsets(top: 8, left: 0, bottom: 8, right: 0) @@ -550,6 +594,27 @@ class GroupChatView: UIView { }() // MARK: - Bottom Bar + lazy var quickActionBar: UIView = { + let view = UIView() + view.backgroundColor = .clear + return view + }() + + lazy var galleryBtn: UIButton = makeQuickActionButton(title: " 照片", imageName: "IM/gallery") + lazy var cameraBtn: UIButton = makeQuickActionButton(title: " 拍照", imageName: "IM/camera") + lazy var locationBtn: UIButton = makeQuickActionButton(title: " 位置", imageName: "IM/location") + + private func makeQuickActionButton(title: String, imageName: String) -> UIButton { + let btn = UIButton(type: .custom) + btn.setTitle(title, for: .normal) + btn.setTitleColor(UIColor(hexStr: "#7F8794"), for: .normal) + btn.setImage(UIImage(named: imageName), for: .normal) + btn.titleLabel?.font = .systemFont(ofSize: 13) + btn.backgroundColor = .white + btn.cornerRadius = 10 + return btn + } + lazy var bottomBar: UIView = { let view = UIView() view.backgroundColor = .clear @@ -563,13 +628,13 @@ class GroupChatView: UIView { lazy var bottomBarCornerView: UIView = { let view = UIView() view.backgroundColor = .white - view.cornerRadius = 25 + view.cornerRadius = 13 return view }() lazy var voiceBtn: UIButton = { let btn = UIButton(type: .custom) - btn.setImage(UIImage(named: "IM/voice"), for: .normal) + btn.setImage(UIImage(named: "IM/voice_input"), for: .normal) return btn }() @@ -587,7 +652,7 @@ class GroupChatView: UIView { lazy var emojiBtn: UIButton = { let btn = UIButton(type: .custom) - btn.setImage(UIImage(named: "IM/emoji"), for: .normal) + btn.setImage(UIImage(named: "IM/emoji_input"), for: .normal) return btn }() @@ -599,13 +664,9 @@ class GroupChatView: UIView { lazy var sendBtn: UIButton = { let btn = UIButton(type: .custom) - btn.setTitle("发送", for: .normal) - btn.setTitleColor(UIColor(hexStr: "#16B3FF"), for: .normal) - btn.titleLabel?.font = .systemFont(ofSize: 13, weight: .medium) - btn.backgroundColor = .white - btn.borderWidth = 1 - btn.borderColor = UIColor(hexStr: "#16B3FF") - btn.cornerRadius = 17 + btn.setImage(UIImage(named: "IM/send"), for: .normal) + btn.backgroundColor = UIColor(hexStr: "#18B5F4") + btn.cornerRadius = 14 return btn }() @@ -683,7 +744,7 @@ class GroupChatView: UIView { override init(frame: CGRect) { super.init(frame: .zero) - backgroundColor = .clear + backgroundColor = UIColor(hexStr: "#F5F5F5") setupUI() setupRx() } @@ -745,10 +806,78 @@ final class ChatQuoteBlockView: UIControl { } } +final class ChatSenderNameView: UIView { + private let ownerLabel: ChatPaddingLabel = { + let label = ChatPaddingLabel() + label.text = "圈主" + label.font = .systemFont(ofSize: 10, weight: .medium) + label.textColor = UIColor(hexStr: "#16B3FF") + label.backgroundColor = UIColor(hexStr: "#DFF6FF") + label.cornerRadius = 6 + label.clipsToBounds = true + label.insets = UIEdgeInsets(top: 2, left: 6, bottom: 2, right: 6) + return label + }() + + private let nameLabel: UILabel = { + let label = UILabel() + label.font = .systemFont(ofSize: 12) + label.textColor = UIColor(hexStr: "#7B7B7B") + label.lineBreakMode = .byTruncatingTail + return label + }() + + private var ownerWidthConstraint: NSLayoutConstraint! + private var spacingConstraint: NSLayoutConstraint! + + override init(frame: CGRect) { + super.init(frame: frame) + addSubview(ownerLabel) + addSubview(nameLabel) + ownerLabel.translatesAutoresizingMaskIntoConstraints = false + nameLabel.translatesAutoresizingMaskIntoConstraints = false + ownerWidthConstraint = ownerLabel.widthAnchor.constraint(equalToConstant: 0) + spacingConstraint = nameLabel.leadingAnchor.constraint(equalTo: ownerLabel.trailingAnchor) + NSLayoutConstraint.activate([ + ownerLabel.leadingAnchor.constraint(equalTo: leadingAnchor), + ownerLabel.centerYAnchor.constraint(equalTo: centerYAnchor), + ownerLabel.heightAnchor.constraint(equalToConstant: 20), + ownerWidthConstraint, + spacingConstraint, + nameLabel.centerYAnchor.constraint(equalTo: centerYAnchor), + nameLabel.trailingAnchor.constraint(equalTo: trailingAnchor), + heightAnchor.constraint(equalToConstant: 20) + ]) + } + + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } + + func configure(name: String, isOwner: Bool) { + nameLabel.text = name + ownerLabel.isHidden = !isOwner + ownerWidthConstraint.constant = isOwner ? ownerLabel.intrinsicContentSize.width : 0 + spacingConstraint.constant = isOwner ? 6 : 0 + } +} + +private final class ChatPaddingLabel: UILabel { + var insets = UIEdgeInsets.zero + + override func drawText(in rect: CGRect) { + super.drawText(in: rect.inset(by: insets)) + } + + override var intrinsicContentSize: CGSize { + let size = super.intrinsicContentSize + return CGSize(width: size.width + insets.left + insets.right, + height: size.height + insets.top + insets.bottom) + } +} + // MARK: - 气泡上方操作菜单 final class ChatBubbleActionMenu: UIView { - var onQuote: (() -> Void)? - var onRevoke: (() -> Void)? + var onMention: (() -> Void)? + var onReply: (() -> Void)? var onDismiss: (() -> Void)? private let panel = UIView() @@ -787,7 +916,7 @@ final class ChatBubbleActionMenu: UIView { stack.leadingAnchor.constraint(equalTo: panel.leadingAnchor), stack.trailingAnchor.constraint(equalTo: panel.trailingAnchor), stack.bottomAnchor.constraint(equalTo: panel.bottomAnchor), - panel.heightAnchor.constraint(equalToConstant: 44) + panel.heightAnchor.constraint(equalToConstant: 68) ]) arrow.backgroundColor = UIColor(hexStr: "#333333") @@ -796,7 +925,7 @@ final class ChatBubbleActionMenu: UIView { required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } - func show(in host: UIView, anchor: UIView, showRevoke: Bool) { + func show(in host: UIView, anchor: UIView, canMention: Bool) { removeFromSuperview() host.addSubview(self) frame = host.bounds @@ -806,22 +935,22 @@ final class ChatBubbleActionMenu: UIView { stack.removeArrangedSubview($0) $0.removeFromSuperview() } - let quoteBtn = makeButton(title: "引用", action: #selector(handleQuote)) - quoteBtn.widthAnchor.constraint(equalToConstant: 72).isActive = true - stack.addArrangedSubview(quoteBtn) - if showRevoke { + if canMention { + let mentionBtn = makeButton(title: "@TA", imageName: "IM/at", action: #selector(handleMention)) + mentionBtn.widthAnchor.constraint(equalToConstant: 72).isActive = true + stack.addArrangedSubview(mentionBtn) let sep = UIView() sep.backgroundColor = UIColor.white.withAlphaComponent(0.2) sep.translatesAutoresizingMaskIntoConstraints = false sep.widthAnchor.constraint(equalToConstant: 1).isActive = true stack.addArrangedSubview(sep) - let revokeBtn = makeButton(title: "撤回", action: #selector(handleRevoke)) - revokeBtn.widthAnchor.constraint(equalToConstant: 72).isActive = true - stack.addArrangedSubview(revokeBtn) } + let replyBtn = makeButton(title: "回复", imageName: "IM/reply", action: #selector(handleReply)) + replyBtn.widthAnchor.constraint(equalToConstant: 72).isActive = true + stack.addArrangedSubview(replyBtn) - let panelW: CGFloat = showRevoke ? 145 : 72 - let panelH: CGFloat = 44 + let panelW: CGFloat = canMention ? 145 : 72 + let panelH: CGFloat = 68 let arrowSize: CGFloat = 8 let gap: CGFloat = 6 @@ -850,23 +979,29 @@ final class ChatBubbleActionMenu: UIView { UIView.animate(withDuration: 0.15) { self.alpha = 1 } } - private func makeButton(title: String, action: Selector) -> UIButton { + private func makeButton(title: String, imageName: String, action: Selector) -> UIButton { let btn = UIButton(type: .system) btn.setTitle(title, for: .normal) + btn.setImage(UIImage(named: imageName)?.withRenderingMode(.alwaysOriginal), for: .normal) btn.setTitleColor(.white, for: .normal) - btn.titleLabel?.font = .systemFont(ofSize: 14, weight: .medium) + btn.titleLabel?.font = .systemFont(ofSize: 12, weight: .medium) + btn.imageView?.contentMode = .scaleAspectFit + btn.contentHorizontalAlignment = .center + btn.contentVerticalAlignment = .center + btn.imageEdgeInsets = UIEdgeInsets(top: -18, left: 17, bottom: 0, right: -17) + btn.titleEdgeInsets = UIEdgeInsets(top: 30, left: -14, bottom: 0, right: 14) btn.addTarget(self, action: action, for: .touchUpInside) btn.translatesAutoresizingMaskIntoConstraints = false return btn } - @objc private func handleQuote() { - onQuote?() + @objc private func handleMention() { + onMention?() dismiss() } - @objc private func handleRevoke() { - onRevoke?() + @objc private func handleReply() { + onReply?() dismiss() } @@ -902,6 +1037,7 @@ class TextSendMsgCell: UITableViewCell { timeLabel.isHidden = !msg.showTime timeLabel.text = msg.showTime ? chatFormatTime(msg.timestamp) : nil avatarView.image = msg.avatar + senderNameView.configure(name: msg.senderName, isOwner: msg.isCircleOwner) contentLabel.attributedText = msg.attributedContent(isOutgoing: true) let hasQuote = msg.quotePreview != nil quoteBlock.configure(msg.quotePreview) @@ -928,23 +1064,28 @@ class TextSendMsgCell: UITableViewCell { let avatarView: UIImageView = { let iv = UIImageView() iv.contentMode = .scaleAspectFill - iv.cornerRadius = 15 + iv.cornerRadius = 10 iv.clipsToBounds = true iv.backgroundColor = UIColor(hexStr: "#E0E0E0") - iv.borderWidth = 2 - iv.borderColor = .white +// iv.borderWidth = 2 +// iv.borderColor = .white return iv }() private let bubbleView: UIView = { let v = UIView() - v.backgroundColor = UIColor(hexStr: "#16B3FF") + v.backgroundColor = UIColor(hexStr: "#C9EEFF") + v.cornerRadius = 10 + v.layer.maskedCorners = [.layerMinXMinYCorner, .layerMinXMaxYCorner, .layerMaxXMaxYCorner] return v }() + private let senderNameView = ChatSenderNameView() + private let contentLabel: UILabel = { let label = UILabel() - label.font = .systemFont(ofSize: 14) + label.font = .systemFont(ofSize: 14, weight: .medium) + label.textColor = UIColor(hexStr: "#293445") label.numberOfLines = 0 return label }() @@ -963,27 +1104,37 @@ class TextSendMsgCell: UITableViewCell { bubbleView.addSubview(contentLabel) contentView.addSubview(quoteBlock) contentView.addSubview(avatarView) + contentView.addSubview(senderNameView) timeLabel.layoutChain.top().centerX() + avatarView.layoutChain - .topToBottomOfView(timeLabel, offset: 14) - .right(12).width(30).height(30) + .topToBottomOfView(timeLabel, offset: 10) + .right(12).width(38).height(38) + + senderNameView.translatesAutoresizingMaskIntoConstraints = false + senderNameView.layoutChain + .topToView(avatarView) + .rightToLeftOfView(avatarView, offset: -9) +// NSLayoutConstraint.activate([ +// senderNameView.trailingAnchor.constraint(equalTo: avatarView.leadingAnchor, constant: -5), +// senderNameView.bottomAnchor.constraint(equalTo: avatarView.bottomAnchor), +// senderNameView.leadingAnchor.constraint(greaterThanOrEqualTo: contentView.leadingAnchor, constant: 80) +// ]) + bubbleView.layoutChain - .topToBottomOfView(avatarView, offset: -15) - .rightToView(avatarView, offset: -13) + .topToBottomOfView(senderNameView, offset: 5) + .rightToView(senderNameView) .left(60, relation: .greaterThanOrEqual) .width(100, relation: .greaterThanOrEqual) .height(30, relation: .greaterThanOrEqual) contentLabel.translatesAutoresizingMaskIntoConstraints = false + contentLabel.layoutChain + .edgesVertical(13) + .edgesHorzontal(12) + quoteBlock.translatesAutoresizingMaskIntoConstraints = false - NSLayoutConstraint.activate([ - contentLabel.topAnchor.constraint(equalTo: bubbleView.topAnchor, constant: 10), - contentLabel.leadingAnchor.constraint(equalTo: bubbleView.leadingAnchor, constant: 20), - contentLabel.trailingAnchor.constraint(equalTo: bubbleView.trailingAnchor, constant: -20), - contentLabel.bottomAnchor.constraint(equalTo: bubbleView.bottomAnchor, constant: -10) - ]) - let qTop = quoteBlock.topAnchor.constraint(equalTo: bubbleView.bottomAnchor, constant: 4) let qH = quoteBlock.heightAnchor.constraint(equalToConstant: 0) quoteTopConstraint = qTop @@ -1005,10 +1156,6 @@ class TextSendMsgCell: UITableViewCell { override func layoutSubviews() { super.layoutSubviews() - bubbleView.setNeedsLayout() - bubbleView.layoutIfNeeded() - bubbleView.setCornerRadius(corners: [.topLeft, .bottomLeft, .bottomRight], - withCornerRadii: CGSize(width: bubbleView.dl.height / 2, height: bubbleView.dl.height / 2)) } } @@ -1028,7 +1175,7 @@ class TextReceivedMsgCell: UITableViewCell { timeLabel.isHidden = !msg.showTime timeLabel.text = msg.showTime ? chatFormatTime(msg.timestamp) : nil avatarView.image = msg.avatar - nameLabel.text = msg.senderName + senderNameView.configure(name: msg.senderName, isOwner: msg.isCircleOwner) contentLabel.attributedText = msg.attributedContent(isOutgoing: false) let hasQuote = msg.quotePreview != nil quoteBlock.configure(msg.quotePreview) @@ -1052,31 +1199,28 @@ class TextReceivedMsgCell: UITableViewCell { return label }() - private let nameLabel: UILabel = { - let label = UILabel() - label.font = .systemFont(ofSize: 10, weight: .regular) - label.textColor = UIColor(hexStr: "#666666") - return label - }() - let avatarView: UIImageView = { let iv = UIImageView() iv.contentMode = .scaleAspectFill - iv.cornerRadius = 15 + iv.cornerRadius = 10 iv.clipsToBounds = true iv.backgroundColor = UIColor(hexStr: "#E0E0E0") - iv.borderWidth = 2 - iv.borderColor = .white +// iv.borderWidth = 2 +// iv.borderColor = .white iv.isUserInteractionEnabled = true return iv }() private let bubbleView: UIView = { let v = UIView() - v.backgroundColor = UIColor(hexStr: "#CCEAFF") + v.backgroundColor = UIColor(hexStr: "#FFFFFF") + v.cornerRadius = 10 + v.layer.maskedCorners = [.layerMaxXMinYCorner, .layerMinXMaxYCorner, .layerMaxXMaxYCorner] return v }() + private let senderNameView = ChatSenderNameView() + private let contentLabel: UILabel = { let label = UILabel() label.font = .systemFont(ofSize: 14) @@ -1098,42 +1242,40 @@ class TextReceivedMsgCell: UITableViewCell { bubbleView.addSubview(contentLabel) contentView.addSubview(quoteBlock) contentView.addSubview(avatarView) - contentView.addSubview(nameLabel) + contentView.addSubview(senderNameView) timeLabel.layoutChain.top().centerX() + + avatarView.layoutChain + .topToBottomOfView(timeLabel, offset: 10) + .left(12).width(38).height(38) + + senderNameView.translatesAutoresizingMaskIntoConstraints = false + senderNameView.layoutChain + .topToView(avatarView) + .leftToRightOfView(avatarView, offset: 9) + bubbleView.layoutChain - .topToBottomOfView(timeLabel, offset: 14) - .left(30) + .topToBottomOfView(senderNameView, offset: 5) + .leftToView(senderNameView) .right(60, relation: .greaterThanOrEqual) .width(100, relation: .greaterThanOrEqual) .height(30, relation: .greaterThanOrEqual) contentLabel.translatesAutoresizingMaskIntoConstraints = false + contentLabel.layoutChain + .edgesVertical(13) + .edgesHorzontal(12) + quoteBlock.translatesAutoresizingMaskIntoConstraints = false - avatarView.translatesAutoresizingMaskIntoConstraints = false - nameLabel.translatesAutoresizingMaskIntoConstraints = false - NSLayoutConstraint.activate([ - contentLabel.topAnchor.constraint(equalTo: bubbleView.topAnchor, constant: 10), - contentLabel.leadingAnchor.constraint(equalTo: bubbleView.leadingAnchor, constant: 20), - contentLabel.trailingAnchor.constraint(equalTo: bubbleView.trailingAnchor, constant: -20), - contentLabel.bottomAnchor.constraint(equalTo: bubbleView.bottomAnchor, constant: -10), - // 头像 + 昵称贴在气泡下方 - avatarView.topAnchor.constraint(equalTo: bubbleView.bottomAnchor, constant: -15), - avatarView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 12), - avatarView.widthAnchor.constraint(equalToConstant: 30), - avatarView.heightAnchor.constraint(equalToConstant: 30), - nameLabel.leadingAnchor.constraint(equalTo: avatarView.trailingAnchor, constant: 5), - nameLabel.bottomAnchor.constraint(equalTo: avatarView.bottomAnchor) - ]) - - // 引用在 senderName 下方 - let qTop = quoteBlock.topAnchor.constraint(equalTo: nameLabel.bottomAnchor, constant: 4) + // 引用在 bubbleView 下方 + let qTop = quoteBlock.topAnchor.constraint(equalTo: bubbleView.bottomAnchor, constant: 4) let qH = quoteBlock.heightAnchor.constraint(equalToConstant: 0) quoteTopConstraint = qTop quoteHeightConstraint = qH NSLayoutConstraint.activate([ qTop, - quoteBlock.leadingAnchor.constraint(equalTo: nameLabel.leadingAnchor), + quoteBlock.leadingAnchor.constraint(equalTo: senderNameView.leadingAnchor), quoteBlock.trailingAnchor.constraint(lessThanOrEqualTo: contentView.trailingAnchor, constant: -60), quoteBlock.widthAnchor.constraint(lessThanOrEqualTo: bubbleView.widthAnchor), quoteBlock.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -10), @@ -1148,10 +1290,6 @@ class TextReceivedMsgCell: UITableViewCell { override func layoutSubviews() { super.layoutSubviews() - bubbleView.setNeedsLayout() - bubbleView.layoutIfNeeded() - bubbleView.setCornerRadius(corners: [.topLeft, .topRight, .bottomRight], - withCornerRadii: CGSize(width: bubbleView.dl.height / 2, height: bubbleView.dl.height / 2)) } } @@ -1216,17 +1354,19 @@ final class EmojiSendMsgCell: UITableViewCell { return label }() - private let avatarView: UIImageView = { + let avatarView: UIImageView = { let iv = UIImageView() iv.contentMode = .scaleAspectFill - iv.cornerRadius = 15 + iv.cornerRadius = 10 iv.clipsToBounds = true iv.backgroundColor = UIColor(hexStr: "#E0E0E0") - iv.borderWidth = 2 - iv.borderColor = .white +// iv.borderWidth = 2 +// iv.borderColor = .white return iv }() + private let senderNameView = ChatSenderNameView() + private let lottieView: LottieAnimationView = { let v = LottieAnimationView() v.contentMode = .scaleAspectFit @@ -1243,17 +1383,27 @@ final class EmojiSendMsgCell: UITableViewCell { backgroundColor = .clear contentView.addSubview(timeLabel) contentView.addSubview(avatarView) + contentView.addSubview(senderNameView) contentView.addSubview(lottieView) timeLabel.layoutChain.top().centerX() + avatarView.layoutChain + .topToBottomOfView(timeLabel, offset: 10) + .right(12).width(38).height(38) + + senderNameView.translatesAutoresizingMaskIntoConstraints = false + senderNameView.layoutChain + .topToView(avatarView) + .rightToLeftOfView(avatarView, offset: -9) + avatarView.layoutChain .topToBottomOfView(timeLabel, offset: 14) .right(12) .width(30).height(30) lottieView.layoutChain - .topToBottomOfView(avatarView, offset: -15) + .topToBottomOfView(senderNameView, offset: 5) .right(60) .width(60).height(60) .bottom(10) @@ -1267,6 +1417,7 @@ final class EmojiSendMsgCell: UITableViewCell { timeLabel.isHidden = !msg.showTime timeLabel.text = msg.showTime ? chatFormatTime(msg.timestamp) : nil avatarView.image = msg.avatar + senderNameView.configure(name: msg.senderName, isOwner: msg.isCircleOwner) let index = Int(msg.content.replacingOccurrences(of: "js_emoji:", with: "")) ?? 0 guard Self.emojiFileNames.indices.contains(index) else { animationName = nil @@ -1323,21 +1474,16 @@ final class EmojiReceivedMsgCell: UITableViewCell { let avatarView: UIImageView = { let iv = UIImageView() iv.contentMode = .scaleAspectFill - iv.cornerRadius = 15 + iv.cornerRadius = 10 iv.clipsToBounds = true iv.backgroundColor = UIColor(hexStr: "#E0E0E0") - iv.borderWidth = 2 - iv.borderColor = .white +// iv.borderWidth = 2 +// iv.borderColor = .white iv.isUserInteractionEnabled = true return iv }() - private let nameLabel: UILabel = { - let label = UILabel() - label.font = .systemFont(ofSize: 10, weight: .regular) - label.textColor = UIColor(hexStr: "#666666") - return label - }() + private let senderNameView = ChatSenderNameView() private let lottieView: LottieAnimationView = { let v = LottieAnimationView() @@ -1355,25 +1501,25 @@ final class EmojiReceivedMsgCell: UITableViewCell { backgroundColor = .clear contentView.addSubview(timeLabel) contentView.addSubview(avatarView) - contentView.addSubview(nameLabel) + contentView.addSubview(senderNameView) contentView.addSubview(lottieView) timeLabel.layoutChain.top().centerX() + avatarView.layoutChain + .topToBottomOfView(timeLabel, offset: 10) + .left(12).width(38).height(38) + + senderNameView.translatesAutoresizingMaskIntoConstraints = false + senderNameView.layoutChain + .topToView(avatarView) + .leftToRightOfView(avatarView, offset: 9) + lottieView.layoutChain - .topToBottomOfView(timeLabel, offset: 14) + .topToBottomOfView(senderNameView, offset: 5) .left(60) .width(60).height(60) - - avatarView.layoutChain - .topToBottomOfView(lottieView, offset: -15) - .left(12) - .width(30).height(30) .bottom(10) - - nameLabel.layoutChain - .leftToRightOfView(avatarView, offset: 5) - .bottomToView(avatarView) } required init?(coder: NSCoder) { @@ -1384,7 +1530,7 @@ final class EmojiReceivedMsgCell: UITableViewCell { timeLabel.isHidden = !msg.showTime timeLabel.text = msg.showTime ? chatFormatTime(msg.timestamp) : nil avatarView.image = msg.avatar - nameLabel.text = msg.senderName + senderNameView.configure(name: msg.senderName, isOwner: msg.isCircleOwner) let index = Int(msg.content.replacingOccurrences(of: "js_emoji:", with: "")) ?? 0 guard Self.emojiFileNames.indices.contains(index) else { animationName = nil @@ -1473,20 +1619,24 @@ final class VoiceSendMsgCell: UITableViewCell, VoicePlaybackView { return label }() - private let avatarView: UIImageView = { + let avatarView: UIImageView = { let iv = UIImageView() iv.contentMode = .scaleAspectFill - iv.cornerRadius = 15 + iv.cornerRadius = 10 iv.clipsToBounds = true iv.backgroundColor = UIColor(hexStr: "#E0E0E0") - iv.borderWidth = 2 - iv.borderColor = .white +// iv.borderWidth = 2 +// iv.borderColor = .white return iv }() + private let senderNameView = ChatSenderNameView() + private let bubbleView: UIView = { let v = UIView() - v.backgroundColor = UIColor(hexStr: "#16B3FF") + v.backgroundColor = UIColor(hexStr: "#C9EEFF") + v.cornerRadius = 10 + v.layer.maskedCorners = [.layerMinXMinYCorner, .layerMinXMaxYCorner, .layerMaxXMaxYCorner] return v }() @@ -1516,18 +1666,25 @@ final class VoiceSendMsgCell: UITableViewCell, VoicePlaybackView { bubbleView.addSubview(playAnimation) bubbleView.addSubview(durationLabel) contentView.addSubview(avatarView) + contentView.addSubview(senderNameView) let tap = UITapGestureRecognizer(target: self, action: #selector(togglePlay)) bubbleView.addGestureRecognizer(tap) timeLabel.layoutChain.top().centerX() + avatarView.layoutChain - .topToBottomOfView(timeLabel, offset: 14) - .right(12).width(30).height(30) + .topToBottomOfView(timeLabel, offset: 10) + .right(12).width(38).height(38) + + senderNameView.translatesAutoresizingMaskIntoConstraints = false + senderNameView.layoutChain + .topToView(avatarView) + .rightToLeftOfView(avatarView, offset: -9) bubbleView.layoutChain - .topToBottomOfView(avatarView, offset: -15) - .rightToView(avatarView, offset: -13) + .topToBottomOfView(senderNameView, offset: 5) + .rightToView(senderNameView) .width(105).height(39).bottom(10) playAnimation.layoutChain @@ -1548,6 +1705,7 @@ final class VoiceSendMsgCell: UITableViewCell, VoicePlaybackView { timeLabel.isHidden = !msg.showTime timeLabel.text = msg.showTime ? chatFormatTime(msg.timestamp) : nil avatarView.image = msg.avatar + senderNameView.configure(name: msg.senderName, isOwner: msg.isCircleOwner) let dur = msg.content.int / 1000 durationLabel.text = dur > 0 ? "\(dur)''" : "" voiceUrl = msg.voiceUrl @@ -1580,10 +1738,6 @@ final class VoiceSendMsgCell: UITableViewCell, VoicePlaybackView { override func layoutSubviews() { super.layoutSubviews() - bubbleView.setNeedsLayout() - bubbleView.layoutIfNeeded() - bubbleView.setCornerRadius(corners: [.topLeft , .bottomRight, .bottomLeft], - withCornerRadii: CGSize(width: bubbleView.dl.height / 2, height: bubbleView.dl.height / 2)) } } @@ -1595,7 +1749,7 @@ final class VoiceReceivedMsgCell: UITableViewCell, VoicePlaybackView { timeLabel.isHidden = !msg.showTime timeLabel.text = msg.showTime ? chatFormatTime(msg.timestamp) : nil avatarView.image = msg.avatar - nameLabel.text = msg.senderName + senderNameView.configure(name: msg.senderName, isOwner: msg.isCircleOwner) let dur = msg.content.int / 1000 durationLabel.text = dur > 0 ? "\(dur)''" : "" voiceUrl = msg.voiceUrl @@ -1632,25 +1786,21 @@ final class VoiceReceivedMsgCell: UITableViewCell, VoicePlaybackView { let avatarView: UIImageView = { let iv = UIImageView() iv.contentMode = .scaleAspectFill - iv.cornerRadius = 15 + iv.cornerRadius = 10 iv.clipsToBounds = true iv.backgroundColor = UIColor(hexStr: "#E0E0E0") - iv.borderWidth = 2 - iv.borderColor = .white - iv.isUserInteractionEnabled = true +// iv.borderWidth = 2 +// iv.borderColor = .white return iv }() - private let nameLabel: UILabel = { - let label = UILabel() - label.font = .systemFont(ofSize: 10, weight: .regular) - label.textColor = UIColor(hexStr: "#666666") - return label - }() + private let senderNameView = ChatSenderNameView() private let bubbleView: UIView = { let v = UIView() - v.backgroundColor = UIColor(hexStr: "#CCEAFF") + v.backgroundColor = UIColor(hexStr: "#FFFFFF") + v.cornerRadius = 10 + v.layer.maskedCorners = [.layerMaxXMinYCorner, .layerMinXMaxYCorner, .layerMaxXMaxYCorner] return v }() @@ -1681,29 +1831,28 @@ final class VoiceReceivedMsgCell: UITableViewCell, VoicePlaybackView { bubbleView.addSubview(playAnimation) bubbleView.addSubview(durationLabel) contentView.addSubview(avatarView) - contentView.addSubview(nameLabel) + contentView.addSubview(senderNameView) let tap = UITapGestureRecognizer(target: self, action: #selector(togglePlay)) bubbleView.addGestureRecognizer(tap) timeLabel.layoutChain.top().centerX() + avatarView.layoutChain + .topToBottomOfView(timeLabel, offset: 10) + .left(12).width(38).height(38) + + senderNameView.translatesAutoresizingMaskIntoConstraints = false + senderNameView.layoutChain + .topToView(avatarView) + .leftToRightOfView(avatarView, offset: 9) + bubbleView.layoutChain - .topToBottomOfView(timeLabel, offset: 14) + .topToBottomOfView(senderNameView, offset: 5) + .leftToView(senderNameView) .width(105) .height(39) - - avatarView.layoutChain - .topToBottomOfView(bubbleView, offset: -15) - .left(12) - .width(30).height(30) .bottom(10) - bubbleView.layoutChain.leftToView(avatarView, offset: 13) - - nameLabel.layoutChain - .leftToRightOfView(avatarView, offset: 5) - .bottomToView(avatarView) - playAnimation.layoutChain .left(36) .centerY() @@ -1725,10 +1874,6 @@ final class VoiceReceivedMsgCell: UITableViewCell, VoicePlaybackView { override func layoutSubviews() { super.layoutSubviews() - bubbleView.setNeedsLayout() - bubbleView.layoutIfNeeded() - bubbleView.setCornerRadius(corners: [.topLeft , .topRight, .bottomRight], - withCornerRadii: CGSize(width: bubbleView.dl.height / 2, height: bubbleView.dl.height / 2)) } } @@ -1742,6 +1887,7 @@ final class ImageSendMsgCell: UITableViewCell { timeLabel.isHidden = !msg.showTime timeLabel.text = msg.showTime ? chatFormatTime(msg.timestamp) : nil avatarView.image = msg.avatar + senderNameView.configure(name: msg.senderName, isOwner: msg.isCircleOwner) if !msg.imageUrl.isEmpty { if let localImage = UIImage(contentsOfFile: msg.imageUrl) { photoView.image = localImage @@ -1771,17 +1917,19 @@ final class ImageSendMsgCell: UITableViewCell { return label }() - private let avatarView: UIImageView = { + let avatarView: UIImageView = { let iv = UIImageView() iv.contentMode = .scaleAspectFill - iv.cornerRadius = 15 + iv.cornerRadius = 10 iv.clipsToBounds = true iv.backgroundColor = UIColor(hexStr: "#E0E0E0") - iv.borderWidth = 2 - iv.borderColor = .white +// iv.borderWidth = 2 +// iv.borderColor = .white return iv }() + private let senderNameView = ChatSenderNameView() + lazy var photoView: UIImageView = { let iv = UIImageView() iv.contentMode = .scaleAspectFill @@ -1799,6 +1947,7 @@ final class ImageSendMsgCell: UITableViewCell { contentView.addSubview(timeLabel) contentView.addSubview(photoView) contentView.addSubview(avatarView) + contentView.addSubview(senderNameView) let tap = UITapGestureRecognizer(target: self, action: #selector(onTap)) photoView.addGestureRecognizer(tap) @@ -1806,13 +1955,19 @@ final class ImageSendMsgCell: UITableViewCell { loadingView.layoutChain.centerX().centerY() timeLabel.layoutChain.top().centerX() + avatarView.layoutChain - .topToBottomOfView(timeLabel, offset: 14) - .right(12).width(30).height(30) + .topToBottomOfView(timeLabel, offset: 10) + .right(12).width(38).height(38) + + senderNameView.translatesAutoresizingMaskIntoConstraints = false + senderNameView.layoutChain + .topToView(avatarView) + .rightToLeftOfView(avatarView, offset: -9) photoView.layoutChain - .topToBottomOfView(avatarView, offset: -15) - .rightToView(avatarView, offset: -13) + .topToBottomOfView(senderNameView, offset: 5) + .rightToView(senderNameView, offset: 0) .bottom(10) } @@ -1830,7 +1985,7 @@ final class ImageReceivedMsgCell: UITableViewCell { timeLabel.isHidden = !msg.showTime timeLabel.text = msg.showTime ? chatFormatTime(msg.timestamp) : nil avatarView.image = msg.avatar - nameLabel.text = msg.senderName + senderNameView.configure(name: msg.senderName, isOwner: msg.isCircleOwner) if !msg.imageUrl.isEmpty { photoView.dl.setImage(with: msg.imageUrl) } @@ -1850,21 +2005,15 @@ final class ImageReceivedMsgCell: UITableViewCell { let avatarView: UIImageView = { let iv = UIImageView() iv.contentMode = .scaleAspectFill - iv.cornerRadius = 15 + iv.cornerRadius = 10 iv.clipsToBounds = true iv.backgroundColor = UIColor(hexStr: "#E0E0E0") - iv.borderWidth = 2 - iv.borderColor = .white - iv.isUserInteractionEnabled = true +// iv.borderWidth = 2 +// iv.borderColor = .white return iv }() - private let nameLabel: UILabel = { - let label = UILabel() - label.font = .systemFont(ofSize: 10, weight: .regular) - label.textColor = UIColor(hexStr: "#666666") - return label - }() + private let senderNameView = ChatSenderNameView() lazy var photoView: UIImageView = { let iv = UIImageView() @@ -1881,7 +2030,7 @@ final class ImageReceivedMsgCell: UITableViewCell { selectionStyle = .none backgroundColor = .clear contentView.addSubview(timeLabel) - contentView.addSubview(nameLabel) + contentView.addSubview(senderNameView) contentView.addSubview(photoView) contentView.addSubview(avatarView) @@ -1890,24 +2039,229 @@ final class ImageReceivedMsgCell: UITableViewCell { timeLabel.layoutChain.top().centerX() - photoView.layoutChain - .topToBottomOfView(timeLabel, offset: 14) - .width(160).height(160) - avatarView.layoutChain - .topToBottomOfView(photoView, offset: -15) - .left(12) - .width(30).height(30) + .topToBottomOfView(timeLabel, offset: 10) + .left(12).width(38).height(38) + + senderNameView.translatesAutoresizingMaskIntoConstraints = false + senderNameView.layoutChain + .topToView(avatarView) + .leftToRightOfView(avatarView, offset: 9) + + photoView.layoutChain + .topToBottomOfView(senderNameView, offset: 5) + .leftToView(senderNameView) + .width(160).height(160) .bottom(10) - - photoView.layoutChain.leftToView(avatarView, offset: 13) - - nameLabel.layoutChain - .leftToRightOfView(avatarView, offset: 5) - .bottomToView(avatarView) } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } } + +// MARK: - 位置消息 +final class LocationSendMsgCell: ChatLocationMsgCell { + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier, isOutgoing: true) + } + + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } +} + +final class LocationReceivedMsgCell: ChatLocationMsgCell { + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier, isOutgoing: false) + } + + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } +} + +class ChatLocationMsgCell: UITableViewCell { + var onLocationTap: (() -> Void)? + var menuAnchorView: UIView { cardView } + + private let isOutgoing: Bool + private let timeLabel: UILabel = { + let label = UILabel() + label.font = .systemFont(ofSize: 12) + label.textColor = UIColor(hexStr: "#999999") + label.textAlignment = .center + return label + }() + private let avatarView: UIImageView = { + let iv = UIImageView() + iv.contentMode = .scaleAspectFill + iv.cornerRadius = 10 + iv.clipsToBounds = true + iv.backgroundColor = UIColor(hexStr: "#E0E0E0") +// iv.borderWidth = 2 +// iv.borderColor = .white + return iv + }() + private let senderNameView = ChatSenderNameView() + private let cardView: UIControl = { + let view = UIControl() + view.backgroundColor = .white + view.cornerRadius = 10 + view.clipsToBounds = true + return view + }() + private let mapPreview = ChatLocationMapPreview() + private let titleLabel: UILabel = { + let label = UILabel() + label.font = .systemFont(ofSize: 14, weight: .bold) + label.textColor = UIColor(hexStr: "#293445") + return label + }() + private let addressLabel: UILabel = { + let label = UILabel() + label.font = .systemFont(ofSize: 12, weight: .medium) + label.textColor = UIColor(hexStr: "#AAAAAA") + return label + }() + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + self.isOutgoing = false + super.init(style: style, reuseIdentifier: reuseIdentifier) + setupUI() + } + + init(style: UITableViewCell.CellStyle, reuseIdentifier: String?, isOutgoing: Bool) { + self.isOutgoing = isOutgoing + super.init(style: style, reuseIdentifier: reuseIdentifier) + selectionStyle = .none + backgroundColor = .clear + setupUI() + } + + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } + + func configure(_ msg: ChatMessage) { + timeLabel.isHidden = !msg.showTime + timeLabel.text = msg.showTime ? chatFormatTime(msg.timestamp) : nil + avatarView.image = msg.avatar + senderNameView.configure(name: msg.senderName, isOwner: msg.isCircleOwner) + let location = msg.location ?? ChatLocationPayload(name: msg.content, address: "", latitude: 0, longitude: 0) + titleLabel.text = location.name.isEmpty ? "位置" : location.name + addressLabel.text = location.address.isEmpty ? "暂无详细地址" : location.address + mapPreview.configure(location: location) + } + + private func setupUI() { + selectionStyle = .none + backgroundColor = .clear + contentView.addSubview(timeLabel) + contentView.addSubview(cardView) + contentView.addSubview(avatarView) + contentView.addSubview(senderNameView) + cardView.addSubview(titleLabel) + cardView.addSubview(addressLabel) + cardView.addTarget(self, action: #selector(handleLocationTap), for: .touchUpInside) + + timeLabel.layoutChain.top().centerX() + cardView.translatesAutoresizingMaskIntoConstraints = false + avatarView.translatesAutoresizingMaskIntoConstraints = false + senderNameView.translatesAutoresizingMaskIntoConstraints = false + + titleLabel.layoutChain + .top(11) + .left(10) + + addressLabel.layoutChain + .topToBottomOfView(titleLabel, offset: 8) + .edgesHorzontal(10) + + if isOutgoing { + avatarView.layoutChain + .topToBottomOfView(timeLabel, offset: 10) + .right(12).width(38).height(38) + + senderNameView.layoutChain + .topToView(avatarView) + .rightToLeftOfView(avatarView, offset: -9) + + cardView.layoutChain + .topToBottomOfView(senderNameView, offset: 5) + .rightToView(senderNameView) + .width(250) + .height(148) + .bottom(10) + } else { + avatarView.layoutChain + .topToBottomOfView(timeLabel, offset: 10) + .left(12).width(38).height(38) + + senderNameView.layoutChain + .topToView(avatarView) + .leftToRightOfView(avatarView, offset: 9) + + cardView.layoutChain + .topToBottomOfView(senderNameView, offset: 5) + .leftToView(senderNameView) + .width(250) + .height(148) + .bottom(10) + } + } + + @objc private func handleLocationTap() { onLocationTap?() } +} + +private final class ChatLocationMapPreview: UIView { + private let imageView = UIImageView() + private let pinView: UIView = { + let view = UIView() + view.backgroundColor = UIColor(hexStr: "#16B3FF") + view.cornerRadius = 10 + view.borderWidth = 3 + view.borderColor = .white + view.layer.shadowColor = UIColor.black.cgColor + view.layer.shadowOpacity = 0.18 + view.layer.shadowRadius = 3 + view.layer.shadowOffset = CGSize(width: 0, height: 1) + return view + }() + private var requestID = UUID() + + override init(frame: CGRect) { + super.init(frame: frame) + backgroundColor = UIColor(hexStr: "#E7F0E9") + clipsToBounds = true + imageView.contentMode = .scaleAspectFill + addSubview(imageView) + addSubview(pinView) + imageView.translatesAutoresizingMaskIntoConstraints = false + pinView.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + imageView.topAnchor.constraint(equalTo: topAnchor), + imageView.leadingAnchor.constraint(equalTo: leadingAnchor), + imageView.trailingAnchor.constraint(equalTo: trailingAnchor), + imageView.bottomAnchor.constraint(equalTo: bottomAnchor), + pinView.centerXAnchor.constraint(equalTo: centerXAnchor), + pinView.centerYAnchor.constraint(equalTo: centerYAnchor), + pinView.widthAnchor.constraint(equalToConstant: 20), + pinView.heightAnchor.constraint(equalToConstant: 20) + ]) + } + + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } + + func configure(location: ChatLocationPayload) { + let identifier = UUID() + requestID = identifier + imageView.image = nil + guard CLLocationCoordinate2DIsValid(location.coordinate), + abs(location.latitude) > 0.0001 || abs(location.longitude) > 0.0001 else { return } + let options = MKMapSnapshotter.Options() + options.region = MKCoordinateRegion(center: location.coordinate, + latitudinalMeters: 700, + longitudinalMeters: 700) + options.size = CGSize(width: 460, height: 168) + options.scale = UIScreen.main.scale + MKMapSnapshotter(options: options).start(with: .main) { [weak self] snapshot, _ in + guard let self, self.requestID == identifier else { return } + self.imageView.image = snapshot?.image + } + } +} diff --git a/QuickLocation/Section/Group/GroupChat/GroupChatViewModel.swift b/QuickLocation/Section/Group/GroupChat/GroupChatViewModel.swift index 0de543fe..69697150 100644 --- a/QuickLocation/Section/Group/GroupChat/GroupChatViewModel.swift +++ b/QuickLocation/Section/Group/GroupChat/GroupChatViewModel.swift @@ -6,6 +6,7 @@ // import UIKit +import CoreLocation import RxSwift import RxCocoa import OpenIMSDK @@ -22,6 +23,40 @@ struct QuotePreview { let quotedClientMsgID: String? } +struct ChatLocationPayload: Codable, Equatable { + let name: String + let address: String + let latitude: Double + let longitude: Double + + var coordinate: CLLocationCoordinate2D { + CLLocationCoordinate2D(latitude: latitude, longitude: longitude) + } + + var encodedDescription: String { + guard let data = try? JSONEncoder().encode(self), + let value = String(data: data, encoding: .utf8) else { + return [name, address].filter { !$0.isEmpty }.joined(separator: "\n") + } + return value + } + + static func decode(description: String?, latitude: Double, longitude: Double) -> ChatLocationPayload { + if let description, + let data = description.data(using: .utf8), + let payload = try? JSONDecoder().decode(ChatLocationPayload.self, from: data) { + return payload + } + let parts = (description ?? "").components(separatedBy: "\n") + return ChatLocationPayload( + name: parts.first ?? "", + address: parts.dropFirst().joined(separator: "\n"), + latitude: latitude, + longitude: longitude + ) + } +} + enum ChatSectionItem { case send(ChatMessage) case received(ChatMessage) @@ -31,6 +66,8 @@ enum ChatSectionItem { case voiceReceived(ChatMessage) case imageSend(ChatMessage) case imageReceived(ChatMessage) + case locationSend(ChatMessage) + case locationReceived(ChatMessage) case notification(NSAttributedString, showTime: Bool = false, timestamp: TimeInterval = 0) case revoked(NSAttributedString, showTime: Bool = false, timestamp: TimeInterval = 0) } @@ -57,7 +94,9 @@ final class GroupChatViewModel { private var lastTimeGap: TimeInterval = 0 private let timeGapThreshold: TimeInterval = 300 - var groupModel: GroupInfoModel? + var groupModel: GroupInfoModel? { + didSet { refreshMessageMetadata() } + } var memberList: [GroupMemberModel] = [] { didSet { buildAvatarCache() } } @@ -110,16 +149,23 @@ final class GroupChatViewModel { cache[member.user_id] = member.userIcon } avatarCache = cache - refreshMessageAvatars() + refreshMessageMetadata() } - private func refreshMessageAvatars() { + private func refreshMessageMetadata() { var items = messagesSubject.value var didChange = false items = items.map { item in - guard var m = item.chatMessage, updateAvatar(&m) else { return item } + guard var message = item.chatMessage else { return item } + let avatarUpdated = updateAvatar(&message) + let isOwner = isCircleOwner(id: message.senderId) + let ownerUpdated = message.isCircleOwner != isOwner + if ownerUpdated { + message = message.with(isCircleOwner: isOwner) + } + guard avatarUpdated || ownerUpdated else { return item } didChange = true - return ChatSectionItem.with(m) + return ChatSectionItem.with(message) } if didChange { messagesSubject.accept(items) } } @@ -144,6 +190,11 @@ final class GroupChatViewModel { memberList.first { id == $0.user_id }?.nick_name ?? "" } + func isCircleOwner(id: String) -> Bool { + guard !id.isEmpty, let groupModel else { return false } + return groupModel.group_key.contains(id) + } + // MARK: - Quote / Mention state func setPendingQuote(_ msg: OIMMessageInfo?) { pendingQuote = msg @@ -239,6 +290,26 @@ final class GroupChatViewModel { }) } + func sendLocation(_ location: ChatLocationPayload) { + let msg = OIMMessageInfo.createLocationMessage(location.encodedDescription, + latitude: location.latitude, + longitude: location.longitude) + OIMManager.manager.sendMessage(msg, + recvID: "", + groupID: groupId, + offlinePushInfo: nil, + onSuccess: { [weak self] _ in + self?.cacheMessage(msg) + self?.appendMessage(msg) + }, + onProgress: nil as OIMNumberCallback?, + onFailure: { code, errMsg in + DispatchQueue.main.async { + DLToast.showError(text: errMsg ?? "位置发送失败(\(code))") + } + }) + } + // MARK: - Revoke func revokeMessage(clientMsgID: String) { OIMManager.manager.revokeMessage(conversationID, @@ -276,9 +347,10 @@ final class GroupChatViewModel { } let ts = timestampFrom(item: items[idx]) let showTime: Bool = { - switch items[idx] { - case let .send(m), let .received(m), let .emojiSend(m), let .emojiReceived(m), - let .voiceSend(m), let .voiceReceived(m), let .imageSend(m), let .imageReceived(m): + switch items[idx] { + case let .send(m), let .received(m), let .emojiSend(m), let .emojiReceived(m), + let .voiceSend(m), let .voiceReceived(m), let .imageSend(m), let .imageReceived(m), + let .locationSend(m), let .locationReceived(m): return m.showTime case let .notification(_, s, _), let .revoked(_, s, _): return s @@ -602,7 +674,8 @@ final class GroupChatViewModel { private func timestampFrom(item: ChatSectionItem) -> TimeInterval { switch item { case let .send(m), let .received(m), let .emojiSend(m), let .emojiReceived(m), - let .voiceSend(m), let .voiceReceived(m), let .imageSend(m), let .imageReceived(m): + let .voiceSend(m), let .voiceReceived(m), let .imageSend(m), let .imageReceived(m), + let .locationSend(m), let .locationReceived(m): return m.timestamp case let .notification(_, _, ts), let .revoked(_, _, ts): return ts @@ -619,6 +692,8 @@ final class GroupChatViewModel { case var .voiceReceived(m): m.showTime = show; return .voiceReceived(m) case var .imageSend(m): m.showTime = show; return .imageSend(m) case var .imageReceived(m): m.showTime = show; return .imageReceived(m) + case var .locationSend(m): m.showTime = show; return .locationSend(m) + case var .locationReceived(m): m.showTime = show; return .locationReceived(m) case let .notification(text, _, ts): return .notification(text, showTime: show, timestamp: ts) case let .revoked(text, _, ts): return .revoked(text, showTime: show, timestamp: ts) } @@ -636,6 +711,7 @@ final class GroupChatViewModel { var atUserIDs: [String] = [] var atNicknames: [String] = [] var isAtAll = false + var location: ChatLocationPayload? let maxWH: CGFloat = 200 var msgImageW: CGFloat = 0 @@ -659,6 +735,11 @@ final class GroupChatViewModel { imageUrl = pic.sourcePicture?.url ?? pic.bigPicture?.url ?? pic.sourcePath ?? "" imageW = msgImageW imageH = msgImageH + } else if type == 109, let elem = msg.locationElem { + location = ChatLocationPayload.decode(description: elem.desc, + latitude: elem.latitude, + longitude: elem.longitude) + content = location?.name ?? "" } else if type == 106, let at = msg.atTextElem { content = at.text ?? "" atUserIDs = at.atUserList ?? [] @@ -684,12 +765,15 @@ final class GroupChatViewModel { } let sendID = msg.sendID ?? "" + let senderName = msg.senderNickname?.isEmpty == false + ? msg.senderNickname! + : getUserNickName(id: sendID) return ChatMessage( id: msg.clientMsgID ?? UUID().uuidString, isSelf: isSelf, senderId: sendID, avatar: getUserAvatar(id: sendID), - senderName: msg.senderNickname ?? "", + senderName: senderName, content: content, voiceUrl: voiceUrl, imageUrl: imageUrl, @@ -700,7 +784,9 @@ final class GroupChatViewModel { quotePreview: quotePreview, atUserIDs: atUserIDs, atNicknames: atNicknames, - isAtAll: isAtAll + isAtAll: isAtAll, + isCircleOwner: isCircleOwner(id: sendID), + location: location ) } @@ -719,6 +805,9 @@ final class GroupChatViewModel { let summary = dur > 0 ? "[语音] \(dur)''" : "[语音]" return QuotePreview(senderName: name, kind: .voice, summary: summary, quotedClientMsgID: id) } + if type == 109 { + return QuotePreview(senderName: name, kind: .unknown, summary: "[位置]", quotedClientMsgID: id) + } var text = "" if type == 106 { text = msg.atTextElem?.text ?? "" @@ -764,6 +853,11 @@ final class GroupChatViewModel { return chatMsg.isSelf ? .imageSend(chatMsg) : .imageReceived(chatMsg) } + if msg.contentType.rawValue == 109 { + let chatMsg = convert(msg) + return chatMsg.isSelf ? .locationSend(chatMsg) : .locationReceived(chatMsg) + } + // 文本 / @ / 引用 let chatMsg = convert(msg) if chatMsg.content.isEmpty && chatMsg.quotePreview == nil { return nil } @@ -815,7 +909,8 @@ extension ChatSectionItem { var chatMessage: ChatMessage? { switch self { case let .send(m), let .received(m), let .emojiSend(m), let .emojiReceived(m), - let .voiceSend(m), let .voiceReceived(m), let .imageSend(m), let .imageReceived(m): + let .voiceSend(m), let .voiceReceived(m), let .imageSend(m), let .imageReceived(m), + let .locationSend(m), let .locationReceived(m): return m case .notification, .revoked: return nil @@ -826,6 +921,9 @@ extension ChatSectionItem { var revokedClientMsgID: String? { nil } static func with(_ msg: ChatMessage) -> ChatSectionItem { + if msg.location != nil { + return msg.isSelf ? .locationSend(msg) : .locationReceived(msg) + } if !msg.imageUrl.isEmpty { return msg.isSelf ? .imageSend(msg) : .imageReceived(msg) } diff --git a/QuickLocation/Section/Group/RemoveMember/RemoveMemberVC.swift b/QuickLocation/Section/Group/RemoveMember/RemoveMemberVC.swift index ecb99360..84fc0c03 100644 --- a/QuickLocation/Section/Group/RemoveMember/RemoveMemberVC.swift +++ b/QuickLocation/Section/Group/RemoveMember/RemoveMemberVC.swift @@ -41,12 +41,26 @@ class RemoveMemberVC: BaseViewController { self?.rootView.updateHeight(itemCount: count) }) .disposed(by: disposeBag) + + rootView.searchField.rx.text.orEmpty + .distinctUntilChanged() + .subscribe(onNext: { [weak self] keyword in + self?.rootView.updateSearchPlaceholder(isHidden: !keyword.isEmpty) + self?.viewModel.updateSearchKeyword(keyword) + }) + .disposed(by: disposeBag) + + rootView.searchField.rx.controlEvent(.editingDidEndOnExit) + .subscribe(onNext: { [weak self] in + self?.rootView.searchField.resignFirstResponder() + }) + .disposed(by: disposeBag) rootView.tableView.rx.modelSelected(GroupMemberModel.self) .subscribe(viewModel.cellAction.inputs) .disposed(by: disposeBag) - // selectedMembers 驱动删除按钮状态和文字 + // selectedMembers 驱动移除按钮状态 let selectedCount = viewModel.selectedMembers .map { $0.count } .share(replay: 1) @@ -55,21 +69,19 @@ class RemoveMemberVC: BaseViewController { .map { $0 > 0 } .bind(to: rootView.deleteBtn.rx.isEnabled) .disposed(by: disposeBag) - - selectedCount - .map { "删除(\($0))" } - .bind(to: rootView.deleteBtn.rx.title()) - .disposed(by: disposeBag) - rootView.deleteBtn.rx.tap.subscribe(onNext: { _ in - self.showConfirmPop(showCloseBtn: true, - title: "确定要移除成员吗?", - message: "成员将从当前圈子中移除", - confirmText: "否", - cancelText: "是") { - self.requestRemoveMember() - } - }).disposed(by: disposeBag) + rootView.deleteBtn.rx.tap + .subscribe(onNext: { [weak self] in + guard let self = self else { return } + self.showConfirmPop(showCloseBtn: true, + title: "确定要移除成员吗?", + message: "成员将从当前圈子中移除", + confirmText: "否", + cancelText: "是") { + self.requestRemoveMember() + } + }) + .disposed(by: disposeBag) } // MARK: - UITableViewDataSource @@ -79,7 +91,8 @@ class RemoveMemberVC: BaseViewController { let cell: RemoveMemberCell = tableView.dequeueReusableCell(for: indexPath) cell.configure(model, isOwn: self.viewModel.groupId.contains(model.user_id), - isSelected: self.viewModel.isSelected(id: model.user_id)) + isSelected: self.viewModel.isSelected(id: model.user_id), + showsSeparator: indexPath.row < tableView.numberOfRows(inSection: indexPath.section) - 1) return cell }) }() @@ -91,6 +104,7 @@ class RemoveMemberVC: BaseViewController { DLToast.dismiss() guard let model = response.model else { return } self.viewModel.groupModel = model + self.rootView.updateMemberCount(response.list.count) self.viewModel.loadData(response.list) }.disposed(by: disposeBag) } diff --git a/QuickLocation/Section/Group/RemoveMember/RemoveMemberView.swift b/QuickLocation/Section/Group/RemoveMember/RemoveMemberView.swift index b1fc9339..e00c1fb8 100644 --- a/QuickLocation/Section/Group/RemoveMember/RemoveMemberView.swift +++ b/QuickLocation/Section/Group/RemoveMember/RemoveMemberView.swift @@ -6,261 +6,261 @@ // import UIKit -import RxSwift -import RxCocoa -class RemoveMemberView: UIView { +final class RemoveMemberView: UIView { - var disposeBag = DisposeBag() - /// 单行高度 - static let rowHeight: CGFloat = 85 - - private func setupRx() { - } - - private func setupUI() { - addSubview(navBgView) - addSubview(navView) - - addSubview(titleLab) - addSubview(cornerBgView) - addSubview(tableView) - - navBgView.layoutChain - .edges(excludingEdge: .bottom) - .height(kNaviHeight) - - navView.layoutChain - .edges(excludingEdge: .bottom) - .height(kNaviHeight) - - titleLab.layoutChain - .topToBottomOfView(navView, offset: 8) - .left(15) - - cornerBgView.layoutChain - .topToBottomOfView(titleLab, offset: 16) - .edgesHorzontal(15) - - tableView.layoutChain - .topToBottomOfView(titleLab, offset: 16) - .edgesHorzontal(15) - } - - /// 根据数据源数量更新高度,上限到 bottom = kSafeBottomMargin + 10 - func updateHeight(itemCount: Int) { - let contentH = CGFloat(itemCount) * Self.rowHeight - let maxH = dl.height - kNaviHeight - kSafeBottomMargin - 10 - 16 - let targetH = min(contentH, maxH) - - tableView.layoutChain.height(targetH) - cornerBgView.layoutChain.height(targetH) - tableView.isScrollEnabled = targetH > maxH - } + static let rowHeight: CGFloat = 52 private var listHeightConstraint: NSLayoutConstraint? - - lazy var navBgView: UIImageView = { - let iv = UIImageView() - iv.image = UIImage(named: "Common/navBar_bg_2") - iv.contentMode = .scaleAspectFill - return iv - }() - - lazy var navView: BaseNavigationView = { - let nav = BaseNavigationView(title: "移除圈子成员") - nav.addRightButton(deleteBtn) - return nav - }() - - lazy var deleteBtn: UIButton = { - let btn = UIButton(type: .custom) - btn.setTitle("删除(0)", for: .normal) - btn.setTitleColor(UIColor(hexStr: "#FF383C"), for: .normal) - btn.titleLabel?.font = .systemFont(ofSize: 12, weight: .medium) - btn.contentHorizontalAlignment = .right - return btn - }() - - lazy var titleLab: UILabel = { - let label = UILabel() - label.text = "圈子成员" - label.font = .systemFont(ofSize: 16, weight: .semibold) - label.textColor = ThemeManager.shared.color.titleAuxColor - return label - }() - - lazy var cornerBgView: UIView = { - let view = UIView() - view.backgroundColor = UIColor(hexStr: "#F5FBFF") - view.cornerRadius = 10 - return view - }() - - lazy var tableView: UITableView = { - let tableView = UITableView(frame: .zero, style: .plain) - tableView.backgroundColor = .clear - tableView.separatorStyle = .none - tableView.estimatedRowHeight = 85 - tableView.isScrollEnabled = false - tableView.register(RemoveMemberCell.self) - return tableView - }() - + override init(frame: CGRect) { - super.init(frame: .zero) - backgroundColor = .white + super.init(frame: frame) + backgroundColor = UIColor(hexStr: "#F7F7F7") setupUI() - setupRx() } - required init?(coder aDecoder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - -} - - -// MARK: - RemoveMemberCell -class RemoveMemberCell: UITableViewCell { - - var disposeBag = DisposeBag() - - func configure(_ model: GroupMemberModel, isOwn: Bool, isSelected: Bool) { - avaterImgView.image = model.userIcon - nameLab.text = model.nick_name - ownView.isHidden = !isOwn - selectedBtn.isHidden = isOwn - selectedBtn.isSelected = isSelected - } - - 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(avaterImgView) - bgView.addSubview(nameLab) - bgView.addSubview(stackView) - bgView.addSubview(lineView) - - bgView.layoutChain - .edgesHorzontal() - .edgesVertical() - - avaterImgView.layoutChain - .edgesVertical(20) - .left(15) - .height(45) - .widthToHeight(1) - - nameLab.layoutChain - .leftToRightOfView(avaterImgView, offset: 10) - .centerY(avaterImgView) - - stackView.layoutChain - .right(15) - .centerY() - - ownView.layoutChain.width(25).height(35) - selectedBtn.layoutChain.width(20).height(20) - - lineView.layoutChain - .height(0.5) - .edgesHorzontal(15) - .bottom() - } - - lazy var bgView: UIView = { - let view = UIView() - view.backgroundColor = .clear//UIColor(hexStr: "#F5FBFF") - return view - }() - - lazy var avaterImgView: UIImageView = { - let view = UIImageView() - view.backgroundColor = .clear - view.cornerRadius = 22.5 - return view - }() - - lazy var nameLab: UILabel = { - let label = UILabel() - label.textColor = UIColor(hexStr: "#0F2846") - label.font = .systemFont(ofSize: 14, weight: .medium) - return label - }() - - lazy var stackView: UIStackView = { - let view = UIStackView(arrangedSubviews: [ownView, selectedBtn]) - view.axis = .horizontal - view.alignment = .trailing - view.spacing = 0 - view.backgroundColor = .clear - return view - }() - - lazy var ownView: UIView = { - let view = UIView() - view.backgroundColor = .clear - view.isHidden = true - - let icon = UIImageView(image: UIImage(named: "Common/owner")) - view.addSubview(icon) - icon.layoutChain - .top() - .centerX() - .width(18) - .height(18) - - let label = UILabel() - label.text = "圈主" - label.textColor = ThemeManager.shared.color.titleAuxColor - label.font = .systemFont(ofSize: 10, weight: .medium) - view.addSubview(label) - label.layoutChain - .topToBottomOfView(icon) - .centerX() - - return view - }() - - lazy var selectedBtn: UIButton = { - let btn = UIButton(type: .custom) - btn.setImage(UIImage(named: "Common/checkbox_20x20"), for: .normal) - btn.setImage(UIImage(named: "Common/delete_check"), for: .selected) - btn.isUserInteractionEnabled = false - btn.isHidden = true - return btn - }() - - lazy var lineView: UIView = { - let view = UIView() - view.backgroundColor = ThemeManager.shared.color.lineColor - return view - }() - required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } - - override func awakeFromNib() { - super.awakeFromNib() - // Initialization code + + private func setupUI() { + addSubview(navView) + addSubview(searchField) + addSubview(titleLab) + addSubview(listContainerView) + listContainerView.addSubview(tableView) + + navView.layoutChain + .top() + .edgesHorzontal() + .height(kNaviHeight) + + searchField.layoutChain + .topToBottomOfView(navView, offset: 20) + .edgesHorzontal(15) + .height(38) + + searchField.addSubview(searchPlaceholderView) + searchPlaceholderView.layoutChain + .center() + .height(20) + searchPlaceholderView.layoutChain.width(52) + + titleLab.layoutChain + .topToBottomOfView(searchField, offset: 19) + .left(16) + .height(19) + + listContainerView.layoutChain + .topToBottomOfView(titleLab, offset: 6) + .edgesHorzontal(15) + + tableView.layoutChain.edges() + listHeightConstraint = listContainerView.jh_setDimension(.height, toSize: 0) } - override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) + func updateMemberCount(_ count: Int) { + let prefix = "圈成员" + let countText = "(\(count)人)" + let text = prefix + countText + let attributedText = NSMutableAttributedString(string: text) + attributedText.addAttributes([ + .font: UIFont.systemFont(ofSize: 14, weight: .medium), + .foregroundColor: UIColor(hexStr: "#6E6E73") + ], range: NSRange(location: 0, length: text.count)) + attributedText.addAttributes([ + .font: UIFont.systemFont(ofSize: 13, weight: .regular), + .foregroundColor: UIColor(hexStr: "#8E8E93") + ], range: NSRange(location: prefix.count, length: countText.count)) + titleLab.attributedText = attributedText + } - // Configure the view for the selected state + func updateHeight(itemCount: Int) { + let contentHeight = CGFloat(itemCount) * Self.rowHeight + layoutIfNeeded() + + let bottomInset = max(kSafeBottomMargin, safeAreaInsets.bottom) + let maxHeight = max(0, bounds.height - listContainerView.frame.minY - bottomInset) + listHeightConstraint?.constant = min(contentHeight, maxHeight) + tableView.isScrollEnabled = contentHeight >= maxHeight && itemCount > 0 + listContainerView.isHidden = itemCount == 0 + layoutIfNeeded() } - - override func prepareForReuse() { - super.prepareForReuse() - disposeBag = DisposeBag() + + func updateSearchPlaceholder(isHidden: Bool) { + searchPlaceholderView.isHidden = isHidden } + + lazy var navView: BaseNavigationView = { + let nav = BaseNavigationView(title: "圈子成员") + nav.addRightButton(deleteBtn) + return nav + }() + + lazy var deleteBtn: UIButton = { + let button = UIButton(type: .custom) + button.setTitle("移除", for: .normal) + button.setTitleColor(UIColor(hexStr: "#FF4D53"), for: .normal) + button.setTitleColor(UIColor(hexStr: "#FF4D53", alpha: 0.35), for: .disabled) + button.titleLabel?.font = .systemFont(ofSize: 14, weight: .medium) + button.contentHorizontalAlignment = .right + button.isEnabled = false + return button + }() + + lazy var searchField: UISearchTextField = { + let textField = UISearchTextField() + textField.backgroundColor = .white + textField.borderStyle = .none + textField.cornerRadius = 11 + textField.clipsToBounds = true + textField.font = .systemFont(ofSize: 14) + textField.textColor = UIColor(hexStr: "#293445") + textField.tintColor = UIColor(hexStr: "#293445") + textField.returnKeyType = .search + textField.clearButtonMode = .whileEditing + textField.textAlignment = .left + textField.leftView = UIView(frame: .zero) + textField.leftViewMode = .never + return textField + }() + + private lazy var searchPlaceholderView: UIView = { + let view = UIView() + view.isUserInteractionEnabled = false + + let imageView = UIImageView(image: UIImage(named: "Group/remove_member_search")) + imageView.contentMode = .scaleAspectFit + view.addSubview(imageView) + imageView.layoutChain + .left() + .centerY() + .width(16) + .height(16) + + let label = UILabel() + label.text = "搜索" + label.textColor = UIColor(hexStr: "#B0B0B5") + label.font = .systemFont(ofSize: 14) + view.addSubview(label) + label.layoutChain + .leftToRightOfView(imageView, offset: 6) + .right() + .centerY() + + return view + }() + + private lazy var titleLab = UILabel() + + private lazy var listContainerView: UIView = { + let view = UIView() + view.backgroundColor = .white + view.cornerRadius = 10 + view.clipsToBounds = true + return view + }() + + lazy var tableView: UITableView = { + let tableView = UITableView(frame: .zero, style: .plain) + tableView.backgroundColor = .clear + tableView.separatorStyle = .none + tableView.rowHeight = Self.rowHeight + tableView.estimatedRowHeight = Self.rowHeight + tableView.isScrollEnabled = false + tableView.showsVerticalScrollIndicator = false + tableView.keyboardDismissMode = .onDrag + tableView.register(RemoveMemberCell.self) + return tableView + }() +} + +// MARK: - RemoveMemberCell +final class RemoveMemberCell: UITableViewCell { + + func configure( + _ model: GroupMemberModel, + isOwn: Bool, + isSelected: Bool, + showsSeparator: Bool + ) { + avatarImageView.image = model.userIcon + nameLab.text = model.nick_name + selectedBtn.isHidden = false + selectedBtn.isSelected = isOwn ? false : isSelected + selectedBtn.alpha = isOwn ? 0.45 : 1 + lineView.isHidden = !showsSeparator + } + + override init(style: CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + selectionStyle = .none + backgroundColor = .clear + contentView.backgroundColor = .clear + setupSubviews() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private func setupSubviews() { + contentView.addSubview(avatarImageView) + contentView.addSubview(nameLab) + contentView.addSubview(selectedBtn) + contentView.addSubview(lineView) + + avatarImageView.layoutChain + .left(16) + .centerY() + .width(38) + .height(38) + + nameLab.layoutChain + .leftToRightOfView(avatarImageView, offset: 12) + .centerY() + + selectedBtn.layoutChain + .right(14) + .centerY() + .width(24) + .height(24) + + lineView.layoutChain + .left(20) + .right(13) + .bottom() + .height(0.5) + } + + private lazy var avatarImageView: UIImageView = { + let imageView = UIImageView() + imageView.backgroundColor = UIColor(hexStr: "#F2F2F2") + imageView.contentMode = .scaleAspectFill + imageView.cornerRadius = 9 + imageView.clipsToBounds = true + return imageView + }() + + private lazy var nameLab: UILabel = { + let label = UILabel() + label.textColor = UIColor(hexStr: "#111111") + label.font = .systemFont(ofSize: 15, weight: .regular) + label.lineBreakMode = .byTruncatingTail + return label + }() + + private lazy var selectedBtn: UIButton = { + let button = UIButton(type: .custom) + button.setImage(UIImage(named: "Group/remove_member_unselected"), for: .normal) + button.setImage(UIImage(named: "Group/remove_member_selected"), for: .selected) + button.isUserInteractionEnabled = false + return button + }() + + private lazy var lineView: UIView = { + let view = UIView() + view.backgroundColor = UIColor(hexStr: "#EEEEF0") + return view + }() } diff --git a/QuickLocation/Section/Group/RemoveMember/RemoveMemberViewModel.swift b/QuickLocation/Section/Group/RemoveMember/RemoveMemberViewModel.swift index 53358606..a822d560 100644 --- a/QuickLocation/Section/Group/RemoveMember/RemoveMemberViewModel.swift +++ b/QuickLocation/Section/Group/RemoveMember/RemoveMemberViewModel.swift @@ -27,6 +27,7 @@ class RemoveMemberViewModel { private var disposeBag = DisposeBag() private let sectionedItems = PublishSubject<[ReviewMemberListSectionModel]>() private var list: [GroupMemberModel] = [] + private var searchKeyword = "" var selectedMembers = BehaviorRelay<[String]>(value: []) @@ -42,7 +43,7 @@ class RemoveMemberViewModel { current.append(memberId) } this.selectedMembers.accept(current) - self.sectionedItems.onNext(self.list.mapSection()) + self.emitItems() return .empty() } }(self) @@ -53,7 +54,27 @@ class RemoveMemberViewModel { func loadData(_ list: [GroupMemberModel]) { self.list = list - sectionedItems.onNext(list.mapSection()) + selectedMembers.accept(selectedMembers.value.filter { selectedId in + list.contains(where: { $0.user_id == selectedId }) + }) + emitItems() + } + + func updateSearchKeyword(_ keyword: String) { + searchKeyword = keyword.trimmingCharacters(in: .whitespacesAndNewlines) + emitItems() + } + + private func emitItems() { + let items: [GroupMemberModel] + if searchKeyword.isEmpty { + items = list + } else { + items = list.filter { + $0.nick_name.localizedCaseInsensitiveContains(searchKeyword) + } + } + sectionedItems.onNext(items.mapSection()) } init(groupId: String) { diff --git a/QuickLocation/Section/Mine/About/AboutVC.swift b/QuickLocation/Section/Mine/About/AboutVC.swift index e9455c35..0e3cb438 100644 --- a/QuickLocation/Section/Mine/About/AboutVC.swift +++ b/QuickLocation/Section/Mine/About/AboutVC.swift @@ -28,7 +28,7 @@ final class AboutVC: BaseViewController { rootView.feedbackBtn.rx.controlEvent(.touchUpInside) .subscribe(onNext: { _ in - DLToast.show(text: "敬请期待") + AppRouter.push(Route.feedback) }) .disposed(by: disposeBag) diff --git a/QuickLocation/Section/Mine/Feedback/FeedbackSuccessView.swift b/QuickLocation/Section/Mine/Feedback/FeedbackSuccessView.swift new file mode 100644 index 00000000..bc043f55 --- /dev/null +++ b/QuickLocation/Section/Mine/Feedback/FeedbackSuccessView.swift @@ -0,0 +1,88 @@ +// +// FeedbackSuccessView.swift +// QuickLocation +// + +import UIKit + +final class FeedbackSuccessView: UIView { + + private let cardView = UIView() + + override init(frame: CGRect) { + super.init(frame: frame) + setupUI() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private func setupUI() { + backgroundColor = UIColor.black.withAlphaComponent(0.66) + + let pointerView = UIView() + pointerView.backgroundColor = .white + pointerView.transform = CGAffineTransform(rotationAngle: .pi / 4) + addSubview(pointerView) + pointerView.layoutChain.centerX().centerY(self, offset: 94).width(28).height(28) + + cardView.backgroundColor = .white + cardView.layer.cornerRadius = 36 + addSubview(cardView) + cardView.layoutChain.centerX().centerY(self, offset: -8).width(280).height(208) + + let headerImageView = UIImageView(image: UIImage(named: "Mine/feedback_success_header")) + headerImageView.contentMode = .scaleToFill + headerImageView.layer.cornerRadius = 36 + headerImageView.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner] + headerImageView.clipsToBounds = true + cardView.addSubview(headerImageView) + headerImageView.layoutChain.top().left().right().height(100) + + let iconView = UIImageView(image: UIImage(named: "Mine/feedback_success_icon")) + iconView.contentMode = .scaleAspectFit + cardView.addSubview(iconView) + iconView.layoutChain.top(-60).centerX().width(120).height(120) + + let titleLabel = UILabel() + titleLabel.text = "反馈提交成功" + titleLabel.font = .systemFont(ofSize: 24, weight: .semibold) + titleLabel.textColor = UIColor(hexStr: "#1D1D1D") + titleLabel.textAlignment = .center + cardView.addSubview(titleLabel) + titleLabel.layoutChain.top(78).left(16).right(16) + + let detailLabel = UILabel() + detailLabel.text = "感谢您的反馈,我们会及时查看并妥\n善处理相关问题" + detailLabel.font = .systemFont(ofSize: 15, weight: .medium) + detailLabel.textColor = UIColor(hexStr: "#767676") + detailLabel.textAlignment = .center + detailLabel.numberOfLines = 2 + detailLabel.lineBreakMode = .byWordWrapping + cardView.addSubview(detailLabel) + detailLabel.layoutChain.topToBottomOfView(titleLabel, offset: 22).left(24).right(24) + } + + func show(in superview: UIView) { + frame = superview.bounds + autoresizingMask = [.flexibleWidth, .flexibleHeight] + alpha = 0 + cardView.transform = CGAffineTransform(scaleX: 0.9, y: 0.9) + superview.addSubview(self) + UIView.animate(withDuration: 0.24, delay: 0, options: .curveEaseOut) { + self.alpha = 1 + self.cardView.transform = .identity + } + } + + func dismiss(completion: @escaping () -> Void) { + UIView.animate(withDuration: 0.2, animations: { + self.alpha = 0 + self.cardView.transform = CGAffineTransform(scaleX: 0.96, y: 0.96) + }, completion: { _ in + self.removeFromSuperview() + completion() + }) + } +} diff --git a/QuickLocation/Section/Mine/Feedback/FeedbackVC.swift b/QuickLocation/Section/Mine/Feedback/FeedbackVC.swift new file mode 100644 index 00000000..458eba10 --- /dev/null +++ b/QuickLocation/Section/Mine/Feedback/FeedbackVC.swift @@ -0,0 +1,168 @@ +// +// FeedbackVC.swift +// QuickLocation +// + +import UIKit +import RxSwift +import RxCocoa +import HXPHPicker + +final class FeedbackVC: BaseViewController { + + private enum FeedbackCategory: String, CaseIterable { + case feature = "功能问题" + case suggestion = "优化建议" + case other = "其他" + } + + private struct FeedbackDraft { + let category: FeedbackCategory + let detail: String + let images: [UIImage] + let contact: String + } + + private var rootView: FeedbackView! + private var selectedCategory: FeedbackCategory = .feature + private var selectedImages: [UIImage] = [] + private var pendingDraft: FeedbackDraft? + private var isSubmitting = false + + override func loadView() { + rootView = FeedbackView(frame: UIScreen.main.bounds) + view = rootView + } + + override func viewDidLoad() { + super.viewDidLoad() + bind() + } + + private func bind() { + rootView.navView.onBackTapped = { [weak self] in + guard self?.isSubmitting == false else { return } + self?.navigationController?.popViewController(animated: true) + } + + rootView.categoryButtons.forEach { button in + button.addTarget(self, action: #selector(categoryTapped(_:)), for: .touchUpInside) + } + + rootView.detailTextView.rx.text.orEmpty + .subscribe(onNext: { [weak self] text in + self?.handleDetailChange(text) + }) + .disposed(by: disposeBag) + + rootView.contactTextField.rx.controlEvent(.editingDidEndOnExit) + .subscribe(onNext: { [weak self] in + self?.rootView.contactTextField.resignFirstResponder() + }) + .disposed(by: disposeBag) + + rootView.onAddImage = { [weak self] in + self?.showAlbum() + } + + rootView.onDeleteImage = { [weak self] index in + guard let self, self.selectedImages.indices.contains(index) else { return } + self.selectedImages.remove(at: index) + self.rootView.updateImages(self.selectedImages) + } + + rootView.saveBtn.rx.tap + .subscribe(onNext: { [weak self] in + self?.submit() + }) + .disposed(by: disposeBag) + } + + @objc private func categoryTapped(_ sender: UIButton) { + let categories = FeedbackCategory.allCases + guard categories.indices.contains(sender.tag) else { return } + let category = categories[sender.tag] + selectedCategory = category + rootView.updateCategory(selectedIndex: sender.tag) + } + + private func handleDetailChange(_ text: String) { + let limitedText = text.count > 200 ? String(text.prefix(200)) : text + if limitedText != text { + rootView.detailTextView.text = limitedText + rootView.detailTextView.selectedRange = NSRange(location: limitedText.count, length: 0) + } + rootView.updateDetail(text: limitedText) + } + + private func showAlbum() { + let remainingCount = 3 - selectedImages.count + guard remainingCount > 0, !isSubmitting else { return } + + let config = PhotoTools.getWXPickerConfig() + config.selectOptions = [.photo] + config.selectMode = .multiple + config.maximumSelectedCount = remainingCount + config.allowSyncICloudWhenSelectPhoto = false + config.previewView.bottomView.editButtonHidden = true + config.photoList.allowAddCamera = false + + let pickerController = PhotoPickerController(picker: config) + pickerController.pickerDelegate = self + pickerController.modalPresentationStyle = .fullScreen + present(pickerController, animated: true) + } + + private func submit() { + guard !isSubmitting else { return } + view.endEditing(true) + + let detail = (rootView.detailTextView.text ?? "") + .trimmingCharacters(in: .whitespacesAndNewlines) + guard !detail.isEmpty else { + DLToast.show(text: "请补充详细问题或意见") + return + } + + pendingDraft = FeedbackDraft( + category: selectedCategory, + detail: detail, + images: selectedImages, + contact: rootView.contactTextField.text ?? "" + ) + isSubmitting = true + rootView.setSubmitting(true) + + let successView = FeedbackSuccessView() + successView.show(in: view) + DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) { [weak self, weak successView] in + guard let self, let successView else { return } + successView.dismiss { + AppRouter.shared.popOrDismiss() + } + } + } +} + +extension FeedbackVC: PhotoPickerControllerDelegate { + + func pickerController( + _ pickerController: PhotoPickerController, + didFinishSelection result: PickerResult + ) { + let remainingCount = max(0, 3 - selectedImages.count) + guard remainingCount > 0 else { return } + + result.getImage { _, _, _ in + } completionHandler: { [weak self] images in + DispatchQueue.main.async { + guard let self else { return } + self.selectedImages.append(contentsOf: images.prefix(remainingCount)) + self.selectedImages = Array(self.selectedImages.prefix(3)) + self.rootView.updateImages(self.selectedImages) + } + } + } + + func pickerController(didCancel pickerController: PhotoPickerController) {} +} diff --git a/QuickLocation/Section/Mine/Feedback/FeedbackView.swift b/QuickLocation/Section/Mine/Feedback/FeedbackView.swift new file mode 100644 index 00000000..6d484b2f --- /dev/null +++ b/QuickLocation/Section/Mine/Feedback/FeedbackView.swift @@ -0,0 +1,398 @@ +// +// FeedbackView.swift +// QuickLocation +// + +import UIKit + +final class FeedbackView: UIView { + + let navView = BaseNavigationView(title: "问题反馈") + let detailTextView = UITextView() + let contactTextField = UITextField() + let saveBtn = UIButton(type: .custom) + private(set) var categoryButtons: [UIButton] = [] + + var onAddImage: (() -> Void)? + var onDeleteImage: ((Int) -> Void)? + + private let scrollView = UIScrollView() + private let contentView = UIView() + private let detailPlaceholderLabel = UILabel() + private let countLabel = UILabel() + private let imagesCollectionView: UICollectionView + private var images: [UIImage] = [] + + override init(frame: CGRect) { + let layout = UICollectionViewFlowLayout() + layout.scrollDirection = .horizontal + layout.minimumLineSpacing = 8 + layout.minimumInteritemSpacing = 8 + layout.itemSize = CGSize(width: 100, height: 100) + imagesCollectionView = UICollectionView(frame: .zero, collectionViewLayout: layout) + super.init(frame: frame) + backgroundColor = UIColor(hexStr: "#F8F8F8") + setupUI() + updateCategory(selectedIndex: 0) + updateDetail(text: "") + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private func setupUI() { + addSubview(navView) + navView.layoutChain.top().edgesHorzontal().height(kNaviHeight) + + saveBtn.setTitle("保存", for: .normal) + saveBtn.setTitleColor(.white, for: .normal) + saveBtn.titleLabel?.font = FontManager.boboBold(18) + saveBtn.setBackgroundImage(UIImage(named: "Common/button_bg_2"), for: .normal) + saveBtn.layer.cornerRadius = 24 + saveBtn.clipsToBounds = true + addSubview(saveBtn) + saveBtn.layoutChain + .left(28) + .right(28) + .bottom(kSafeBottomMargin + 22) + .height(56) + + scrollView.alwaysBounceVertical = false + scrollView.keyboardDismissMode = .onDrag + scrollView.showsVerticalScrollIndicator = false + addSubview(scrollView) + scrollView.layoutChain + .topToBottomOfView(navView) + .edgesHorzontal() + .bottomToTopOfView(saveBtn, offset: -12) + + scrollView.addSubview(contentView) + contentView.layoutChain.edges().widthToView(scrollView) + + let typeTitle = makeSectionTitle(required: true, title: "您想反馈的功能类型") + contentView.addSubview(typeTitle) + typeTitle.layoutChain.top(14).left(16).right(16) + + let titles = ["功能问题", "优化建议", "其他"] + categoryButtons = titles.enumerated().map { index, title in + let button = UIButton(type: .custom) + button.tag = index + button.setTitle(title, for: .normal) + button.titleLabel?.font = .systemFont(ofSize: 15, weight: .medium) + button.layer.cornerRadius = 12 + button.layer.borderWidth = 1 + contentView.addSubview(button) + button.translatesAutoresizingMaskIntoConstraints = false + return button + } + + let firstButton = categoryButtons[0] + let secondButton = categoryButtons[1] + let thirdButton = categoryButtons[2] + NSLayoutConstraint.activate([ + firstButton.topAnchor.constraint(equalTo: typeTitle.bottomAnchor, constant: 12), + firstButton.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 16), + firstButton.heightAnchor.constraint(equalToConstant: 34), + secondButton.topAnchor.constraint(equalTo: firstButton.topAnchor), + secondButton.leadingAnchor.constraint(equalTo: firstButton.trailingAnchor, constant: 16), + secondButton.widthAnchor.constraint(equalTo: firstButton.widthAnchor), + secondButton.heightAnchor.constraint(equalTo: firstButton.heightAnchor), + thirdButton.topAnchor.constraint(equalTo: firstButton.topAnchor), + thirdButton.leadingAnchor.constraint(equalTo: secondButton.trailingAnchor, constant: 16), + thirdButton.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -16), + thirdButton.widthAnchor.constraint(equalTo: firstButton.widthAnchor), + thirdButton.heightAnchor.constraint(equalTo: firstButton.heightAnchor) + ]) + + let detailTitle = makeSectionTitle(required: true, title: "请补充详细问题或意见") + contentView.addSubview(detailTitle) + detailTitle.layoutChain + .topToBottomOfView(firstButton, offset: 20) + .left(16) + .right(16) + + let detailContainer = UIView() + detailContainer.backgroundColor = .white + detailContainer.layer.cornerRadius = 16 + contentView.addSubview(detailContainer) + detailContainer.layoutChain + .topToBottomOfView(detailTitle, offset: 12) + .left(16) + .right(16) + .height(150) + + detailTextView.backgroundColor = .clear + detailTextView.font = .systemFont(ofSize: 14, weight: .medium) + detailTextView.textColor = UIColor(hexStr: "#293445") + detailTextView.textContainerInset = UIEdgeInsets(top: 10, left: 10, bottom: 28, right: 10) + detailTextView.textContainer.lineFragmentPadding = 0 + detailTextView.isScrollEnabled = true + detailTextView.returnKeyType = .default + detailContainer.addSubview(detailTextView) + detailTextView.layoutChain.edges() + + detailPlaceholderLabel.text = "请在这里输入内容" + detailPlaceholderLabel.font = .systemFont(ofSize: 14, weight: .medium) + detailPlaceholderLabel.textColor = UIColor(hexStr: "#B5B5B5") + detailPlaceholderLabel.isUserInteractionEnabled = false + detailContainer.addSubview(detailPlaceholderLabel) + detailPlaceholderLabel.layoutChain.top(12).left(14).right(14) + + countLabel.font = .systemFont(ofSize: 13, weight: .medium) + countLabel.textColor = UIColor(hexStr: "#767676") + countLabel.textAlignment = .right + detailContainer.addSubview(countLabel) + countLabel.layoutChain.right(14).bottom(10) + + let imageTitle = makeSectionTitle( + required: false, + title: "请提供相关问题的图片", + detail: "(选填,最多可上传三张)" + ) + contentView.addSubview(imageTitle) + imageTitle.layoutChain + .topToBottomOfView(detailContainer, offset: 18) + .left(16) + .right(16) + + imagesCollectionView.backgroundColor = .clear + imagesCollectionView.isScrollEnabled = false + imagesCollectionView.showsHorizontalScrollIndicator = false + imagesCollectionView.dataSource = self + imagesCollectionView.delegate = self + imagesCollectionView.register( + FeedbackImageCell.self, + forCellWithReuseIdentifier: FeedbackImageCell.reuseIdentifier + ) + imagesCollectionView.register( + FeedbackAddImageCell.self, + forCellWithReuseIdentifier: FeedbackAddImageCell.reuseIdentifier + ) + contentView.addSubview(imagesCollectionView) + imagesCollectionView.layoutChain + .topToBottomOfView(imageTitle, offset: 12) + .left(16) + .right(16) + .height(100) + + let contactTitle = makeSectionTitle( + required: false, + title: "联系方式", + detail: "(选填,可以留下您的手机号、微信、邮箱)" + ) + contentView.addSubview(contactTitle) + contactTitle.layoutChain + .topToBottomOfView(imagesCollectionView, offset: 18) + .left(16) + .right(16) + + contactTextField.backgroundColor = .white + contactTextField.layer.cornerRadius = 20 + contactTextField.font = .systemFont(ofSize: 14, weight: .medium) + contactTextField.textColor = UIColor(hexStr: "#293445") + contactTextField.returnKeyType = .done + contactTextField.clearButtonMode = .whileEditing + contactTextField.attributedPlaceholder = NSAttributedString( + string: "请输入您的联系方式", + attributes: [ + .foregroundColor: UIColor(hexStr: "#B5B5B5"), + .font: UIFont.systemFont(ofSize: 14, weight: .medium) + ] + ) + contactTextField.leftView = UIView(frame: CGRect(x: 0, y: 0, width: 16, height: 1)) + contactTextField.leftViewMode = .always + contactTextField.rightView = UIView(frame: CGRect(x: 0, y: 0, width: 16, height: 1)) + contactTextField.rightViewMode = .unlessEditing + contentView.addSubview(contactTextField) + contactTextField.layoutChain + .topToBottomOfView(contactTitle, offset: 12) + .left(16) + .right(16) + .height(40) + .bottom(24) + } + + private func makeSectionTitle(required: Bool, title: String, detail: String? = nil) -> UILabel { + let label = UILabel() + label.numberOfLines = 0 + + let text = NSMutableAttributedString() + if required { + text.append(NSAttributedString( + string: "*", + attributes: [ + .font: UIFont.systemFont(ofSize: 17, weight: .medium), + .foregroundColor: UIColor(hexStr: "#F64545") + ] + )) + } + text.append(NSAttributedString( + string: title, + attributes: [ + .font: UIFont.systemFont(ofSize: 16, weight: .medium), + .foregroundColor: UIColor(hexStr: "#293445") + ] + )) + if let detail { + text.append(NSAttributedString( + string: detail, + attributes: [ + .font: UIFont.systemFont(ofSize: 12, weight: .medium), + .foregroundColor: UIColor(hexStr: "#B5B5B5") + ] + )) + } + label.attributedText = text + return label + } + + func updateCategory(selectedIndex: Int) { + for (index, button) in categoryButtons.enumerated() { + let isSelected = index == selectedIndex + button.backgroundColor = isSelected ? UIColor(hexStr: "#08B2F5") : .clear + button.layer.borderColor = UIColor( + hexStr: isSelected ? "#08B2F5" : "#D6D6D6" + ).cgColor + button.setTitleColor( + isSelected ? .white : UIColor(hexStr: "#293445"), + for: .normal + ) + } + } + + func updateDetail(text: String) { + detailPlaceholderLabel.isHidden = !text.isEmpty + countLabel.text = "\(text.count)/200" + } + + func updateImages(_ images: [UIImage]) { + self.images = Array(images.prefix(3)) + imagesCollectionView.reloadData() + } + + func setSubmitting(_ submitting: Bool) { + saveBtn.isEnabled = !submitting + saveBtn.alpha = submitting ? 0.65 : 1 + } +} + +extension FeedbackView: UICollectionViewDataSource, UICollectionViewDelegateFlowLayout { + + func collectionView( + _ collectionView: UICollectionView, + layout collectionViewLayout: UICollectionViewLayout, + sizeForItemAt indexPath: IndexPath + ) -> CGSize { + let width = min(100, floor((collectionView.bounds.width - 16) / 3)) + return CGSize(width: width, height: 100) + } + + func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + images.count + (images.count < 3 ? 1 : 0) + } + + func collectionView( + _ collectionView: UICollectionView, + cellForItemAt indexPath: IndexPath + ) -> UICollectionViewCell { + if indexPath.item < images.count { + guard let cell = collectionView.dequeueReusableCell( + withReuseIdentifier: FeedbackImageCell.reuseIdentifier, + for: indexPath + ) as? FeedbackImageCell else { + return UICollectionViewCell() + } + cell.configure(image: images[indexPath.item]) + cell.onDelete = { [weak self, weak cell] in + guard let self, let cell, + let currentIndexPath = collectionView.indexPath(for: cell) else { return } + self.onDeleteImage?(currentIndexPath.item) + } + return cell + } + + guard let cell = collectionView.dequeueReusableCell( + withReuseIdentifier: FeedbackAddImageCell.reuseIdentifier, + for: indexPath + ) as? FeedbackAddImageCell else { + return UICollectionViewCell() + } + return cell + } + + func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { + guard indexPath.item == images.count, images.count < 3 else { return } + onAddImage?() + } +} + +private final class FeedbackImageCell: UICollectionViewCell { + static let reuseIdentifier = "FeedbackImageCell" + + var onDelete: (() -> Void)? + + private let imageView = UIImageView() + private let deleteButton = UIButton(type: .custom) + + override init(frame: CGRect) { + super.init(frame: frame) + + imageView.contentMode = .scaleAspectFill + imageView.layer.cornerRadius = 16 + imageView.clipsToBounds = true + contentView.addSubview(imageView) + imageView.layoutChain.edges() + + let symbolConfig = UIImage.SymbolConfiguration(pointSize: 10, weight: .bold) + deleteButton.setImage(UIImage(systemName: "xmark", withConfiguration: symbolConfig), for: .normal) + deleteButton.tintColor = UIColor(hexStr: "#293445") + deleteButton.backgroundColor = UIColor.white.withAlphaComponent(0.92) + deleteButton.layer.cornerRadius = 11 + deleteButton.layer.shadowColor = UIColor.black.withAlphaComponent(0.12).cgColor + deleteButton.layer.shadowOpacity = 1 + deleteButton.layer.shadowRadius = 3 + deleteButton.layer.shadowOffset = CGSize(width: 0, height: 1) + deleteButton.addTarget(self, action: #selector(deleteTapped), for: .touchUpInside) + contentView.addSubview(deleteButton) + deleteButton.layoutChain.top(6).right(6).width(22).height(22) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func prepareForReuse() { + super.prepareForReuse() + imageView.image = nil + onDelete = nil + } + + func configure(image: UIImage) { + imageView.image = image + } + + @objc private func deleteTapped() { + onDelete?() + } +} + +private final class FeedbackAddImageCell: UICollectionViewCell { + static let reuseIdentifier = "FeedbackAddImageCell" + + private let addImageView = UIImageView(image: UIImage(named: "Mine/feedback_add")) + + override init(frame: CGRect) { + super.init(frame: frame) + + contentView.backgroundColor = .white + contentView.layer.cornerRadius = 16 + addImageView.contentMode = .scaleAspectFit + contentView.addSubview(addImageView) + addImageView.layoutChain.centerX().centerY().width(48).height(48) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +}